This is different from checking if a specific function is defined. Here, for this check to return true, the function has to be defined and passing the arguments
#define overload_set(F)\
struct { auto operator()(auto&&...args)const\
->decltype(F(std::forward(args)...))\
{ return (F(std::forward(args)...)); }\
}
this takes a token F and generates an overload set type for F.
It is not quite perfect: it only does perfect forwarding with SFINAE tests. But it is close.
We then use this:
templatestruct can_invoke:std::false_type{};
template
struct can_invoke()(std::declval()...)
))
>:std::true_type{};
Mixing them we get:
typedef overload_set(Foo) Foo_overloads;
std::cout << can_invoke::value<<"\n";
will print 1 if Foo(3,2) works. As noted, this is limited by failures of perfect forwarding.
You can also pass Foo_overloads{} to functions expecting a function object, and it will dispatch at the call site instead of doing it when you pass the function object.