2

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

C++11 允许这个 via extern template,但这里的问题是我只想键入一次的Derived-specific 实例化Base。从技术上讲这是可能的,因为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声明不必出现在任何实例化之前,所以第二个问题仍然有意义。

4

1 回答 1

0

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

此外,显式实例化声明必须在任何隐式实例化源之前有效。如果您只想为该特化的模板参数命名一次,请在显式实例化声明Derived.

于 2021-01-28T22:20:36.850 回答