繁体   English   中英

extern模板和不完整的类型

[英]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>;

这样,我避免必须包括b.hppa.hpp这似乎是一个好主意,以减少编译时间。 但它不起作用( a.hpp本身不编译!)有更好的方法吗?

注意:当然我可以不使用显式模板实例化,但这不是我想要的! 我想“预编译” A<B>以节省编译时间,如果它被使用,但如果A<B>不使用我不希望包括b.hpp在使用每一个文件a.hpp

extern模板声明阻止了成员函数体的实例化,但它强制实例化类定义,因为无论如何编译器都需要它,并且类体需要模板参数的完整定义,因为它访问它的成员。 我担心将B的身体隐藏在A<B>使用者A<B>是不可能的。

extern模板是一种优化,但它不会改变实例化机制的基本工作方式。

最后的extern模板类A告诉编译器在某些编译单元中存在这种模板特化的声明。 编译器继续,然后链接器应该抱怨没有找到正确的类。 它没有生病; 这取决于用例。 您可以在单独的cpp文件中定义模板A.如果您反复编译它,这显然会减少一点编译时间。 你可以做不同的结构:

只有A类模板的一个a.hpp。

一个带有B类的b.cpp文件及其.h文件。 (它是模板吗?)

b.cpp包含a.hpp,在里面你做一个explicite模板实例化模板类A; (不是外部)。

此时,只要您需要使用该模板,您就可以编写

extern模板类A;

在您的文件中并链接已编译的b.cpp文件。 如果您包含a.hpp文件,因为您仍然需要该模板,因为您有extern命令,所以不会重新编译它。

来自http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1448.pdf

用于声明类模板的显式实例化的extern说明符仅抑制成员函数和静态数据成员的定义的显式实例化,这些成员函数和静态数据成员以前没有专门用于包含声明的转换单元。

因此,如果A中需要B的定义,则不能在不知道B的情况下使用extern template 。您当然可以尝试去除该要求。 在给定的情况下,您可以删除using t声明并使用meta函数来生成该类型:

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 不过,引用和指针都可以。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM