I am trying to implement my own is_member_function_pointer
and I\'m having trouble with it.
namespace __implementation
{
// integral_constan
Alternatively
template<typename T> struct remove_c { typedef T type; };
template<typename T> struct remove_c<T const> { typedef T type; };
template<bool C>
struct bool_ { static bool const value = C; };
template<typename T, typename U>
struct is_same : bool_<false> {};
template<typename T>
struct is_same<T, T> : bool_<true> { };
template<typename T, typename = bool_<true> >
struct is_function : bool_<false> {};
struct C { };
template<typename T>
struct is_function< T,
bool_<is_same<typename remove_c<T>::type const C::*,
typename remove_c<T>::type C::*>::value> >
: bool_<true> {};
template<typename T>
struct is_member_function_pointer_impl : bool_<false> {};
template<typename T, typename C>
struct is_member_function_pointer_impl<T C::* const volatile>
: is_function<T> {};
template<typename T>
struct is_member_function_pointer
: is_member_function_pointer_impl<T const volatile> {};
A very short talk on Chat has brought this easy solution:
// is_member_function_pointer
template<typename T> struct is_member_function_pointer : public false_type {};
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...)> : public true_type {};
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...) const> : public true_type {};
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...) volatile> : public true_type {};
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...) const volatile> : public true_type {};
Which includes specializations for volatile
as well.
EDIT as @Xeo and @Johannes pointed out, I missed the ref-qualifier (aka rvalue for *this) versions:
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...) &> : public true_type {};
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...) const &> : public true_type {};
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...) volatile &> : public true_type {};
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...) const volatile &> : public true_type {};
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...) &&> : public true_type {};
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...) const &&> : public true_type {};
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...) volatile &&> : public true_type {};
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...) const volatile &&> : public true_type {};
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...,...)> : public true_type {};
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...,...) const> : public true_type {};
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...,...) volatile> : public true_type {};
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...,...) const volatile> : public true_type {};
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...,...) &> : public true_type {};
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...,...) const &> : public true_type {};
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...,...) volatile &> : public true_type {};
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...,...) const volatile &> : public true_type {};
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...,...) &&> : public true_type {};
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...,...) const &&> : public true_type {};
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...,...) volatile &&> : public true_type {};
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...,...) const volatile &&> : public true_type {};
Which is still quite doable. It's clearer then crazy template magic and numerous helper templates IMHO.
EDIT2 to clarify, the above are all in an implementation namespace and wrapped around by
template<typename T> constexpr bool
is_member_function_pointer() { return __implementation::is_member_function_pointer<remove_cv<T>>::result; }
Where remove_cv
is alias template'd to the convenient
template<typenamen T> using
remove_cv = typename __implementation::remove_cv<T>::type;
I suppose there are other, and maybe better ways, but this one is at least clear to the reader without any further SFINAE tricks like applied in libc++ or libstdc++, IMHO.