2

在 C 和 C++ 中,函数、ADT 和类的一个非常常见的编码模式是:

  • 带有(类的函数)声明的头 .h 文件。
  • 带有实际代码的实现 .cpp 文件。

这些被编译成一个单独的对象(共享或不共享)。其他代码,使用声明的实体(我们称之为'foo'),包括 foo.h 文件,单独编译,然后链接到 foo.o 。

但是,对于模板化的 foo,这是不可能的:如果不指定所需的实例化类型, foo.o 是无用的。每个人似乎都在做的是将实现代码(通常是 foo.cpp)包含在与用户代码相同的翻译单元中。

我希望能够避免这种情况,使用一些不需要包括 foo.cpp 的机制。理想情况下,这应该有效:

主.cpp:

#include "foo.h"
int main() {
    foo<int>();
}

富.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>()

4

2 回答 2

2

这是显式实例化。

template foo<int>();

它告诉编译器fooint. int就像您在.cpp文件中编写实现一样。如果您知道将来将使用哪些类型,这将很有用。如果您foo<int>在许多翻译单元中使用,它可以减少项目中的总编译时间。例如:

文件FooBar.h

template <typename T>
class Bar
{
public:
    T data;
    void func();
};

template<typename T> void foo();

文件FooBar.cpp

template <typename T>
void Bar<T>::func()
{
}

template <typename T>
void foo() {
}

// explicit instantiation

template class Bar<int>;
template class Bar<std::string>;
template foo<int>();
template foo<float>();

主要问题是,您的fooBar模板化的东西只能与实例化类型一起使用。例如,foo仅限于intfloat,并且Bar仅限于intstd::string

于 2013-11-05T16:29:24.683 回答
0

实际上,仅用于实例化,我们甚至不必复制签名:

template decltype(foo<int>) foo;

这在这个例子中并没有太大的区别,但是如果你的签名很长而且很乏味的话。

于 2015-02-05T23:53:01.493 回答