c++一种反射机制,判断类中是否存在特定的函数
c++语言本身并没有提供反射机制,倒是有一个比较基础的RTTI,利用c++的模板特性,SFINAE,可以实现一些反射功能,先看代码:
#define HAS_MEMBER(member)\
template<typename T, typename... Args>struct has_member_##member\
{\
private:\
template<typename U> static auto Check(int) -> decltype(std::declval<U>().member(std::declval<Args>()...), std::true_type()); \
template<typename U> static auto Check(...) -> decltype(std::false_type()); \
public:\
static const bool value = std::is_same<decltype(Check<T>(0)), std::true_type>::value; \
} \
在看一下使用实例:
class Person
{
public:
Person() {}
public:
void test() {
cout << "asasa" << endl;
}
};
HAS_MEMBER(test);
int main()
{
cout << has_member_test<Person>::value << endl;
return 0;
}
这段代码可以判断一个class Person中是否存在一个名字为test的函数,分析一下是如何做到的:
main函数上方的 HAS_MEMEBER(test); 实例化出了一个struct , 名字是has_member_test, 这里用到了宏的字符串连接这个语法。
再看内部的value变量,这里其实有个要注意的地方,一般而言类里的staic变量,只是一种声明,而不是一种定义,需要在类外再去定义一下,才能被分配内存空间,但是大多编译器有优化,如果变量类型是类似int型,或者说可以隐式转换成int型的 const变量,可以直接在类中定义了,不需要到类外再定义一遍。
std::is_same在这里内部是一个decltype,比较Check(0)的返回值是否与std::true_type相同,相同的话,就得到了true,否则就是false。
重点是内部的Check函数,先看第一个Check函数,他接受一个int ,返回一个atuo, 返回值类型是一种尾序语法声明的,返回值中有一个declval, 他返回一个类型的右值引用,不管是否有没有默认构造函数或该类型不可以创建对象。(可以用于抽象基类),也就是说 std::declval<U>()这里得到了一个Person实例。
然后对他调用 Person().test, (member 会被宏替换成test), 这里就变成了 Person().test(std::declVal<Args>()…), 其中的Args 是可变模板参数包,这里不解释了,其实就是以对应的参数,来调用 Person().test(), 如果Person中有test方法,且test函数参数正确,那么这里就会编译通过,由于逗号表达式的原因,会选取右侧的std::true_type,作为返回值,如果Person里面没有test函数,或函数参数不匹配,那么这个模板本身就没有办法匹配,由于SFINAE机制,模板匹配失败是OK的,所以会找下一个候选模板,这里就找到了第二个Check函数,肯定是可以匹配的,这个函数则直接返回false, 由此就是实现了一种简单的反射机制。
更多推荐

所有评论(0)