
On 12/6/2010 7:43 PM, Stephan T. Lavavej wrote:
[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)); \
I quickly played around with this a little seeing if I could remove 'decltype'. Evidently the VC++ compiler can not handle: "template<typename U> static std::true_type helper(&U::NAME);" spitting out the message of 'error C2998: 'std::tr1::true_type helper' : cannot be a template definition' instead. While 'decltype' solves that problem for expressions of the type '&T::someVariablename' in template code in VC10, VC9 has the same problem and there, as I mentioned, there is no solution which I have been able to discover since 'decltype' does not exist in VC++ prior to the latest release. So as I mentioned I can use 'decltype' in VC10 for a solution but I am still without a solution for earlier versions of VC++. BTW, without the 'decltype' in your example code I do not see why the code is not valid. Care to explain why VC++ thinks it is necessary ? I can not imagine not being able to understand '&T::someVariablename' by a C++ compiler when T is known to be a type. I will continue to look for a workaround for VC9 and earlier, as I think my library should be usable by VC9, VC8, and perhaps VC7.1. Thanks for your neat solution for VC10 !
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"); }