在 C 中,std::enable_if 是一个元函数,允许基于某些约束条件启用模板。它最近被更简洁的 std::enable_if_t 取代。但是,当尝试移植现有代码以使用新语法时,一些用户会遇到意外的重新定义错误。
示例代码
考虑使用 std: 编写的以下代码: enable_if:
template<typename T, typename std::enable_if<std::is_same<int, T>::value>::type* = nullptr> void f() { } template<typename T, typename std::enable_if<std::is_same<double, T>::value>::type* = nullptr> void f() { }
此代码成功编译,具有 int 和 double 的单独特化。现在,假设我们想使用 std::enable_if_t 语法重写它:
template<typename T, typename = std::enable_if_t<std::is_same<int, T>::value>> void g() { } template<typename T, typename = std::enable_if_t<std::is_same<double, T>::value>> void g() { }
意外错误
与预期相反,此更新的代码无法编译,与海湾合作委员会 5.2 reporting:
error: redefinition of 'template<class T, class> void g()' void g() { }
解释
错误在于 std::enable_if_t 表示类型,而不是条件。当用作模板参数时,它指定类型约束。在原始 std::enable_if 情况下,第二个模板参数是指针类型,而在 std::enable_if_t 版本中,它成为类型别名。这会产生两个具有相同类型 (void()) 的不同模板参数。
解决方案
为了避免这种歧义,我们需要确保第二个模板参数表示唯一类型约束。实现此目的的一种方法是使用虚拟模板参数:
template<typename T, typename U = std::enable_if_t<std::is_same<int, T>::value>> void g() { } template<typename T, typename U = std::enable_if_t<std::is_same<double, T>::value>> void g() { }
在这种情况下,U 是一个虚拟参数,仅用于区分两个模板参数。经过此修改,代码将成功编译。
以上是为什么在模板参数中使用 std::enable_if_t 时会出现重新定义错误?的详细内容。更多信息请关注PHP中文网其他相关文章!