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