#include <iostream>
#include <type_traits>
using namespace std;
#define DETECTED_MEMBER(member_name) \
template<typename C, typename T>class has_##member_name \
{ \
template<class U> static constexpr auto Check(U*) -> typename \
std::is_same< decltype( std::declval<U>().member_name), T >::type; \
\
template<typename> static constexpr std::false_type Check(...); \
typedef decltype(Check<C>(0)) Result; \
public: \
enum { eIS_NOCONST = 0 }; \
enum { eIS_CONST = 0 }; \
enum { eIS_AVAILABLE = Result::value }; \
}; \
template<class C,typename R, typename... Args>class has_##member_name<C, R(Args...)> \
{ \
typedef R(C::*Method)(Args...); typedef R(C::*CMethod)(Args...)const; \
template <class U> using NoConst = decltype(static_cast<Method> (&U::member_name)); \
template <class U> using Const = decltype(static_cast<CMethod>(&U::member_name)); \
\
template<class U> static constexpr std::true_type CheckNoConst( NoConst<U>*p ); \
template<class> static constexpr std::false_type CheckNoConst(...); \
typedef decltype(CheckNoConst<C>(0)) NoConstResult; \
\
template<class U> static constexpr std::true_type CheckConst( Const<U>*p); \
template<class> static constexpr std::false_type CheckConst(...); \
typedef decltype(CheckConst<C>(0)) ConstResult; \
public: \
enum { eIS_NOCONST = NoConstResult::value }; \
enum { eIS_CONST = ConstResult::value }; \
enum { eIS_AVAILABLE = eIS_NOCONST | eIS_CONST }; \
};
#define is_available(class_name, member_type, member_name) has_##member_name<class_name, member_type>::eIS_AVAILABLE
#define is_available_method(class_name, member_type, member_name) has_##member_name<class_name, member_type>::eIS_NOCONST
#define is_available_cmethod(class_name, member_type, member_name) has_##member_name<class_name, member_type>::eIS_CONST
//------------------------------------------------------------------------------------
int g;
struct A
{
A():r(g){}
void fooA(int);
void fooA(int)const;
void fooA();
void fooA()const;
int v;
int& r;
int a[10];
int* p;
int** pp;
private:
void private_foo();
};
struct B : A
{
int v;
int fooB(){ return 0; }
};
DETECTED_MEMBER(fooA);
DETECTED_MEMBER(fooB);
DETECTED_MEMBER(v);
DETECTED_MEMBER(r);
DETECTED_MEMBER(a);
DETECTED_MEMBER(p);
DETECTED_MEMBER(pp);
DETECTED_MEMBER(private_foo);
int main()
{
//синтаксис: is_available( имя_класса , тип_мембера , имя_мембера)
//вернет true если мембер доступен, иначе - false
//---- детектирование данных
cout<< "is available int B.v ? "
<< is_available(B,int,v) <<endl;
cout<< "is available int& B.r ? "
<< is_available(B,int&,r) <<endl;
cout<< "is available int B.a[10] ? "
<< is_available(B,int[10],a) <<endl;
cout<< "is available int* B.p ? "
<< is_available(B,int*,p) <<endl;
cout<< "is available int* B.pp ? "
<< is_available(B,int**,pp) <<endl;
//---- детектирование методов
cout<< "is available void B.fooA(int) or void B::fooA(int)const ? "
<<is_available(B,void(int),fooA) <<endl;
cout<< "is available void B.fooA(int) ? "
<< is_available_method(B,void(int),fooA) <<endl;
cout<< "is available void B.fooA(int)const ? "
<< is_available_cmethod(B,void(int),fooA) <<endl;
cout<< "is available int B.fooB() ? "
<< is_available_method(B,int(),fooB) <<endl;
cout<< "is available void B.private_foo() ? "
<< is_available(B,void(),private_foo) <<endl;
}