struct BLA
{
};
template<typename T>
class DUMMY
{
public:
DUMMY() = default;
template<typename U = T, typename = void>
void someFunction()
{
std::cout << std::is_same<U, BLA>::value << "\n";
std::cout << "someFunction() - DEFAULT\n";
}
template<typename U = T, typename std::enable_if<std::is_same<U, BLA>::value, void>::type>
void someFunction()
{
std::cout << "someFunction()\n";
}
};
int main()
{
DUMMY<BLA> dummy;
dummy.someFunction();
}
为什么此SFINAE代码调用显示“ someFunction()-DEFAULT”的someFunction()?它应该调用另一个。显然,std :: is_same :: value是真实的。
答案 0 :(得分:2)
template<typename U = T, typename std::enable_if<std::is_same<U, BLA>::value, void>::type>
将导致template<typename U = T, void>
中(正确替换)无效。
您可能会更改为
template<typename U = T, typename std::enable_if<std::is_same<U, BLA>::value, int>::type = 0>
但是随后,这两个功能都是可行的,而且模棱两可。
所以,您最终可能会做
template<typename U = T, typename std::enable_if<!std::is_same<U, BLA>::value, int>::type = 0>
void someFunction()
{
std::cout << std::is_same<U, BLA>::value << "\n";
std::cout << "someFunction() - DEFAULT\n";
}
template<typename U = T, typename std::enable_if<std::is_same<U, BLA>::value, int>::type = 0>
void someFunction()
{
std::cout << "someFunction()\n";
}
在C ++ 17中,操作更简单
void someFunction()
{
if constexpr (std::is_same<U, BLA>::value) {
std::cout << "someFunction()\n";
} else {
std::cout << std::is_same<U, BLA>::value << "\n";
std::cout << "someFunction() - DEFAULT\n";
}
}
答案 1 :(得分:0)
我正在写新答案,因为它不适合发表评论。除了@ Jarod42。
您似乎以为
template<typename U = T, typename std::enable_if<std::is_same<U, BLA>::value, void>::type>
替换为
template<typename U = T, typename = void>
但不是。替代
template<typename U = T, void>
。
因此,您应该将其声明为
template<typename U = T, typename = typename std::enable_if<std::is_same<U, BLA>::value, void>::type>
。
因为您使用的typename
用于指定类型是从属类型,而不是用于模板参数声明。但是无论如何,它们都不起作用。一个会静默删除格式错误的文件,另一个会导致对同一函数的多次声明。
在您发表评论后,我会尝试解释更详细。
template<typename U = T, typename std::enable_if<std::is_same<U, BLA>::value, void>::type>
void someFunction()
{
std::cout << "someFunction()\n";
}
如果T == BLA
,则U
变成BLA
,并得到std::is_same< U , BLA>::value
true
。所以结果看起来像这样
template<typename U = BLA, void>
如果T == NotBlaType
,则U
变成NotBlaType
,并得到std::is_same<U,BLA>::value
false
。结果是替换失败,std::enable_if<false,void>
没有type
。
但在两种情况下均未声明该函数。因为不能将void
用作non-type template parameter。
但是,如果我们将void
更改为int
,则可以使用。这就是@ Jarod42建议int
的原因。
template<void>
不合法。
但是template<int = 2>
是合法的。
使声明有效后,应有条件地切换函数的声明(因为两个函数具有相同的签名,因此会导致多个声明)。这就是@ Jarod42答案中的两个函数都具有std::enable_if
来评估彼此求反的原因。