外部模板&不完整的类型

时间:2016-01-07 14:12:46

标签: c++ templates c++11 incomplete-type

最近,当我尝试优化我的包含层次结构时,我偶然发现文件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>

3 个答案:

答案 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需要存储BB::a_t,您就需要B。不过,引用和指针都可以。