is_member_function_pointer implementation

邮差的信 提交于 2019-12-01 10:44:48

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.

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> {};
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!