
[Edward Diener]
You missed the fact in the attachment that the T passed in must be the full signature of a pointer to data member, as in 'Gipf Dvonn::*' in your first example below.
I wasn't sure if mentioning the data member's type was a desired feature of your code. Here's how to achieve that: C:\Temp>type meow.cpp #include <type_traits> #define DEFINE_HAS_MEMBER_OF_TYPE(NAME) \ template <typename T> class has_member_ ## NAME { \ private: \ template <typename U> static std::true_type helper(decltype(&U::NAME)); \ template <typename U> static std::false_type helper(...); \ public: \ typedef decltype(helper<T>(nullptr)) type; \ static const bool value = type::value; \ }; \ \ template <typename T, typename X, bool B> \ struct has_member_ ## NAME ## _of_type_helper \ : public std::false_type { }; \ \ template <typename T, typename X> \ struct has_member_ ## NAME ## _of_type_helper<T, X, true> \ : public std::is_same<decltype(&T::NAME), X T::*> { }; \ \ template <typename T, typename X> \ struct has_member_ ## NAME ## _of_type \ : public has_member_ ## NAME ## _of_type_helper< \ T, X, has_member_ ## NAME<T>::value> { }; DEFINE_HAS_MEMBER_OF_TYPE(cMem) struct Gipf { }; struct Dvonn { Gipf cMem; }; struct Tzaar { int cMem; }; struct Yinsh { int Zertz; }; int main() { static_assert( has_member_cMem_of_type<Dvonn, Gipf>::value, "one"); static_assert(!has_member_cMem_of_type<Dvonn, int>::value, "two"); static_assert(!has_member_cMem_of_type<Tzaar, Gipf>::value, "three"); static_assert( has_member_cMem_of_type<Tzaar, int>::value, "four"); static_assert(!has_member_cMem_of_type<Yinsh, Gipf>::value, "five"); static_assert(!has_member_cMem_of_type<Yinsh, int>::value, "six"); } C:\Temp>cl /EHsc /nologo /W4 meow.cpp meow.cpp C:\Temp> Note that these macros do not attempt to avoid the formation of Standard-forbidden double underscores when given data member names with leading or trailing underscores. (Conveniently, I hate such names.) STL