外部模板和不完整的类型
extern template & incomplete types
最近当我尝试优化我的包含层次结构时,我偶然发现了文件a.hpp
:
template<class T>
class A
{
using t = typename T::a_t;
};
class B;
extern template class A<B>;
这似乎是格式错误的。事实上,似乎最后的 extern 模板语句会导致实例化 A<B>
这导致编译器抱怨不完整的类型。
我的目标是在a.cpp
中定义A<B>
:
#include <b.hpp>
template class A<B>;
这样我就不必包含来自a.hpp
的b.hpp
,这似乎是减少编译时间的好主意。但是它不起作用(a.hpp
本身无法编译!有没有更好的方法
注意:当然,我不能使用显式模板实例化,但这不是我想要的!我想"预编译"A<B>
以节省编译时间(如果使用(,但是如果不使用A<B>
,我不想在每个使用a.hpp
的文件中都包含b.hpp
!
extern 模板声明阻止成员函数体的实例化,但它强制实例化类定义,因为编译器无论如何都需要它,并且类体需要模板参数的完整定义,因为它访问其成员。恐怕不可能对A<B>
的用户隐藏B的身体。
Extern 模板是一种优化,但它不会改变实例化机制的基本工作原理。
来自 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1448.pdf
用于声明显式实例化的 extern 说明符 类模板仅禁止显式实例化定义 成员函数和静态数据成员以前不专门化 在包含声明的翻译单元中。
因此,如果在 A 中需要 B 的定义,则在不知道 B 的情况下不能使用 extern template
。您当然可以尝试摆脱该要求。在给定的情况下,您可以删除 using t
声明并有一个元函数来生成该类型:
template<typename T>
struct get_a_t;
template<typename T>
struct get_a_t<A<T>>
{
using type = typename T::a_t;
};
不确定在您的情况下是否可行。只要 A 需要存储B
或B::a_t
,就需要B
。不过,引用和指针是可以的。
最后一个外部模板类 A 告诉编译器,在某个编译单元中存在此类模板专用化的声明。编译器继续,然后链接器应该抱怨找不到正确的类。它不是畸形的;这取决于用例。您可以在单独的 cpp 文件中定义模板 A。如果你一遍又一遍地编译它,这显然只会减少一点编译时间。您可以执行不同的结构:
一个只有 A 类模板的 a.hpp。
一个 B.cpp 文件,其中包含 B 类及其 .h 文件。(是模板吗?
b.cpp 包括 a.hpp,并在内部创建一个显式模板实例化模板类 A;(不是与外部(。
此时,每当您需要使用该模板时,您只需编写即可
外部模板A类;
并链接编译后的 B.cpp 文件。如果包含 a.hpp 文件,因为您仍然需要模板,则不会重新编译它,因为您有 extern 命令。
- 调用外部函数,无法指定类型 C++/MVS
- 使用外部定义的模板类型作为模板参数的更通用模板的模板别名
- 外部基础类型未按请求对齐时的atomic_ref
- Pybind11:作为返回值的外部类型
- C++:在"try"外部创建的类型会导致错误,但在内部不会
- 外部 "C" Visual Studio 2015 中的显式类型错误,DLL 测试代码
- 函数类型定义可以与外部"C"相关联吗?
- 从内部类型参数推断外部类型
- 使用从外部参数包中获取的参数类型声明函数
- 为什么对非类型模板参数的引用需要外部链接
- 获取外部媒体类型
- 外部函数指针声明和类型推断定义
- C++:检查是否在没有外部库的情况下抛出了某个异常类型
- 外部模板,用于使用非竞争类型参数化的模板
- 类型是否只有内部/外部链接以外的"链接"?
- 错误 C2899:不能在模板声明外部使用类型名
- 类类型的矢量导致未解决的外部符号错误LNK2019
- 外部模板和不完整的类型
- 可变类型的部分模板专门化和扩展到外部类型的可变参数包会导致歧义
- "外部"C""是函数类型的一部分吗?