一般在使用基于类模板类型的enable_if
时,需要复制类模板类型作为构造函数或方法的模板参数:
template <
typename U = T,
typename = typename std::enable_if<
!std::is_void<U>::value
>::type
>
Class() { }
究竟什么时候需要(或不需要)?
例如,下面的代码可以在 G++、Clang 和 VC++ 上正常编译...
template <typename T = void>
class Class {
public:
template <
typename U,
typename = typename std::enable_if<
// Is the use of T here allowed?
std::is_void<T>::value
|| std::is_base_of<T, U>::value
>::type
>
Class(U &&arg) {
std::cout << "Derived" << std::endl;
}
template <
typename U,
typename ...U_Rest,
typename = typename std::enable_if<
// Is the use of T here allowed?
!std::is_void<T>::value
&& !std::is_base_of<T, U>::value
>::type
>
Class(U &&arg, U_Rest &&...rest) {
std::cout << "Not Derived" << std::endl;
}
};
... 但直接使用 T
作为 enable_if
的一部分。具体来说,如果 T
为 void
,构造函数的“派生”版本将始终启用,而“非派生”版本将始终禁用,无论参数 U
。
根据标准,上述实际上合法吗?或者编译器只是接受它,可能是因为“不需要诊断”?
最佳答案
SFINAE适用于模板方法,应该不是hard failure(所以主要应该看它的模板参数)
这里你的条件取决于U
,所以没问题。
注意你应该更喜欢
template <typename U, std::enable_if_t<cond>* = nullptr>
结束
template <typename U, typename = std::enable_if_t<cond>>
允许写入禁用版本
template <typename U, std::enable_if_t<!cond>* = nullptr>
作为
template <typename U, typename = std::enable_if_t<cond>> //...
template <typename U, typename = std::enable_if_t<!cond>> // ...
具有相同的签名。
关于c++ - 在启用基于它的构造函数时是否总是需要复制类模板参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39100394/