教做奥数的网站,58同城建设银行招聘网站,金融行业网站模板,怎么样搭建wordpress译注 - 需要注意的是如果是用VC编译器#xff0c;直接使用__if_exist关键字就行了#xff0c;不需要用这种方法#xff1a; __if_exist(Class::member){//do_something}__if_exist(Class::method){//do_something} 目的 检测一个特定类成员的存在性。 别称 动机 编译期的反…译注 - 需要注意的是如果是用VC编译器直接使用__if_exist关键字就行了不需要用这种方法 __if_exist(Class::member) { //do_something} __if_exist(Class::method) { //do_something } 目的 检测一个特定类成员的存在性。 别称 动机 编译期的反射能力是C模板元编程的基础。 诸如Boost.TypeTraits和TR1 type_traits header的类型特征Type traits库提供了强大的方法来分离类型和他们的关系的信息。检测一个类的数据成员的存在性也是编译期反射的一个例子。 解决方案和示例代码 成员检测器惯用法(idiom)通过匹配失败不是错误(Substitution Failure Is Not An Error-SFINAE)惯用法实现。下面的模板类DetectXT是一个可以检测类型T是不是有一个名为X的数据成员的元函数。注意数据成员X可以是任何类型。 templatetypename Tclass DetectX { struct Fallback { int X; }; // add member name X struct Derived : T, Fallback { }; templatetypename U, U struct Check; typedef char ArrayOfOne[1]; // typedef for an array of size one. typedef char ArrayOfTwo[2]; // typedef for an array of size two. templatetypename U static ArrayOfOne func(Checkint Fallback::*, U::X *); templatetypename U static ArrayOfTwo func(...); public: typedef DetectX type; enum { value sizeof(funcDerived(0)) 2 }; };//(typedef DetectX type; 这个并没有被用到删掉这行也没有关系) 这个惯用法的工作原理是在编译期创建一个可控的二义性并通过SFINAE惯用法最终从其中恢复过来。第一个代理类Fallback有一个名字和你想要检测存在性的成员一样的成员。类Derived多继承自T和Fallback这样它将有至少一个名为X的成员如果T也有一个数据成员X的话将会有两个。 模板结构体Check被用来创建一个可控的二义性。Check需要两个模板参数第一个是类型参数第二个是一个该类型的实例例如Checkint, 5就是一个有效地实例化 译注注意例子中用到了指向成员的指针(Pointers to Members)int Fallback::*。两个名为func的重载函数创建了一个重载集合这是SFINAE惯用法的通常做法。第一个func函数只有在数据成员U::X可以被无二义性的取得的情况下会被实例化。而U::X的地址只有在类Derived中只有一个名为X的数据成员时可以被取得。也就是说此时T不会有名为X的数据成员。如果T含有XU::X的地址在没有更多排除歧义的信息的情况下是没法取得的因此在没有错误的情况下对第一个func的实例化将会失败而另一个同名函数将会被选择。你应该注意到了两个func函数的返回值类型是不同的。第一个函数返回一个大小为1的数组的引用而第二个函数返回一个大小为2的数组的引用。通过返回值大小的不同可以用来检测哪个函数被实例化了。最终一个布尔值被暴露出来译注声明为public的一个枚举值值为0或者1可当为布尔值使用。当返回值的sizeof结果为2时该值为true也就是说只有当因为T含有名为X的数据成员而导致第二个函数func被实例化时为true。 对每一个需要检测的不同的数据成员上面的模板需要相应的变化。这时使用一个宏将是一个好办法。下面的示例代码说明了宏的使用方法 #define CREATE_MEMBER_DETECTOR(X) \ templatetypename T class Detect_##X { \ struct Fallback { int X; }; \ struct Derived : T, Fallback { }; \ \ templatetypename U, U struct Check; \ \ typedef char ArrayOfOne[1]; \ typedef char ArrayOfTwo[2]; \ \ templatetypename U static ArrayOfOne func(Checkint Fallback::*, U::X *); \ templatetypename U static ArrayOfTwo func(...); \ public: \ typedef Detect_##X type; \ enum { value sizeof(funcDerived(0)) 2 }; \ }; CREATE_MEMBER_DETECTOR(first); CREATE_MEMBER_DETECTOR(second); int main(void) { typedef std::pairint, double Pair; std::cout ((Detect_firstPair::value Detect_secondPair::value)? Pair : Not Pair); } 检测被重载的成员函数 一个成员检测器惯用法的变体可以用来检测一个类中特定成员函数的存在性即使这个函数被重载了译注不被重载的当然也行因为检测时函数的参数类型可以作为模板参数传入所以可以区分不同的重载也能被检测到。 templatetypename T, typename RESULT, typename ARG1, typename ARG2class HasPolicy { template typename U, RESULT (U::*)(ARG1, ARG2) struct Check; template typename U static char func(CheckU, U::policy *); template typename U static int func(...); public: typedef HasMember type; enum { value sizeof(funcT(0)) sizeof(char) }; };//(typedef HasMember type; 似乎是个笔误但是删掉这行也没有关系) 上面的模板类HasPolicy检查U是否拥有一个名为policy的成员函数该函数有两个参数ARG1和ARG2返回值为RESULT。模板结构体Check只有在U含有U::policy成员函数该函数有两个参数ARG1和ARG2并且返回RESULT时才会实例化成功。 注意模板结构体Check的第一个模板参数是一个类型第二个模板参数是指向该类型的成员函数的指针。如果模板结构体Check不能被实例化剩下的以int为返回值的func将会被实例化。func函数返回值类型的大小最终决定类型特征的答案true或者false. 已知应用 相关惯用法 Substitution Failure Is Not An Error (SFINAE) 参考资料 Substitution failure is not an error, part II 原文链接 http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Member_Detector 转载于:https://www.cnblogs.com/shawnhue/archive/2011/11/29/More_CPP_Idioms_Member_Detector.html