带有别名负载的外部模板声明

extern template declaration with alias payload

考虑一下。有一个 class Derived 继承自大量模板化 class Base 的一些实例化,并且 Derived 在各种源文件中有很多用途。因此,只有一个 Derived 特定的 Base.

实例化是合理的

C++11 通过 extern template 允许这样做,但这里的问题是我只想键入 BaseDerived 特定实例化一次。从技术上讲这是可能的,因为 Derived 可以为该实例化保留别名,但问题是:它是否仍会强制编译器不实例化模板?

这里是尝试:

// Base.hpp
template < typename Arg > struct Base { using TheArg = Arg; };

// Derived.hpp
#include "Base.hpp"
struct Derived : Base<int> { };
// The next line will be huge in real-world scenario, so I want to avoid it.
// extern template struct Base<int>;
// Instead I want this.
extern template struct Base<Derived::TheArg>;

// Derived.cpp
#include "Derived.hpp"
template struct Base<Derived::TheArg>;

// Use01.cpp
#include "Derived.hpp"
void use01() { Derived dd; }

这里的重点是强制 Use01.cpp 不实例化 Base<int> 而是引用 Derived.cpp 处的显式实例化。

我正在使用 gcc-v9.3 进行编译,问题是:

  1. extern template 声明是否对翻译单元中的所有实例化生效,还是仅对出现在 其声明后的实例化生效?
  2. 使用 Derived::TheArg 而不是 int 会导致延迟实例化的任何问题吗?

extern template 声明放在 Use01.cpp 的末尾并注释掉 Derived.cpp 处的显式实例化会使编译失败,所以这让我对 extern template 声明不必出现在任何实例化之前,所以第二个问题仍然有意义。

class 模板特化的显式实例化声明不会 阻止实例化该特化。毕竟,您仍然需要能够引用结果 class 的成员,这意味着了解其布局的一切。它所做的是防止实例化其(非内联)成员函数,因此不需要为它们发出代码。

此外,显式实例化声明必须先于任何隐式实例化源才能生效。如果你只想命名该特化的模板参数一次,请在显式实例化声明 定义 Derived.

之前为其引入类型别名