#include <type_traits>
//User types
struct field_t{};
struct other_t{};
struct StructA{field_t field;};
struct StructB{other_t other;};
struct StructC:public StructA{};
struct StructD:public StructB{};
struct StructT{other_t field;field_t other;};
//Implementation detail
template<typename T,typename FIELD_T>
struct type_has_field{
struct ok_type{char padding[1];};
struct no_type{char padding[8];};
template<class U>
struct has_field{
struct Fallback{int field;};
struct Derived:U,Fallback{};
template<typename C, C> struct ChT;
template<typename C> static no_type f(ChT<int Fallback::*,&C::field>(*)=nullptr);
template<typename C> static ok_type f(...);
static const bool value=sizeof(ok_type)==sizeof(f<Derived>(0));
};
struct FalseStruct{
template<class U>struct next{typedef FalseStruct type;};
static const bool value=false;
};
struct TrueStruct{
static const bool value=true;
};
struct NextStruct1{
template<class U>
struct next{
static const bool flag=(
std::is_same<
FIELD_T,
decltype((*(U*)nullptr).field)
>::value
);
typedef typename std::conditional<
flag,
TrueStruct,FalseStruct
> type_expr;
typedef typename type_expr::type type;
};
};
struct NextStruct0{
template<class U>
struct next{
static const bool flag=(
has_field<U>::value
);
typedef typename std::conditional<
flag,
NextStruct1,FalseStruct
> type_expr;
typedef typename type_expr::type type;
};
};
typedef typename std::conditional<
std::is_class<T>::value,
NextStruct0,FalseStruct
> type_expr0;
typedef typename type_expr0::type type_expr1;
typedef typename type_expr1::template next<T> type_expr2;
typedef typename type_expr2::type type_expr3;
typedef typename type_expr3::template next<T> type_expr4;
typedef typename type_expr4::type type_expr5;
static const bool value=type_expr5::value;
};
//Experiment
static_assert(
false==type_has_field<float,field_t>::value,
"field_t float::field - should not exist"
);
static_assert(
false==type_has_field<char,field_t>::value,
"field_t char::field - should not exist"
);
static_assert(
true==type_has_field<StructA,field_t>::value,
"field_t StructA::field - should exist"
);
static_assert(
false==type_has_field<StructB,field_t>::value,
"field_t StructB::field - should not exist"
);
static_assert(
true==type_has_field<StructC,field_t>::value,
"field_t StructC::field - should exist"
);
static_assert(
false==type_has_field<StructD,field_t>::value,
"field_t StructD::field - should not exist"
);
static_assert(
false==type_has_field<StructT,field_t>::value,
"field_t StructT::field - should not exist"
);
static_assert(
true==type_has_field<StructT,other_t>::value,
"other_t StructT::field - should exist"
);
int main(){return 0;}