c++ - 模板特化和 enable_if 问题

标签 c++ templates c++11 sfinae enable-if

我遇到了关于 enable_if 和模板特化的适当使用的问题。

修改示例后(出于保密原因),这是一个可比较的示例:

I have function called "less" that checks if 1st arg is less than 2nd arg. Let's say I want to have 2 different kinds of implementations depending on the type of input - 1 implementation for integer and another for double.

我目前的代码是这样的 -

#include <type_traits>
#include <iostream>

template <class T,
          class = typename std::enable_if<std::is_floating_point<T>::value>::type>
     bool less(T a, T b) {
  // ....
}

template <class T,
          class = typename std::enable_if<std::is_integral<T>::value>::type>
     bool less(T a, T b) {
  // ....
}

int main() {
    float a;
    float b;
    less(a,b);
    return 0;
}

上面的代码无法编译,因为 - 它说我正在重新定义 less 方法。

错误是:

Z.cpp:15:19: error: template parameter redefines default argument
          class = typename std::enable_if<std::is_integral<T>::value>::type>

                  ^
Z.cpp:9:19: note: previous default template argument defined here
          class = typename std::enable_if<std::is_floating_point<T>::value>::type>
                  ^

Z.cpp:16:11: error: redefinition of 'less'
     bool less(T a, T b) {
          ^

Z.cpp:10:11: note: previous definition is here
     bool less(T a, T b) {
          ^

Z.cpp:23:5: error: no matching function for call to 'less'
    less(a,b);
    ^~~~

Z.cpp:15:43: note: candidate template ignored: disabled by 'enable_if'
      [with T = float]
          class = typename std::enable_if<std::is_integral<T>::value>::type>
                                          ^
3 errors generated.

谁能指出这里的错误是什么?

最佳答案

默认模板参数不是函数模板签名的一部分。因此,在您的示例中,您有两个相同的 less 重载,这是非法的。 clang 提示默认参数的重新定义(根据 §14.1/12 [temp.param] 这也是非法的),而 gcc 产生以下错误消息:

error: redefinition of 'template<class T, class> bool less(T, T)'

要修复错误,请移动 enable_if从默认参数到虚拟模板参数的表达式

template <class T,
          typename std::enable_if<std::is_floating_point<T>::value, int>::type* = nullptr>
     bool less(T a, T b) {
  // ....
}

template <class T,
          typename std::enable_if<std::is_integral<T>::value, int>::type* = nullptr>
     bool less(T a, T b) {
  // ....
}

另一种选择是使用 enable_if在返回类型中,虽然我觉得这更难阅读。

template <class T>
      typename std::enable_if<std::is_floating_point<T>::value, bool>::type 
      less(T a, T b) {
  // ....
}

template <class T>
     typename std::enable_if<std::is_integral<T>::value, bool>::type 
     less(T a, T b) {
  // ....
}

关于c++ - 模板特化和 enable_if 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29502052/

相关文章:

c++ - 没有子类化的 CAsyncSocket?

c++ - 模板参数和它自己的模板参数都包含同名类型;如何在函数签名中引用第二个?

C++ 帮助处理 header

C++按值传递结构数组

templates - 如何将 jinja if-else 逻辑与 Ansible inventory 一起使用

c++ - 在没有参数列表的情况下无效使用模板名称 'x'

c++ - 自定义元素的迭代器在 vector 中

C++ 函数重定义

c++ - 是否可以在 C++ 中创建类型 vector ?

c++ - std::vector 和 std::min 行为