模板专用化和enable_if问题

Template specialization and enable_if problems

本文关键字:if 问题 enable 专用      更新时间:2023-10-16

我遇到了一个关于enable_if和模板专业化的适当使用的问题。

修改示例后(出于保密原因),这里有一个类似的示例:

我有一个名为"less"的函数,它检查第一个参数是否小于第二个参数arg。假设我想要两种不同类型的实现取决于integer和的input-1实现的类型另一个是替身。

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

#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产生以下错误消息:

错误:重新定义"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) {
  // ....
}