过去使用SFINAE选择构造函数重载时,我通常使用以下内容:
template <typename T>
class Class {
public:
template <typename U = T, typename std::enable_if<std::is_void<U>::value, int>::type=0>
Class() {
std::cout << "void" << std::endl;
}
template <typename U = T, typename std::enable_if<!std::is_void<U>::value, int>::type=0>
Class() {
std::cout << "not void" << std::endl;
}
};
但是,我刚刚遇到了这个替代方案:
template <typename U = T, typename std::enable_if<std::is_void<U>::value>::type...>
Class() {
std::cout << "void" << std::endl;
}
考虑到以下情况属于非法......
template <typename U = T, void...> // ERROR!
Class() { }
...上面使用省略号而不是非类型模板参数的替代方法如何工作?
答案 0 :(得分:1)
我之前的回答是错误的。抱歉。我只是想解决它。
此声明:
template <typename U = T, void...>
Class() { }
违反[temp.res] / 8:
该计划是 格式错误,无需诊断,如果[...]可变参数模板的每个有效特化都需要空模板参数包
它不需要诊断,但编译器选择发出一个。无论哪种方式,代码都是不正确的。
另一方面
template <typename U = T, std::enable_if_t<std::is_void<U>::value>...>
Class() { }
不违反此要求。我们有一个空包装,所以我们不要碰到你不能使用void
作为非类型模板参数的事实。此外,enable_if
的假设专业化可以提供一种不void
的类型,因此由于上述限制,它不会形成错误。