最近,当我尝试优化我的包含层次结构时,我偶然发现文件a.hpp
:
template<class T>
class A
{
using t = typename T::a_t;
};
class B;
extern template class A<B>;
似乎是不正确的。事实上,似乎最后的extern模板语句导致A<B>
的实例化导致编译器抱怨不完整的类型。
我的目标是在A<B>
中定义a.cpp
:
#include <b.hpp>
template class A<B>;
这样我就不必在b.hpp
中包含a.hpp
,这似乎是减少编译时间的好主意。但是它不起作用(a.hpp
本身没有编译!)有更好的方法吗?
注意:当然我可以不使用显式模板实例化,但这不是我想要的!我想&#34;预编译&#34;如果使用了A<B>
,则A<B>
可以节省编译时间,但如果未使用b.hpp
,我不想在使用a.hpp
的每个文件中加入 float elevation = cardView.getMaxCardElevation();
float radius = cardView.getRadius();
double cos45 = Math.cos(Math.toRadians(45));
int horizontalPadding = (int) (elevation + (1 - cos45) * radius);
int verticalPadding = (int) (elevation * 1.5 + (1 - cos45) * radius);
!< / p>
答案 0 :(得分:1)
extern模板声明阻止了成员函数体的实例化,但它强制实例化类定义,因为无论如何编译器都需要它,并且类体需要模板参数的完整定义,因为它访问它的成员。我担心将{B}的身体隐藏在A<B>
的用户身上是不可能的。
extern模板是一种优化,但它不会改变实例化机制的基本工作方式。
答案 1 :(得分:0)
最后的extern模板类A告诉编译器在某个编译单元中存在这种模板特化的声明。编译器继续,然后链接器应该抱怨没有找到正确的类。它没有生病;这取决于用例。您可以在单独的cpp文件中定义模板A.如果您反复编译它,这显然会减少一点编译时间。你可以做不同的结构:
只有A类模板的一个a.hpp。
一个带有B类的b.cpp文件及其.h文件。 (它是模板吗?)
b.cpp包含a.hpp,在其中创建一个explicite模板实例化模板类A; (不是extern)。
此时,只要您需要使用该模板,您就可以编写
extern模板类A;
在您的文件中并链接已编译的b.cpp文件。如果你包含a.hpp文件,因为你仍然需要模板,你就不会重新编译它,因为你有extern命令。
答案 2 :(得分:0)
来自http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1448.pdf
extern说明符用于声明a的显式实例化 类模板仅抑制定义的显式实例化 以前没有专门的成员函数和静态数据成员 在包含声明的翻译单元中。
因此,如果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
。不过,引用和指针都可以。