c++允许SFINAE用于此(注意,在c++ 11特性中,这更简单,因为它支持在几乎任意表达式上扩展SFINAE -下面的代码是为使用常见的c++ 03编译器而设计的):
#define HAS_MEM_FUNC(func, name) \
template<typename T, typename Sign> \
struct name { \
typedef char yes[1]; \
typedef char no [2]; \
template <typename U, U> struct type_check; \
template <typename _1> static yes &chk(type_check<Sign, &_1::func > *); \
template <typename > static no &chk(...); \
static bool const value = sizeof(chk<T>(0)) == sizeof(yes); \
}
上面的模板和宏尝试实例化一个模板,给它一个成员函数指针类型,以及实际的成员函数指针。如果类型不匹配,SFINAE会导致模板被忽略。用法:
HAS_MEM_FUNC(toString, has_to_string);
template<typename T> void
doSomething() {
if(has_to_string<T, std::string(T::*)()>::value) {
...
} else {
...
}
}
但是注意,你不能在if分支中调用toString函数。由于编译器将在两个分支中检查有效性,因此在函数不存在的情况下会失败。一种方法是再次使用SFINAE (enable_if也可以从boost中获得):
template<bool C, typename T = void>
struct enable_if {
typedef T type;
};
template<typename T>
struct enable_if<false, T> { };
HAS_MEM_FUNC(toString, has_to_string);
template<typename T>
typename enable_if<has_to_string<T,
std::string(T::*)()>::value, std::string>::type
doSomething(T * t) {
/* something when T has toString ... */
return t->toString();
}
template<typename T>
typename enable_if<!has_to_string<T,
std::string(T::*)()>::value, std::string>::type
doSomething(T * t) {
/* something when T doesnt have toString ... */
return "T::toString() does not exist.";
}
享受使用它的乐趣。它的优点是它也适用于重载的成员函数,也适用于const成员函数(记得使用std::string(T::*)() const作为成员函数指针类型!)