【发布时间】:2013-11-16 14:37:25
【问题描述】:
在 C 和 C++ 中,函数、ADT 和类的一个非常常见的编码模式是:
- 带有(类函数的)声明的头 .h 文件。
- 包含实际代码的实现 .cpp 文件。
这些被编译成一个单独的对象(共享与否)。其他代码,使用声明的实体(我们称之为“foo”),包括 foo.h 文件,单独编译,然后链接到 foo.o。
但是,对于模板化的 foo,这是不可能的:如果不指定所需的实例化类型,foo.o 是无用的。每个人似乎都在做的是将实现代码(通常是 foo.cpp)包含在与用户代码相同的翻译单元中。
我希望能够避免这种情况,使用一些不需要包括 foo.cpp 的机制。理想情况下,这应该有效:
main.cpp:
#include "foo.h"
int main() {
foo<int>();
}
foo.h:
template<typename T> void foo();
foo.cpp:
template<typename T> void foo() {
// implementation here
}
为此,我想我需要某种巧妙的习语,可能涉及我的构建机制,而不仅仅是源文件和头文件,因此我不需要包含实现代码,只需包含头文件。我在想可能是实现文件的一些内容,包括一些自动生成的标题,例如
template foo<int>();
这将解析它们缺少的实例的目标文件(即两次编译传递),或者可能解析源文件(调整编译器?启用一些辅助输出?);你能推荐这样一个成语吗?还是我没有考虑过的另一种选择?
注意:当然,重点是 foo 模块(foo.h、foo.cpp)的代码并不“知道”需要哪些实例化,例如不知道main()会用foo<int>()还是foo<unsigned char>()。
【问题讨论】:
-
C++ 标准曾经有一个特性(我认为
export关键字是为此保留的),但 AFAIK 唯一或多或少正确支持此特性的编译器是 SGI 的 C++ 编译器。此功能后来被删除。 -
@Axel - EDG(爱迪生设计集团)实施了
export,然后建议将其从语言中删除。 -
那么SGI编译器有EDG的前端吗?因为我记得使用它(一定是在 1997/8 左右)并且不耐烦地等待它被 gcc 实现,只是后来才知道它被丢弃了。
-
包含源代码绝对没有任何问题。只需将其放在 .h 文件中即可。
-
@n.m.:我没有说这是“错误的”。但我想封装我的实现。我不想用实现文件中的各种垃圾污染我主要的翻译单元。
标签: c++ templates instantiation idioms