Consider this simple example code:
#include
#include
void f(bool _switch) {
std::cout << \"Nothing really\" &l
namespace details{
template
struct invoke {};
template
struct invoke()(std::declval()...)
))>{
using type=decltype(std::declval()(std::declval()...));
};
}
templatestruct invoke:details::invoke{};
template
struct invoke_test:std::false_type {};
template
struct invoke_test::type,
R
>::value
>::type
>:std::true_type {};
template
struct invoke_test::type ) )
>:std::true_type{};
template
constexpr bool invokable() {
return invoke_test::value;
}
this gives us a pseudo-concept invokable.
We can then use it like:
template
typename std::enable_if()>::type
f(F&&){
std::cout << "can be invoked\n";
}
void f(bool) {
std::cout << "is bool\n";
}
and bob is your uncle.
The real problem is that std::function 's constructor does not do a similar test, and instead claims (falsely) that it can be constructed from anything at all. This is a flaw in the standard, one I suspect will be fixed once concepts are standardized.