判断一个类型包含了哪些数据或函数成员在提供了类型反射机制的高级语言上大有用处,而C++这种静态语言并未提供直接支持。需要有类似MFC一样在每个类型里编写组织相关信息的代码才行。
本篇尝试使用一种非侵入式的判断方式,不需要修改原有类定义,来判断某个类型是否包含某个特定的成员数据或者函数
举例来说,有类型A,B定义如下:
class A
{
public:
bool less(const A& other);
bool equal(const A& other);
};
class B
{
public:
bool less(const B& other);
};
我们想判断A是否包含了成员函数equal,我们需要定义一个元函数来判断,测试代码如下:
TypeExistEqualMemberFunc<A>::value //表达式值为1
TypeExistEqualMemberFunc<B>::value //表达式值为0
实现原理使用了C++的符号查找机制,即在一个类中引用的符号,C++会先在当前类中找,没有再查找基类,再没有就在上层的嵌套类或者名字空间里找(如果有的话)
最后会在全局名字空间里找。实现如下:
template<class T>
struct TypeExistEqualMemberFunc
{
static void equal();
struct test: T
{
static int f(bool (T::*)(const T&));
static int f(bool (T::*)(const T&)const);
static char f(...);
enum {value = (sizeof(f(&equal)) == sizeof(int))};
};
enum {value = test::value};
};
在内部类test里引用的equal函数如果在基类T里有定义,那就不会引用到外部的静态equal函数,使用它调用f方法,使用的是输入成员函数指针的重载版本,value返回true
否则如果T内没有定义equal成员函数,就会引用到外部的静态equal成员函数,将调用f的第三个重载版本;
同样如果T内定义的equal成员函数的参数及返回值类型不符合前两个f重载版本的参数类型定义,也会使用f的第三个版本,这时value的表达式判断为false。
同样的机制也可以用于成员变量的判断!