模板特化和 enable_if 问题

2021-12-13 00:00:00 templates c++ c++11 sfinae enable-if

我遇到了有关 enable_if 和模板特化的适当用法的问题.

I am running into a problem regarding the appropriate usage of enable_if and template specialization.

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

After modifying the example (for confidentiality reasons), here's a comparable example:

我有一个名为less"的函数,用于检查第一个参数是否小于第二个参数arg.假设我想要两种不同的实现取决于输入的类型 - 1 个整数和另一个双倍.

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.

到目前为止我的代码看起来像这样 -

The code that I have so far looks like this -

#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 方法.

The above code does not compile because - It says that I am re-defining the less method.

错误是:

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.

有人能指出这里的错误吗?

Can someone point out what's the mistake here?

推荐答案

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

Default template arguments are not part of the signature of a function template. So in your example you have two identical overloads of less, which is illegal. clang complains about the redefinition of the default argument (which is also illegal according to §14.1/12 [temp.param]), while gcc produces the following error message:

错误:重新定义'templatebool less(T, T)'

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

To fix the error move the enable_if expression from default argument to a dummy template parameter

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,虽然我觉得这更难阅读.


Another option is to use enable_if in the return type, though I feel this is harder to read.

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) {
  // ....
}

相关文章