Here is the solution I tested on newer versions of GCC and Clang, as well as on later and older versions of Visual C ++:
#if defined(_MSC_VER) && _MSC_VER < 1400
#define GEN_MEMBER_CHECKER(Prefix, Member) \
template<class T> struct Prefix##Member \
{ enum { __if_not_exists(T::Member) { value = 0 } __if_exists(T::Member) { value = 1 } }; };
#else
#define GEN_MEMBER_CHECKER(Prefix, Member) \
template<class T> struct Prefix##Member; \
template<class T> struct Prefix##Member<T const> : Prefix##Member<T> { }; \
template<class T> struct Prefix##Member<T volatile> : Prefix##Member<T> { }; \
template<class T> struct Prefix##Member<T volatile const> : Prefix##Member<T> { }; \
template<class T> struct Prefix##Member<T &> : Prefix##Member<T> { }; \
template<class T> struct Prefix##Member<T *> { enum { value = 0 }; }; \
template<> struct Prefix##Member<void> \
{ \
private: \
template<class T> static unsigned char (&test(int, T const &))[1U + 1U]; \
static unsigned char (&test(int, ...))[1U]; \
public: \
template<class T> \
static unsigned char (&check(int, Prefix##Member<T> *))[1U + sizeof(test(0, &T::Member))]; \
static unsigned char (&check(int, ...))[1U]; \
}; \
template<class T> struct Prefix##Member \
{ enum { value = sizeof(Prefix##Member<void>::check(0, (Prefix##Member *)0)) > 2U }; }
#endif
Example:
#include <stdio.h>
GEN_MEMBER_CHECKER(member_check_, Member);
struct HasMember { int Member; };
struct DoesntHaveMember { };
int main()
{
printf("%u %u\n",
member_check_Member<HasMember>::value,
member_check_Member<DoesntHaveMember>::value);
}
Output:
1 0
source
share