#include <cstdint>
#include <type_traits>
#define DEFINE_HAS_MEMBER(traitsName, memberName) \
template <typename U> \
class traitsName \
{ \
private: \
struct Fallback { int memberName; }; \
struct Dummy {}; \
template<typename T, bool is_a_class = std::is_class<T>::value> \
struct identity_for_class_or_dummy { using type = Dummy; }; \
template<typename T> \
struct identity_for_class_or_dummy<T, true> { using type = T; }; \
\
template <typename Base> \
struct Derived : Base, Fallback {}; \
template<typename T, T> struct helper; \
template<typename T> \
static std::uint8_t \
check(helper<int (Fallback::*), \
&Derived<typename identity_for_class_or_dummy<T>::type>::memberName>*); \
template<typename T> static std::uint16_t check(...); \
public: \
static \
constexpr bool value = sizeof(check<U>(0)) == sizeof(std::uint16_t); \
}
DEFINE_HAS_MEMBER(has_foo, foo);
class C{ public: char foo; };
class D : public C {};
class E {};
static_assert(has_foo<C>::value, "");
static_assert(has_foo<D>::value, "");
static_assert(!has_foo<E>::value, "");
static_assert(!has_foo<int>::value, "");
int main()
{
return 0;
}
I2luY2x1ZGUgPGNzdGRpbnQ+CiNpbmNsdWRlIDx0eXBlX3RyYWl0cz4KCiNkZWZpbmUgREVGSU5FX0hBU19NRU1CRVIodHJhaXRzTmFtZSwgbWVtYmVyTmFtZSkgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBVPiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgY2xhc3MgdHJhaXRzTmFtZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgICB7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKICAgIHByaXZhdGU6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgICAgIHN0cnVjdCBGYWxsYmFjayB7IGludCBtZW1iZXJOYW1lOyB9OyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgICAgICAgc3RydWN0IER1bW15IHt9OyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKICAgICAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBULCBib29sIGlzX2FfY2xhc3MgPSBzdGQ6OmlzX2NsYXNzPFQ+Ojp2YWx1ZT4gICAgICAgXAogICAgICAgIHN0cnVjdCBpZGVudGl0eV9mb3JfY2xhc3Nfb3JfZHVtbXkgeyB1c2luZyB0eXBlID0gRHVtbXk7IH07ICAgICAgICAgICBcCiAgICAgICAgdGVtcGxhdGU8dHlwZW5hbWUgVD4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKICAgICAgICBzdHJ1Y3QgaWRlbnRpdHlfZm9yX2NsYXNzX29yX2R1bW15PFQsIHRydWU+IHsgdXNpbmcgdHlwZSA9IFQ7IH07ICAgICAgXAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgICAgICAgdGVtcGxhdGUgPHR5cGVuYW1lIEJhc2U+ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKICAgICAgICBzdHJ1Y3QgRGVyaXZlZCA6IEJhc2UsIEZhbGxiYWNrIHt9OyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgICAgIHRlbXBsYXRlPHR5cGVuYW1lIFQsIFQ+IHN0cnVjdCBoZWxwZXI7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgICAgICAgdGVtcGxhdGU8dHlwZW5hbWUgVD4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKICAgICAgICBzdGF0aWMgc3RkOjp1aW50OF90ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgICAgIGNoZWNrKGhlbHBlcjxpbnQgKEZhbGxiYWNrOjoqKSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgICAgICAgICAgICAgJkRlcml2ZWQ8dHlwZW5hbWUgaWRlbnRpdHlfZm9yX2NsYXNzX29yX2R1bW15PFQ+Ojp0eXBlPjo6bWVtYmVyTmFtZT4qKTsgXAogICAgICAgIHRlbXBsYXRlPHR5cGVuYW1lIFQ+IHN0YXRpYyBzdGQ6OnVpbnQxNl90IGNoZWNrKC4uLik7ICAgICAgICAgICAgICAgICBcCiAgICBwdWJsaWM6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKICAgICAgICBzdGF0aWMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgICAgIGNvbnN0ZXhwciBib29sIHZhbHVlID0gc2l6ZW9mKGNoZWNrPFU+KDApKSA9PSBzaXplb2Yoc3RkOjp1aW50MTZfdCk7ICBcCiAgICB9CgpERUZJTkVfSEFTX01FTUJFUihoYXNfZm9vLCBmb28pOwoKY2xhc3MgQ3sgcHVibGljOiBjaGFyIGZvbzsgfTsKY2xhc3MgRCA6IHB1YmxpYyBDIHt9OwpjbGFzcyBFIHt9OwoKc3RhdGljX2Fzc2VydChoYXNfZm9vPEM+Ojp2YWx1ZSwgIiIpOwpzdGF0aWNfYXNzZXJ0KGhhc19mb288RD46OnZhbHVlLCAiIik7CnN0YXRpY19hc3NlcnQoIWhhc19mb288RT46OnZhbHVlLCAiIik7CnN0YXRpY19hc3NlcnQoIWhhc19mb288aW50Pjo6dmFsdWUsICIiKTsKCmludCBtYWluKCkKewoJcmV0dXJuIDA7Cn0K