$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
Subject: Re: [boost] Workaround for compiler bugs
From: Stephan T. Lavavej (stl_at_[hidden])
Date: 2010-12-06 19:43:45
[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