启用基于类模板形参的构造函数时,是否总是需要复制该类模板形参?
Is it always necessary to duplicate a class template parameter when enabling constructors based on it?
通常,当基于类的模板类型使用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;
}
};
ideone rextester
…而是直接使用T
作为enable_if
的一部分。具体来说,如果T
是void
,则构造函数的"派生"版本将始终被启用,而"非派生"版本将始终被禁用,无论参数U
。
根据标准,上述内容是否合法?或者编译器只是接受它,可能是由于"不需要诊断"?
SFINAE适用于模板方法,它不应该是硬故障(因此主要取决于它的模板参数)。
这里你的情况取决于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>> // ...
相关文章:
- 使用mem_fun_ref if成员函数需要多个形参
- 通过类的模板形参特化成员模板结构
- 非类型引用形参/实参
- 哪个模板形参在boost::shared_ptr构造函数中使用一个原始指针
- 如何确保迭代器模板形参与模板类的模板形参具有相同的数据类型
- 如何在编译时通过模板形参默认值的名称/指针获取函数的类型
- c++:候选模板被忽略:模板形参显式指定的参数无效
- c++中作为形参的指针
- 哪种方法更适合为函数提供编译时间常数?函数实参与模板形参
- 包含void*结构的函数的Const正确性和形参
- 传递boost::函数,该函数接受一个模板实参作为默认为NULL的形参
- 将右值引用形参强制转换为右值引用
- 给引用形参赋值使对象无效
- 当实参是初始化列表而形参是引用时,重载解析
- const整型模板形参的条件
- 使用作为模板形参提供的基类成员,不带限定符
- 为什么必须引用const来避免复制形参?
- 启用基于类模板形参的构造函数时,是否总是需要复制该类模板形参?
- 在不调用initializer_list构造函数的情况下,将不可复制、不可移动的类型构造为函数形参
- 模板类复制构造函数形参,带或不带模板实参