Lets say I have
struct foo {
void ham() {}
void ham() const {}
};
struct bar {
void ham() {}
};
Assuming I have a templated fu
SFINAE over and over again. Here is another option which is unspecified about the return types but lets you specify the arguments.
(For comparison: the approach by @Jarod42 checks the exact signature, return type + arguments, the other void_t
expression sfinae stuff up to now checks only whether ham()
can be called.)
Plus, it works with the current MSVC 2015 Update 1 version (unlike the usual void_t
stuff).
template
struct is_callable_impl
{
template static constexpr auto test(int) -> decltype(std::declval().ham(std::declval() ...), bool{}) { return true; }
template static constexpr auto test(...) { return false; }
static constexpr bool value = test(int{});
using type = std::integral_constant;
};
template
using is_callable = typename is_callable_impl::type;
Use it as
struct foo
{
void ham() {}
void ham() const {}
int ham(int) const {}
};
int main()
{
std::cout
<::value //true
<::value //true
<::value //true
<::value //also true, double is converted to int
<::value //false, can't call foo::ham(std::string) const
<
Demo on Coliru
For the "newest" sfinae stuff, however, I suggest you have a look at boost.hana.