#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;
}
