当前位置: 首页 > 知识库问答 >
问题:

模板专门化并在出现问题时启用_[重复]

淳于嘉树
2023-03-14

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

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

我有一个名为“less”的函数,它检查第一个arg是否小于第二个arg。假设我想根据输入的类型有两种不同的实现——1种实现用于integer,另一种实现用于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;
}

上面的代码不编译,因为——它说我正在重新定义更少的方法。

错误是:

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.

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

共有1个答案

东弘扬
2023-03-14

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

错误:重新定义模板

要修复错误,请将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) {
  // ....
}

 类似资料:
  • 还尝试在专门化的中进行模板方法专门化: 这一次它编译,但调用原始方法,即 解决方案

  • ii)当我更改代码并删除void_t时 0和0打印。表示,专门化是,所以我们使用基本模板。对于字符串,专门化无论如何都失败了。 我的问题:iii)有趣的部分。如果现在我把第一行改为使用int作为默认类型 有人能给我解释一下在iii)发生了什么吗?

  • 在本文中,他们说(c)是(b)的显式专门化。我的疑问是,为什么我们不能说它是(a)的显式专门化?因为我们可以为任何特定类型专门化模板。所以,当专门化int*时,为什么他们说(c)显式专门化(b)。 任何评论都将有助于理解事情。

  • 考虑代码: Microsoft Visual Studio 2013给出以下错误: C2912:显式特化'CByteArray序列化(const HLVariant 错误C2783:“CByteArray serialize(const std::enable_if::type 错误表明没有

  • 我有一个通用算法,需要访问其模板类型的特征。有一个特征类可以专门用于提供这些特征。 在我的类中使用此算法时,我想将其与类中定义的私有类型一起使用。 然而,专门化只能发生在或全局范围内,而我的类是不可访问的。 是否有可能以某种方式专门化具有私有类型的模板,至少在可访问此类型的范围内? 也许可以将这个专门化声明为一个类?

  • 这里有一个最小的例子来说明我遇到的问题。 模板成员显式专用于基类中的。模板的代码是显式生成的,并在成员中调用。 我发现的第一个问题是: 该错误是由于在main中调用造成的。可以通过调用来避免这种情况。为什么在的实例中显然是不可见的?