【问题标题】:Template specialization and enable_if problems [duplicate]模板专业化和 enable_if 问题[重复]
【发布时间】:2015-06-12 16:01:13
【问题描述】:

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

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

我有一个名为“less”的函数,它检查第一个参数是否小于第二个 参数。假设我想要两种不同的实现 取决于输入的类型 - 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.

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

【问题讨论】:

  • 基本上你没有正确使用enable_if,因为你调用返回类型的方式。
  • 快速解决方案是在任一模板中添加省略号参数...,以便将它们视为不同的重载。
  • 或将签名改为template &lt;class T, typename std::enable_if&lt;std::is_floating_point&lt;T&gt;::value&gt;::type* = nullptr&gt;

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


【解决方案1】:

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

错误:'template&lt;class T, class&gt; 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) {
  // ....
}

【讨论】:

  • 从技术上讲,根据标准,第一组代码格式不正确,因为void * 不是模板非类型参数的有效类型。实际上,我所知道的编译器实际上并不在乎。不过,修复很简单。
  • @T.C.直到...感谢您指出这一点
  • 我把它改成了一个函数参数,现在可以用了
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多