如果我将模板分成 header 和源代码,有没有办法将它编译成自己的 object 文件?
If I've separated a template into a header and source, is there any way to compile it to its own object file?
我喜欢 header 文件作为 self-documenting 引用存在。我尝试将它们保留在带有文档注释的声明中,然后在我的源文件中对所有实现进行编程。本质上是一个文档化的界面。
我正在做一个大量使用模板的项目,而不是用实现细节填充 header(我知道我仍然可以声明模板并稍后在 header 但这并不能解决这个问题)我选择做类似的事情。
// foo.h
template<typename T>
class Foo {
public:
Foo();
T get_foo();
private:
T foo;
}
#include "foo.tpp"
// foo.tpp
template<typename T>
Foo<T>(T f) : foo(f) {};
template<typename T>
T Foo<T>get_foo() { return foo; }
这有一定的负面影响。任何使用 #include "foo.h"
的源都必须在 foo 更改时完全重新编译。从本质上讲,这导致我每次更改(概念上但实际上)独立代码时都需要重新编译项目 most/all。
我理解,由于 C++ 编译器处理模板的方式、语言标准或它们的某种组合,当编译器遇到需要替换的情况时,如 auto f = Foo<int>();
,它需要完整的定义Foo<int>
可用于正确执行替换。
有没有办法解决这个问题?在这种情况下,至少在我看来,给定 foo.tpp
作为源文件,编译器可以轻松地扩展两者的模板参数并将它们编译为就好像它们是普通的 header/source 文件一样作为独立的 TU。然后链接器只需要稍后找到它们以在最后的链接阶段解析 Foo<int>
的定义。
从表面上看,这个例子过于简单了,而且我还遗漏了更复杂的案例和注意事项。我想知道是否有解决这个问题的实用方法。我正在考虑编写一个脚本来为我执行替换,然后编译这些文件,但我希望有一个已知的、更通用的方法。
Is there no way at all around this?
是的,有。如果您在定义函数的翻译单元中显式实例化模板,则可以在其他翻译单元中使用这些实例。
但这当然会限制哪些模板参数可以用于您选择用于显式实例化的模板参数。对于不受约束的模板参数,无法在所有翻译单元(使用 ODR 的地方)中定义函数。
不,除了有两种不同的方式。
第一种方法是在带有特定参数的 cpp 文件中显式实例化模板及其方法。然后链接器将找到那些实现。这需要知道您计划支持哪些模板参数。
第二个是模块,没有编译器具有工业质量的实现。模块避免了为每个最终用户重新解析共享模板代码;仍然需要重新编译。
我喜欢 header 文件作为 self-documenting 引用存在。我尝试将它们保留在带有文档注释的声明中,然后在我的源文件中对所有实现进行编程。本质上是一个文档化的界面。
我正在做一个大量使用模板的项目,而不是用实现细节填充 header(我知道我仍然可以声明模板并稍后在 header 但这并不能解决这个问题)我选择做类似的事情。
// foo.h
template<typename T>
class Foo {
public:
Foo();
T get_foo();
private:
T foo;
}
#include "foo.tpp"
// foo.tpp
template<typename T>
Foo<T>(T f) : foo(f) {};
template<typename T>
T Foo<T>get_foo() { return foo; }
这有一定的负面影响。任何使用 #include "foo.h"
的源都必须在 foo 更改时完全重新编译。从本质上讲,这导致我每次更改(概念上但实际上)独立代码时都需要重新编译项目 most/all。
我理解,由于 C++ 编译器处理模板的方式、语言标准或它们的某种组合,当编译器遇到需要替换的情况时,如 auto f = Foo<int>();
,它需要完整的定义Foo<int>
可用于正确执行替换。
有没有办法解决这个问题?在这种情况下,至少在我看来,给定 foo.tpp
作为源文件,编译器可以轻松地扩展两者的模板参数并将它们编译为就好像它们是普通的 header/source 文件一样作为独立的 TU。然后链接器只需要稍后找到它们以在最后的链接阶段解析 Foo<int>
的定义。
从表面上看,这个例子过于简单了,而且我还遗漏了更复杂的案例和注意事项。我想知道是否有解决这个问题的实用方法。我正在考虑编写一个脚本来为我执行替换,然后编译这些文件,但我希望有一个已知的、更通用的方法。
Is there no way at all around this?
是的,有。如果您在定义函数的翻译单元中显式实例化模板,则可以在其他翻译单元中使用这些实例。
但这当然会限制哪些模板参数可以用于您选择用于显式实例化的模板参数。对于不受约束的模板参数,无法在所有翻译单元(使用 ODR 的地方)中定义函数。
不,除了有两种不同的方式。
第一种方法是在带有特定参数的 cpp 文件中显式实例化模板及其方法。然后链接器将找到那些实现。这需要知道您计划支持哪些模板参数。
第二个是模块,没有编译器具有工业质量的实现。模块避免了为每个最终用户重新解析共享模板代码;仍然需要重新编译。