fork download
  1. #include <type_traits>
  2. //User types
  3. struct field_t{};
  4. struct other_t{};
  5. struct StructA{field_t field;};
  6. struct StructB{other_t other;};
  7. struct StructC:public StructA{};
  8. struct StructD:public StructB{};
  9. struct StructT{other_t field;field_t other;};
  10. //Implementation detail
  11. template<typename T,typename FIELD_T>
  12. struct type_has_field{
  13. struct ok_type{char padding[1];};
  14. struct no_type{char padding[8];};
  15. template<class U>
  16. struct has_field{
  17. struct Fallback{int field;};
  18. struct Derived:U,Fallback{};
  19. template<typename C, C> struct ChT;
  20. template<typename C> static no_type f(ChT<int Fallback::*,&C::field>(*)=nullptr);
  21. template<typename C> static ok_type f(...);
  22. static const bool value=sizeof(ok_type)==sizeof(f<Derived>(0));
  23. };
  24. struct FalseStruct{
  25. template<class U>struct next{typedef FalseStruct type;};
  26. static const bool value=false;
  27. };
  28. struct TrueStruct{
  29. static const bool value=true;
  30. };
  31. struct NextStruct1{
  32. template<class U>
  33. struct next{
  34. static const bool flag=(
  35. std::is_same<
  36. FIELD_T,
  37. decltype((*(U*)nullptr).field)
  38. >::value
  39. );
  40. typedef typename std::conditional<
  41. flag,
  42. TrueStruct,FalseStruct
  43. > type_expr;
  44. typedef typename type_expr::type type;
  45. };
  46. };
  47. struct NextStruct0{
  48. template<class U>
  49. struct next{
  50. static const bool flag=(
  51. has_field<U>::value
  52. );
  53. typedef typename std::conditional<
  54. flag,
  55. NextStruct1,FalseStruct
  56. > type_expr;
  57. typedef typename type_expr::type type;
  58. };
  59. };
  60. typedef typename std::conditional<
  61. std::is_class<T>::value,
  62. NextStruct0,FalseStruct
  63. > type_expr0;
  64. typedef typename type_expr0::type type_expr1;
  65. typedef typename type_expr1::template next<T> type_expr2;
  66. typedef typename type_expr2::type type_expr3;
  67. typedef typename type_expr3::template next<T> type_expr4;
  68. typedef typename type_expr4::type type_expr5;
  69. static const bool value=type_expr5::value;
  70. };
  71. //Experiment
  72. static_assert(
  73. false==type_has_field<float,field_t>::value,
  74. "field_t float::field - should not exist"
  75. );
  76. static_assert(
  77. false==type_has_field<char,field_t>::value,
  78. "field_t char::field - should not exist"
  79. );
  80. static_assert(
  81. true==type_has_field<StructA,field_t>::value,
  82. "field_t StructA::field - should exist"
  83. );
  84. static_assert(
  85. false==type_has_field<StructB,field_t>::value,
  86. "field_t StructB::field - should not exist"
  87. );
  88. static_assert(
  89. true==type_has_field<StructC,field_t>::value,
  90. "field_t StructC::field - should exist"
  91. );
  92. static_assert(
  93. false==type_has_field<StructD,field_t>::value,
  94. "field_t StructD::field - should not exist"
  95. );
  96. static_assert(
  97. false==type_has_field<StructT,field_t>::value,
  98. "field_t StructT::field - should not exist"
  99. );
  100. static_assert(
  101. true==type_has_field<StructT,other_t>::value,
  102. "other_t StructT::field - should exist"
  103. );
  104. int main(){return 0;}
Success #stdin #stdout 0s 3336KB
stdin
Standard input is empty
stdout
Standard output is empty