#include <iostream>
#include <type_traits>
#define IS_MEMBER(T1, M) \
struct { \
struct verystrangename1 { bool M; }; \
template<typename T> struct verystrangename2 : verystrangename1, public T { }; \
\
enum return_t { not_member, is_object, is_function }; \
template<typename T, typename = decltype(verystrangename2<T>::M)> constexpr return_t what_member() { return not_member; } \
template<typename T> typename std::enable_if<std::is_member_object_pointer<decltype(&T::M)>::value, return_t>::type constexpr what_member() { return is_object; } \
template<typename T> typename std::enable_if<std::is_member_function_pointer<decltype(&T::M)>::value, return_t>::type constexpr what_member() { return is_function; } \
constexpr operator return_t() { return what_member<T1>(); } \
}
struct t {
int aaa;
float bbb;
void func() {}
};
// Can't be in function
IS_MEMBER(t, aaa) is_aaa_member_of_t;
IS_MEMBER(t, ccc) is_ccc_member_of_t;
IS_MEMBER(t, func) is_func_member_of_t;
// known at compile time
enum { const_is_aaa_member_of_t = (int)is_aaa_member_of_t };
static constexpr int const_is_func_member_of_t = is_func_member_of_t;
int main() {
std::cout << std::boolalpha <<
"0 - not_member, 1 - is_object, 2 - is_function \n\n" <<
"is aaa member of t = " << is_aaa_member_of_t << std::endl <<
"is ccc member of t = " << is_ccc_member_of_t << std::endl <<
"is func member of t = " << is_func_member_of_t << std::endl <<
std::endl;
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CgojZGVmaW5lIElTX01FTUJFUihUMSwgTSkgCVwKc3RydWN0IHsJCVwKCXN0cnVjdCB2ZXJ5c3RyYW5nZW5hbWUxIHsgYm9vbCBNOyB9OyAJXAoJdGVtcGxhdGU8dHlwZW5hbWUgVD4gc3RydWN0IHZlcnlzdHJhbmdlbmFtZTIgOiB2ZXJ5c3RyYW5nZW5hbWUxLCBwdWJsaWMgVCB7IH07CVwKCVwKCWVudW0gcmV0dXJuX3QgeyBub3RfbWVtYmVyLCBpc19vYmplY3QsIGlzX2Z1bmN0aW9uIH07IFwKCXRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lID0gZGVjbHR5cGUodmVyeXN0cmFuZ2VuYW1lMjxUPjo6TSk+IGNvbnN0ZXhwciByZXR1cm5fdCB3aGF0X21lbWJlcigpIHsgcmV0dXJuIG5vdF9tZW1iZXI7ICB9IAlcCgl0ZW1wbGF0ZTx0eXBlbmFtZSBUPiB0eXBlbmFtZSBzdGQ6OmVuYWJsZV9pZjxzdGQ6OmlzX21lbWJlcl9vYmplY3RfcG9pbnRlcjxkZWNsdHlwZSgmVDo6TSk+Ojp2YWx1ZSwgcmV0dXJuX3Q+Ojp0eXBlIGNvbnN0ZXhwciB3aGF0X21lbWJlcigpIHsgcmV0dXJuIGlzX29iamVjdDsgfQlcCgl0ZW1wbGF0ZTx0eXBlbmFtZSBUPiB0eXBlbmFtZSBzdGQ6OmVuYWJsZV9pZjxzdGQ6OmlzX21lbWJlcl9mdW5jdGlvbl9wb2ludGVyPGRlY2x0eXBlKCZUOjpNKT46OnZhbHVlLCByZXR1cm5fdD46OnR5cGUgY29uc3RleHByIHdoYXRfbWVtYmVyKCkgeyByZXR1cm4gaXNfZnVuY3Rpb247IH0JXAoJY29uc3RleHByIG9wZXJhdG9yIHJldHVybl90KCkgeyByZXR1cm4gd2hhdF9tZW1iZXI8VDE+KCk7IH0JXAp9CgpzdHJ1Y3QgdCB7CglpbnQgYWFhOwoJZmxvYXQgYmJiOwoJdm9pZCBmdW5jKCkge30KfTsKCi8vIENhbid0IGJlIGluIGZ1bmN0aW9uCklTX01FTUJFUih0LCBhYWEpIGlzX2FhYV9tZW1iZXJfb2ZfdDsKSVNfTUVNQkVSKHQsIGNjYykgaXNfY2NjX21lbWJlcl9vZl90OwpJU19NRU1CRVIodCwgZnVuYykgaXNfZnVuY19tZW1iZXJfb2ZfdDsKCi8vIGtub3duIGF0IGNvbXBpbGUgdGltZQplbnVtIHsgY29uc3RfaXNfYWFhX21lbWJlcl9vZl90ID0gKGludClpc19hYWFfbWVtYmVyX29mX3QgfTsKc3RhdGljIGNvbnN0ZXhwciBpbnQgY29uc3RfaXNfZnVuY19tZW1iZXJfb2ZfdCA9IGlzX2Z1bmNfbWVtYmVyX29mX3Q7CgoKaW50IG1haW4oKSB7CgkKCXN0ZDo6Y291dCA8PCBzdGQ6OmJvb2xhbHBoYSA8PCAKCQkiMCAtIG5vdF9tZW1iZXIsIDEgLSBpc19vYmplY3QsIDIgLSBpc19mdW5jdGlvbiBcblxuIiA8PAoJCSJpcyBhYWEgbWVtYmVyIG9mIHQgPSAiIDw8IGlzX2FhYV9tZW1iZXJfb2ZfdCA8PCBzdGQ6OmVuZGwgPDwgCgkJImlzIGNjYyBtZW1iZXIgb2YgdCA9ICIgPDwgaXNfY2NjX21lbWJlcl9vZl90IDw8IHN0ZDo6ZW5kbCA8PCAKCQkiaXMgZnVuYyBtZW1iZXIgb2YgdCA9ICIgPDwgaXNfZnVuY19tZW1iZXJfb2ZfdCA8PCBzdGQ6OmVuZGwgPDwgCgkJc3RkOjplbmRsOwoKCXJldHVybiAwOwp9