fork download
  1. #include <iostream>
  2. #include <type_traits>
  3.  
  4. using namespace std;
  5.  
  6.  
  7. #define DETECTED_MEMBER(member_name) \
  8. template<typename C, typename T>class has_##member_name \
  9. { \
  10.   template<class U> static constexpr auto Check(U*) -> typename \
  11.   std::is_same< decltype( std::declval<U>().member_name), T >::type; \
  12.   \
  13.   template<typename> static constexpr std::false_type Check(...); \
  14.   typedef decltype(Check<C>(0)) Result; \
  15. public: \
  16.   enum { eIS_NOCONST = 0 }; \
  17.   enum { eIS_CONST = 0 }; \
  18.   enum { eIS_AVAILABLE = Result::value }; \
  19. }; \
  20. template<class C,typename R, typename... Args>class has_##member_name<C, R(Args...)> \
  21. { \
  22.   typedef R(C::*Method)(Args...); typedef R(C::*CMethod)(Args...)const; \
  23.   template <class U> using NoConst = decltype(static_cast<Method> (&U::member_name)); \
  24.   template <class U> using Const = decltype(static_cast<CMethod>(&U::member_name)); \
  25.   \
  26.   template<class U> static constexpr std::true_type CheckNoConst( NoConst<U>*p ); \
  27.   template<class> static constexpr std::false_type CheckNoConst(...); \
  28.   typedef decltype(CheckNoConst<C>(0)) NoConstResult; \
  29.   \
  30.   template<class U> static constexpr std::true_type CheckConst( Const<U>*p); \
  31.   template<class> static constexpr std::false_type CheckConst(...); \
  32.   typedef decltype(CheckConst<C>(0)) ConstResult; \
  33. public: \
  34.   enum { eIS_NOCONST = NoConstResult::value }; \
  35.   enum { eIS_CONST = ConstResult::value }; \
  36.   enum { eIS_AVAILABLE = eIS_NOCONST | eIS_CONST }; \
  37. };
  38.  
  39. #define is_available(class_name, member_type, member_name) has_##member_name<class_name, member_type>::eIS_AVAILABLE
  40. #define is_available_method(class_name, member_type, member_name) has_##member_name<class_name, member_type>::eIS_NOCONST
  41. #define is_available_cmethod(class_name, member_type, member_name) has_##member_name<class_name, member_type>::eIS_CONST
  42.  
  43. //------------------------------------------------------------------------------------
  44.  
  45.  
  46. int g;
  47. struct A
  48. {
  49. A():r(g){}
  50.  
  51. void fooA(int);
  52. void fooA(int)const;
  53. void fooA();
  54. void fooA()const;
  55.  
  56. int v;
  57. int& r;
  58. int a[10];
  59. int* p;
  60. int** pp;
  61. private:
  62. void private_foo();
  63. };
  64.  
  65. struct B : A
  66. {
  67. int v;
  68. int fooB(){ return 0; }
  69. };
  70.  
  71.  
  72. DETECTED_MEMBER(fooA);
  73. DETECTED_MEMBER(fooB);
  74. DETECTED_MEMBER(v);
  75. DETECTED_MEMBER(r);
  76. DETECTED_MEMBER(a);
  77. DETECTED_MEMBER(p);
  78. DETECTED_MEMBER(pp);
  79.  
  80. DETECTED_MEMBER(private_foo);
  81.  
  82.  
  83. int main()
  84. {
  85. //синтаксис: is_available( имя_класса , тип_мембера , имя_мембера)
  86.  
  87. //вернет true если мембер доступен, иначе - false
  88.  
  89. //---- детектирование данных
  90. cout<< "is available int B.v ? "
  91. << is_available(B,int,v) <<endl;
  92.  
  93. cout<< "is available int& B.r ? "
  94. << is_available(B,int&,r) <<endl;
  95.  
  96. cout<< "is available int B.a[10] ? "
  97. << is_available(B,int[10],a) <<endl;
  98.  
  99. cout<< "is available int* B.p ? "
  100. << is_available(B,int*,p) <<endl;
  101.  
  102. cout<< "is available int* B.pp ? "
  103. << is_available(B,int**,pp) <<endl;
  104.  
  105. //---- детектирование методов
  106. cout<< "is available void B.fooA(int) or void B::fooA(int)const ? "
  107. <<is_available(B,void(int),fooA) <<endl;
  108.  
  109. cout<< "is available void B.fooA(int) ? "
  110. << is_available_method(B,void(int),fooA) <<endl;
  111.  
  112. cout<< "is available void B.fooA(int)const ? "
  113. << is_available_cmethod(B,void(int),fooA) <<endl;
  114.  
  115. cout<< "is available int B.fooB() ? "
  116. << is_available_method(B,int(),fooB) <<endl;
  117.  
  118. cout<< "is available void B.private_foo() ? "
  119. << is_available(B,void(),private_foo) <<endl;
  120. }
  121.  
  122.  
  123.  
Success #stdin #stdout 0s 3340KB
stdin
Standard input is empty
stdout
is available int B.v ? 1
is available int& B.r ? 1
is available int B.a[10] ? 1
is available int* B.p ? 1
is available int* B.pp ? 1
is available void B.fooA(int) or void B::fooA(int)const ? 1
is available void B.fooA(int) ? 1
is available void B.fooA(int)const ? 1
is available int B.fooB() ? 1
is available void B.private_foo() ? 0