Other ways to check if a class has a specific member function

Let me check if

struct Thing { int foo(double, bool) {return 0;} }; 

has a member function int foo(double, bool) at compile time. There are many ways to do this, and most of them are just variations of others. Can someone think of how much different (or at least creative enough) than the 5 ways that I mention here? I'm just trying to learn some new methods with templates and SFINAE.

 #include <iostream> #include <type_traits> // Using void_t (this includes using std::is_detected). template <typename T> using void_t = void; template <typename T, typename = void> struct has_foo : std::false_type {}; template <typename T> struct has_foo<T, void_t<decltype(static_cast<int>(std::declval<T>().foo(double{}, bool{})))> > : std::true_type {}; // Using the ... default argument. template <typename T> struct hasfoo { template <typename U> static std::true_type test (decltype(static_cast<int(T::*)(double, bool)>(&T::foo))*); // or 'decltype(static_cast<int>(std::declval<U>().foo(double{}, bool{})))*' works fine too. template <typename> static std::false_type test (...); static constexpr bool value = decltype(test<T>(nullptr))::value; }; // Overloads and trailing return types. template <typename> struct Helper : std::true_type {}; template <typename T> auto helper(int) -> Helper<decltype(static_cast<int>(std::declval<T>().foo(double{}, bool{})))>; template <typename> std::false_type helper(long); template <typename T> constexpr bool hasFoo() {return decltype(helper<T>(0))::value;} // Comma operator (basically the same as the above). template <typename T> auto check(int) -> decltype(static_cast<int>(std::declval<T>().foo(double{}, bool{})), std::true_type{}); template <typename T> std::false_type check(...); template <typename T> using HasFoo = decltype(check<T>(0)); // Member function pointer template parameter. template <typename T> struct Hasfoo { template <typename U, int(U::*)(double, bool)> struct Tag; template <typename U> static constexpr bool test (Tag<U, &U::foo>*) {return true;} template <typename> static constexpr bool test (...) {return false;} static constexpr bool value = test<T>(nullptr); }; // Tests struct Thing { int foo(double, bool) {return 0;} }; int main() { static_assert (has_foo<Thing>::value, ""); static_assert (hasfoo<Thing>::value, ""); static_assert (hasFoo<Thing>(), ""); static_assert (HasFoo<Thing>::value, ""); } 

Edit: I just remembered the elegant and more general solution that Jakk gave to another question quite recently (here is his actual typing, modified only to match the foo function):

 namespace meta { namespace details { template<template<class...>class Z, class=void, class...Ts> struct can_apply : std::false_type {}; template<template<class...>class Z, class...Ts> struct can_apply<Z, decltype((void)(std::declval<Z<Ts...>>())), Ts...>: std::true_type {}; } template<template<class...>class Z, class...Ts> using can_apply = details::can_apply<Z,void,Ts...>; } template<class T> using member_foo = decltype(static_cast<int(T::*)(double, bool)>(&T::foo)); template<class T> using has_member_foo = meta::can_apply<member_foo, T>; 
+7
c ++ c ++ 11 templates sfinae
source share
5 answers

Can anyone think about how much different (or at least quite creative) than the 5 ways that I mention here?

A rather creative way to do this may be lower.
It is based on the sizeof operator and the trivial declaration of use (here called Type ).
SFINAE and partial template specialization do the rest.

This follows a minimal working example:

 #include<type_traits> #include<cstddef> template<typename T, std::size_t> using Type = T; template<typename T, typename = T> struct U: std::false_type {}; template<typename T> struct U<T, Type<T, sizeof(static_cast<void(T::*)(int)>(&T::f))>>: std::true_type {}; struct S { void f(int) {} }; struct R { int f(double) { return 42; } }; struct T {}; int main() { static_assert(U<S>::value, "!"); static_assert(not U<R>::value, "!"); static_assert(not U<T>::value, "!"); } 
+1
source share

Can anyone think about how much different (or at least quite creative) than the 5 ways that I mention here?

A rather creative way to do this may be lower.
It is based on the noexcept operator and the trivial declaration of use (here called Type ).
SFINAE and partial template specialization do the rest.

This follows a minimal working example:

 #include<type_traits> #include<utility> template<typename T, bool> using Type = T; template<typename T, typename = T> struct U: std::false_type {}; template<typename T> struct U<T, Type<T, noexcept(std::declval<T>().f(42))>>: std::true_type {}; struct S { void f(int) {} }; struct T {}; int main() { static_assert(U<S>::value, "!"); static_assert(not U<T>::value, "!"); } 

This solution has a problem when compared with others.
For example, the structure below will also test:

 struct R { int f(double) {} }; 

In other words, as long as the function under test takes one argument to the type that can be supplied 42, and regardless of the return type, it is accepted.

+1
source share

Can anyone think about how much different (or at least quite creative) than the 5 ways that I mention here?

A rather creative way to do this may be lower.
It does not use any invaluable context. Instead, it relies on the trivial use of declarations (called Type here) and that’s all.
SFINAE and partial template specialization do the rest.

This follows a minimal working example:

 #include<type_traits> template<typename T, void(T::*)(int)> using Type = T; template<typename T, typename = T> struct U: std::false_type {}; template<typename T> struct U<T, Type<T, &T::f>>: std::true_type {}; struct S { void f(int) {} }; struct R { int f(double) { return 42; } }; struct T {}; int main() { static_assert(U<S>::value, "!"); static_assert(not U<R>::value, "!"); static_assert(not U<T>::value, "!"); } 
+1
source share

Can anyone think about how much different (or at least quite creative) than the 5 ways that I mention here?

A rather creative way to do this may be lower.
It is based on function template and overload. If you know how label dispatch works, this should be pretty easy to understand.

This follows a minimal working example:

 #include<type_traits> #include<cstddef> template<typename T, void(T::*)(int) = &T::f> constexpr std::true_type f(int) { return {}; } template<typename T> constexpr std::false_type f(char) { return {}; } template<typename T> constexpr auto detect() { return f<T>(0); } struct S { void f(int) {} }; struct R { int f(double) { return 42; } }; struct T {}; int main() { static_assert(detect<S>(), "!"); static_assert(not detect<R>(), "!"); static_assert(not detect<T>(), "!"); } 
+1
source share

Can anyone think about how much different (or at least quite creative) than the 5 ways that I mention here?

If you can use C ++ 14, another way to check if a class has a member variable is by using template variables.
As an example:

 template<typename T, typename = void> constexpr bool has_foo = false; template<typename T> constexpr bool has_foo<T, decltype(std::declval<T>().foo(), void())> = true; 

I assume that this is perhaps one of the most compact solutions.

This follows a minimal working example:

 #include<utility> template<typename T, typename = void> constexpr bool has_f = false; template<typename T> constexpr bool has_f<T, decltype(std::declval<T>().f(0), void())> = true; struct S { void f(int) {} }; struct T {}; int main() { static_assert(has_f<S>, "!"); static_assert(not has_f<T>, "!"); } 
0
source share

All Articles