fork download
  1. #include <type_traits> // To use 'std::integral_constant'.
  2. #include <iostream> // To use 'std::cout'.
  3. #include <iomanip> // To use 'std::boolalpha'.
  4.  
  5.  
  6. #define GENERATE_HAS_MEMBER(member) \
  7.   \
  8. template < class T > \
  9. class HasMember_##member \
  10. { \
  11. private: \
  12.   using Yes = char[2]; \
  13.   using No = char[1]; \
  14.   \
  15.   struct Fallback { int member; }; \
  16.   struct Derived : T, Fallback { }; \
  17.   \
  18.   template < class U > \
  19.   static No& test ( decltype(U::member)* ); \
  20.   template < typename U > \
  21.   static Yes& test ( U* ); \
  22.   \
  23. public: \
  24.   static constexpr bool RESULT = sizeof(test<Derived>(nullptr)) == sizeof(Yes); \
  25. }; \
  26.   \
  27. template < class T > \
  28. struct has_member_##member \
  29. : public std::integral_constant<bool, HasMember_##member<T>::RESULT> \
  30. { \
  31. };
  32.  
  33.  
  34. GENERATE_HAS_MEMBER(att) // Creates 'has_member_att'.
  35. GENERATE_HAS_MEMBER(func) // Creates 'has_member_func'.
  36.  
  37.  
  38. struct A
  39. {
  40. int att;
  41. void func ( double );
  42. };
  43.  
  44. struct B
  45. {
  46. char att[3];
  47. double func ( const char* );
  48. };
  49.  
  50. struct C : A, B { }; // It will also work with ambiguous members.
  51.  
  52.  
  53. int main ( )
  54. {
  55. std::cout << std::boolalpha
  56. << "\n" "'att' in 'C' : "
  57. << has_member_att<C>::value // <type_traits>-like interface.
  58. << "\n" "'func' in 'C' : "
  59. << has_member_func<C>() // Implicitly convertible to 'bool'.
  60. << "\n";
  61. }
Success #stdin #stdout 0s 3468KB
stdin
Standard input is empty
stdout
'att' in 'C' : true
'func' in 'C' : true