rea*_*esk 6 c++ compiler-errors sfinae template-specialization c++11
我有这样的代码:
class Bar {
public:
void print() {
std::cout << "bar\n";
}
};
template<typename T>
class Foo {
public:
template <typename std::enable_if<std::is_base_of<T,Bar>::value,T>::type>
void print() {
t.print();
}
template <typename>
void print() {
std::cout << t << std::endl;
}
private:
T t;
};
int main() {
// Foo<int> foo1;
Foo<Bar> foo2;
foo2.print();
}
Run Code Online (Sandbox Code Playgroud)
这段代码的目的是:如果T ta是Bar或的子类Bar,则foo.print()推导为void print() {t.print();},否则推导为void print() {std::cout << t << std::endl;},但是事情没有按我预期的那样进行。编译器错误:
“非类型模板参数不能具有类型'typename std :: enable_if :: value,Bar> :: type'(aka'Bar')”,
此代码有什么问题?
您应同时重载print()函数模板(以使SFINAE正常工作),否则始终首选非模板函数。
您应该print()采用自己的模板类型参数;类型检查不应T直接在类模板参数上执行,函数模板重载解析和SFINAE不在函数模板本身上执行,而类模板则不涉及。
您可以将部分std::enable_if移到返回类型。
如果您希望类型为或的派生类,则应将指定的顺序更改为std::is_base_of(即std::is_base_of<Bar, X>不是std::is_base_of<X, Bar>)。BarBar
例如
template <typename X = T>
typename std::enable_if<std::is_base_of<Bar, X>::value>::type print() {
t.print();
}
template <typename X = T>
typename std::enable_if<!std::is_base_of<Bar, X>::value>::type print() {
std::cout << t << std::endl;
}
Run Code Online (Sandbox Code Playgroud)