C++20 模块导出模板实例化

des*_*sio 7 c++ templates c++20 c++-modules

我正在创建一个库,并且 C++20 模块内有一个类模板,我想添加一个实例化,以减少使用我的库的每个项目的编译时间。

这些不同的实现是否等效,或者是否有更好的方法来实现?

1)

//mod.cpp
export module mod;

export template<typename T>
struct mystruct{ T i;};

export template class mystruct<int>;
Run Code Online (Sandbox Code Playgroud)
//mod.cpp
export module mod;

export template<typename T>
struct mystruct{ T i;};

template class mystruct<int>;
Run Code Online (Sandbox Code Playgroud)
//mod.cpp
export module mod;

export template<typename T>
struct mystruct{ T i;};

export extern template class mystruct<int>;



//mod_impl.cpp
module mod;

template class mystruct<int>;
Run Code Online (Sandbox Code Playgroud)

编辑这个答案只说 2. 有效,但我的观点是 1. 和 3. 是否也等于 2.

Nic*_*las 1

模块影响两件事:名称的范围和声明的可达性。仅当它们位于模块的权限范围内时(即:在导入的模块接口 TU 中并且不在全局模块片段中),这两者才重要。

\n

在模块权限内声明的名称仅当由该export模块编辑时才能在该模块外部使用。在显式模板实例化的情况下,模板本身已经导出,因此模块外部的用户已经可以使用该名称。

\n

然而,显式模板实例化定义也是一种声明。模块控制声明的可达性。问题是,声明的可达性规则实际上并不关心export实际上

\n
\n

如果对于实例化上下文([module.context])中的任何点 P,声明 D 是可达的,

\n
    \n
  • 在同一翻译单元中,D 出现在 P 之前,或者
  • \n
  • D 不会被丢弃([module.global.frag]),出现在可从 P 到达的翻译单元中,并且不会出现在私有模块片段中。
  • \n
\n

[注:报关是否出口无关与是否可达无关\xe2\x80\x94 尾注]

\n
\n

添加了强调。

\n

这些规则只关心哪些 TU 已被导入(以及声明是否在全局/私有模块片段中)。

\n

因此,如果主模板声明已export编辑,则导入模块文件之一中的显式模板实例化(不在全局/私有模块片段中)可由导入它的任何代码访问。

\n

export因此,是否显式模板实例化并不重要。如果主模板已被export编辑,则其名称可能已被使用,因此唯一重要的是显式模板实例化是否可见。

\n

所以你的 #1 和 2 在功能上是等效的。最好不要做export一些你不需要的事情。

\n
\n

至于 的行为extern template,这很有趣。

\n

虽然extern规范化表示外部链接,但这不适用于extern template. 所以我们不存在链接问题。由于extern template模块的导入者可以访问该声明(如前所述),因此他们会看到它并尊重它。

\n

所以唯一的问题是“mod_impl.cpp”中的显式定义是否也是可达的。但这不是一个问题,因为只有定义的声明部分是“可访问的”。也就是说,可达性仅对声明重要。

\n

显式实例化定义位于不同的 TU 中。因此,它只会在该 TU 中实例化;导入模块的代码仅到达声明。因此,它不会实例化模板。

\n

所以,是的,你可以进行extern template体操(不过,export这并不重要)。但这与将显式实例化放入模块接口中没有什么不同,而且这样做更干净。

\n