Comment vérifier avec SFINAE si un membre existe sans connaître son type?

Dans le code pré-C ++ 11, si je recherchais une variable membre dont je ne connais pas le type, comment puis-je utiliser SFINAE pour vérifier si le membre existe?

Voici un exemple utilisant l’idiome de détecteur de membre que vous avez demandé:

template struct has_x { typedef char(&yes)[1]; typedef char(&no)[2]; // this creates an ambiguous &Derived::x if T has got member x struct Fallback { char x; }; struct Derived : T, Fallback { }; template struct Check; template static no test(Check*); template static yes test(...); static const bool value = sizeof(test(0)) == sizeof(yes); }; #include  struct A { private: int x; }; // works with private, too struct B { const char x; }; struct C { void x() volatile ; }; struct D : A { }; struct E {}; struct F : A, B {}; // note that &F::x is ambiguous, but // the test with has_x will still succeed int main() { std::cout << has_x::value // 1 << has_x::value // 1 << has_x::value // 1 << has_x::value // 1 << has_x::value // 0 << has_x::value; // 1 } 

Test en direct.

Cela devrait également fonctionner avec MSVC.

Voici une solution que j’ai vérifiée pour les versions les plus récentes de GCC et de Clang, ainsi que pour les versions les plus récentes et les plus anciennes de Visual C ++:

 #if defined(_MSC_VER) && _MSC_VER < 1400 #define GEN_MEMBER_CHECKER(Prefix, Member) \ template 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 struct Prefix##Member; \ template struct Prefix##Member : Prefix##Member { }; \ template struct Prefix##Member : Prefix##Member { }; \ template struct Prefix##Member : Prefix##Member { }; \ template struct Prefix##Member : Prefix##Member { }; \ template struct Prefix##Member { enum { value = 0 }; }; \ template<> struct Prefix##Member \ { \ private: \ template static unsigned char (&test(int, T const &))[1U + 1U]; \ static unsigned char (&test(int, ...))[1U]; \ public: \ template \ static unsigned char (&check(int, Prefix##Member *))[1U + sizeof(test(0, &T::Member))]; \ static unsigned char (&check(int, ...))[1U]; \ }; \ template struct Prefix##Member \ { enum { value = sizeof(Prefix##Member::check(0, (Prefix##Member *)0)) > 2U }; } #endif 

Exemple:

 #include  GEN_MEMBER_CHECKER(member_check_, Member); struct HasMember { int Member; }; struct DoesntHaveMember { }; int main() { printf("%u %u\n", member_check_Member::value, member_check_Member::value); } 

Sortie:

 1 0