很抱歉在最后一个答案中误导了您,我想了一下会更简单。所以我会尝试在这里提供一个完整的解决方案。解决此类问题的一般方法是编写一个特征帮助器模板并将其与enable_if
(C++11、boost 或手动实现)一起使用来决定类专业化:
特征
一个简单的方法,不一定是最好的,但写起来很简单:
template <typename T>
struct has_nested_Vec {
typedef char yes;
typedef char (&no)[2];
template <typename U>
static yes test( typename U::Vec* p );
template <typename U>
static no test( ... );
static const bool value = sizeof( test<T>(0) ) == sizeof(yes);
};
方法很简单,提供两个模板函数,返回不同大小的类型。其中一个采用嵌套Vec
类型,另一个采用省略号。对于所有具有嵌套Vec
的类型,第一个重载是更好的匹配(省略号是任何类型的最差匹配)。对于那些没有嵌套Vec
SFINAE 的类型将丢弃该重载,剩下的唯一选项将是省略号。所以现在我们有一个特征来询问任何类型是否有嵌套Vec
类型。
启用如果
您可以从任何库中使用它,也可以自己滚动,这非常简单:
template <bool state, typename T = void>
struct enable_if {};
template <typename T>
struct enable_if<true,T> {
typedef T type;
};
当第一个参数是false
时,基本模板是唯一的选项,并且没有嵌套的type
,如果条件是true
,则enable_if
有一个type
可以与 SFINAE 一起使用的嵌套。
执行
现在我们需要提供模板和专门化,将 SFINAE 仅用于那些带有嵌套的类型Vec
:
template<class T, class V = void>
struct Functor {
void operator()() const {
std::cerr << "general" << std::endl;
}
};
template<class T>
struct Functor<T, typename enable_if<has_nested_Vec<T>::value>::type > {
void operator()() const {
std::cerr << "special" << std::endl;
}
};
每当我们Functor
用一个类型实例化时,编译器都会尝试使用特化,这将反过来实例化has_nested_Vec
并获得一个真值,传递给enable_if
. 对于那些值为false
,enable_if
的类型没有嵌套type
类型,因此 SFINAE 中将丢弃特化并使用基本模板。
您的特殊情况
在您的特定情况下,您似乎不需要专门化整个类型而只需要专门化运算符,您可以将三个元素混合为一个元素:aFunctor
根据存在性分派到两个内部模板化函数之一的Vec
,消除对enable_if
和特征类的需要:
template <typename T>
class Functor {
template <typename U>
void op_impl( typename U::Vec* p ) const {
std::cout << "specialized";
}
template <typename U>
void op_impl( ... ) const {
std::cout << "general";
}
public:
void operator()() const {
op_impl<T>(0);
}
};