在启用基于它的构造函数时是否总是需要复制 class 模板参数?
Is it always necessary to duplicate a class template parameter when enabling constructors based on it?
一般在使用基于class'模板类型的enable_if
时,需要复制class'模板类型作为构造函数或方法的模板参数:
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
,则 "Derived" 版本的构造函数将始终启用,而 "Not Derived" 版本将始终禁用,无论参数 U
.
根据标准,以上实际上是合法的吗?或者编译器只是接受它,可能是由于 "no diagnostic required"?
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>> // ...
有相同的签名。
一般在使用基于class'模板类型的enable_if
时,需要复制class'模板类型作为构造函数或方法的模板参数:
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
,则 "Derived" 版本的构造函数将始终启用,而 "Not Derived" 版本将始终禁用,无论参数 U
.
根据标准,以上实际上是合法的吗?或者编译器只是接受它,可能是由于 "no diagnostic required"?
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>> // ...
有相同的签名。