#include <type_traits>
struct A {
int foo;
};
struct B : A {};
struct C {
static int foo;
};
struct D : C {};
struct E {
int &foo;
};
struct F {
static int &foo;
};
struct G {};
#define IsMember(MEM) \
template <typename T> \
std::is_member_pointer<decltype(&T::MEM)> is_member_##MEM(int); \
template<typename T> \
decltype(T::MEM, std::true_type{}) is_member_##MEM(long); \
template <typename T> \
std::false_type is_member_##MEM(...); \
template <typename T> \
using IsMember_##MEM = decltype(is_member_##MEM<T>(0));
IsMember(foo);
static_assert(IsMember_foo<A>{}, "No");
static_assert(IsMember_foo<B>{}, "No");
static_assert(!IsMember_foo<C>{}, "No");
static_assert(!IsMember_foo<D>{}, "No");
static_assert(IsMember_foo<E>{}, "No");
static_assert(!IsMember_foo<F>{}, "No");
static_assert(!IsMember_foo<G>{}, "No"); // struct G { };
int main () {}
I2luY2x1ZGUgPHR5cGVfdHJhaXRzPgoKc3RydWN0IEEgewogIGludCBmb287Cn07CgpzdHJ1Y3QgQiA6IEEge307CgpzdHJ1Y3QgQyB7CiAgc3RhdGljIGludCBmb287Cn07CgpzdHJ1Y3QgRCA6IEMge307CgpzdHJ1Y3QgRSB7CiAgaW50ICZmb287Cn07CgpzdHJ1Y3QgRiB7CiAgc3RhdGljIGludCAmZm9vOwp9OwoKc3RydWN0IEcge307CgojZGVmaW5lIElzTWVtYmVyKE1FTSkgXAp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4gXApzdGQ6OmlzX21lbWJlcl9wb2ludGVyPGRlY2x0eXBlKCZUOjpNRU0pPiBpc19tZW1iZXJfIyNNRU0oaW50KTsgXAp0ZW1wbGF0ZTx0eXBlbmFtZSBUPiBcCmRlY2x0eXBlKFQ6Ok1FTSwgc3RkOjp0cnVlX3R5cGV7fSkgaXNfbWVtYmVyXyMjTUVNKGxvbmcpOyBcCnRlbXBsYXRlIDx0eXBlbmFtZSBUPiBcCnN0ZDo6ZmFsc2VfdHlwZSBpc19tZW1iZXJfIyNNRU0oLi4uKTsgXAp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4gXAp1c2luZyBJc01lbWJlcl8jI01FTSA9IGRlY2x0eXBlKGlzX21lbWJlcl8jI01FTTxUPigwKSk7CgpJc01lbWJlcihmb28pOwoKc3RhdGljX2Fzc2VydChJc01lbWJlcl9mb288QT57fSwgIk5vIik7CnN0YXRpY19hc3NlcnQoSXNNZW1iZXJfZm9vPEI+e30sICJObyIpOwpzdGF0aWNfYXNzZXJ0KCFJc01lbWJlcl9mb288Qz57fSwgIk5vIik7CnN0YXRpY19hc3NlcnQoIUlzTWVtYmVyX2ZvbzxEPnt9LCAiTm8iKTsKc3RhdGljX2Fzc2VydChJc01lbWJlcl9mb288RT57fSwgIk5vIik7CnN0YXRpY19hc3NlcnQoIUlzTWVtYmVyX2ZvbzxGPnt9LCAiTm8iKTsKc3RhdGljX2Fzc2VydCghSXNNZW1iZXJfZm9vPEc+e30sICJObyIpOyAvLyBzdHJ1Y3QgRyB7IH07CgppbnQgbWFpbiAoKSB7fQ==