【问题标题】:Where to define class with both template and non-template members?在哪里定义具有模板和非模板成员的类?
【发布时间】:2013-05-11 10:33:28
【问题描述】:

我知道模板定义应该全部进入头文件 [1]。但是如果我在一个类中同时有模板和非模板怎么办:

// cls.h
class cls {
public:
    template <typename U> void bar(U x);   // template
    void baz();                            // non-template
    template <typename V> class nest {
    };
};

// foo1.cpp
#include "cls.h" ...

// foo2.cpp
#include "cls.h" ...

理想情况下,我想在同一个文件中定义barbaz,因为它们关系密切。

  • 但是如果我把所有的实现都放在头文件中,我最终会多重定义baz
  • 如果我将所有实现放入 .cpp,那么 foo1.cppfoo2.cpp 将无法看到 barnest 的定义。

我是否必须在单独的文件之间拆分 barbaz

[1] 在使用 NVCC 编译 CUDA 代码的 MSVC++ 上,将模板声明为 inline 似乎对我不起作用。

【问题讨论】:

  • 将模板声明为内联是什么意思?根据当前答案,将非模板化 baz 定义为内联,它应该可以工作。

标签: c++ class templates


【解决方案1】:

但是如果我把所有的实现都放在头文件中,我最终会多重定义 baz。

您仍然可以将baz() 的函数定义标记为inline。这将允许您将baz() 的定义放在头文件中,而不会导致多个符号定义错误。

如果我将所有实现放入 .cpp,则 foo1.cpp 或 foo2.cpp 看不到 bar 和 nest 的定义。

如果您事先知道函数模板将使用什么类型进行实例化,则可以在包含函数模板定义的 .cpp 文件中使用显式实例化。

template void cls::bar(int);

如果以上选项都不适合你,那么你将不得不放弃这个要求:

理想情况下,我想在同一个文件中定义 bar 和 baz,因为它们关系密切。

并将成员函数模板的定义放在头文件中,非模板成员函数的定义放在一个.cpp文件中。

【讨论】:

  • 谢谢 - 内联非模板代码可以解决问题。但这会导致头文件中包含更多内容而导致膨胀/编译时间更长吗?
  • 它还提出了一个问题,编译器究竟是如何处理inline 代码的——我们如何能够乘以定义inline 函数?
  • 是的。但另一种方法是将 baz 放入 cpp。您始终可以像往常一样将任何未模板化的内容放入 cpp。
  • 另外,如果baz 不能是inlined(例如递归调用自身)怎么办?
  • @MiloChen:inline 关键字在这个意义上与内联没有任何关系。它主要是一种规避单一定义规则并允许将定义放在头文件中的方法。
猜你喜欢
  • 2019-08-16
  • 2020-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-20
  • 1970-01-01
相关资源
最近更新 更多