【问题标题】:Template specification compile error in g++g ++中的模板规范编译错误
【发布时间】:2011-08-05 12:48:38
【问题描述】:

我有一个模板化的容器对象。我正在尝试为float 版本制作一个专门的构造函数。问题是,当编译器尝试编译使用float 版本的第二个对象时,我收到multiple definition of 错误。

注意:h 文件中的整个类。该文件包含一个定义(#ifndef#define#endif)。 g++ 版本 3.4.6。这可以与其他编译器一起编译,例如英特尔的 icc。

代码类似如下:

template <typename T>
class Container {
public:
   Container();
   virtual ~Container() {}
private:
   std::vector<T> data;
   // other members
};

template <> Container<float>::Container() {
   // do something special
}

template <typename T> Container<T>::Container() {
   // do default initialization
}

有什么想法吗?谢谢!

EDIT正在编译的对象也将进入单独的共享对象,不确定是否与它有关。

【问题讨论】:

  • g++ 4.0.1 也可以。升级?
  • 目前,我无法这样做,或者相信我会这样做。我被锁定在这个应用程序的那个版本中。
  • 只是为了测试,我把代码复制到一个有g++ 4.1.1的盒子里,得到了同样的错误。

标签: c++ templates compiler-errors


【解决方案1】:

专业化仍然必须遵守单一定义规则,就像任何其他非模板方法一样。要么将其标记为内联,要么在源文件(不是你的头文件)中定义方法体。

【讨论】:

    【解决方案2】:
    template <> Container<float>::Container() {
       // do something special
    }
    

    是专业的定义。必须在使用它的每个编译单元中声明特化:

    template <> Container<float>::Container();
    

    并在仅一个的 CU 中定义。所以你的.h 必须有声明,你必须找到一个足够的(可能是新的).cpp 来定义。 (正如 Mark B 所指出的,内联特化也是一种允许将定义放在需要的所有编译单元中的方法。

    【讨论】:

      【解决方案3】:

      这很棘手。问题是你的专业不是 模板,而是一个实际的函数定义。而且因为它在一个 标题,当你包含它两次时,你会得到多个定义。 比如:

      template<> Container<float>::Container();
      

      在标头中,并在单个源文件中实现。

      【讨论】:

        【解决方案4】:

        你可以使用typeid:

        template <typename T> Container<T>::Container() {
           if(typeid(T)==typeid(float)) {
              // do something special
           }
           else {
              // do default initialization
           }
        }
        

        缺点:您不能在特殊情况下使用初始化列表。 编辑: 当我写这个答案时,我仍然认为该错误是由编译器引起的,而不是由 OP 的代码引起的(没有过多地研究它)。然而,这种 typeid 方法是绝对有效的 C++(参见下面的链接),如果模板确实不能与您的特定编译器一起正常工作,它是一个非常好的解决方法,并且如果有一天您可以切换到模板解决方案,它可以很容易地替换为更好的编译器。

        演示:example @ ideone

        【讨论】:

        • 这不就是糟糕的设计吗?因为这种尝试抛弃了模板提供的所有可能性。
        • @tgmath:我同意,最常使用typeid 的代码代表糟糕的设计。但是在这种情况下,给typeid 的参数是一个类型而不是一个对象,这还不错。当然,如果可能,您应该使用模板。
        • @f4:没有。我不这么认为。查看我的链接。
        • @smerlin 如果操作对 float 类型有效,而对其他 T 类型无效,则会出现编译错误。这可以通过模板专业化来避免。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-17
        • 1970-01-01
        • 2012-09-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多