我正在尝试使用std::enable_if
通过以下代码使用SFINAE有条件地从两个成员函数模板中选择一个:
#include <iostream>
#include <type_traits>
template<typename T>
struct C {
template<typename Q = T, typename = typename std::enable_if<std::is_same<Q, int>::value>::type>
int foo() {
return 1;
}
template<typename Q = T, typename = typename std::enable_if<!std::is_same<Q, int>::value>::type>
int foo() {
return 0;
}
};
int main() {
std::cout << C<int>().foo() << std::endl; //error member function foo already defined
}
但是由于某种原因,Visual c ++不断给我一个编译器错误,指出已经定义了foo
。即使很明显,根据类的模板参数,也只有一个函数的格式正确。因此SFINAE应该从考虑中删除第二个。
知道为什么这行不通吗?
答案 0 :(得分:3)
尝试
template<typename T>
struct C {
template<typename Q = T,
typename std::enable_if<std::is_same<Q, int>::value, bool>::type = true>
int foo() { // .............................................^^^^^^^^^^^^^^^^^^^^
return 1;
}
template<typename Q = T,
typename std::enable_if<!std::is_same<Q, int>::value, bool>::type = true>
int foo() { // ..............................................^^^^^^^^^^^^^^^^^^^^
return 0;
}
};
关键是在您的代码中SFINAE将启用/禁用模板类型参数的默认值;但是默认值不参与重载解析,因此,在您的情况下,您有两个功能
template<typename, typename = void>
int foo() {
return 1;
}
template<typename, typename>
int foo() {
return 0;
}
具有相同签名;因此编译器无法在两者之间进行选择,并且会出现错误。
我提议的代码是不同的,因为如果std::enable_if
的测试为假,则您不需要类型(=
左侧的元素),而不是值。就像
// ................VVVVVV what is = true ?
template<typename, = true>
int foo() {
return 1;
}
这是禁用该方法的真正“替代失败”。