考虑 module.context p7 中的以下示例
//Translation unit #1:
export module stuff;
export template<typename T, typename U> void foo(T, U u) { auto v = u; }
export template<typename T, typename U> void bar(T, U u) { auto v = *u; }
//Translation unit #2:
export module M1;
import "defn.h"; // provides struct X {};
import stuff;
export template<typename T> void f(T t) {
X x;
foo(t, x);
}
// Translation unit #3:
export module M2;
import "decl.h"; // provides struct X; (not a definition)
import stuff;
export template<typename T> void g(T t) {
X *x;
bar(t, x);
}
// Translation unit #4:
import M1;
import M2;
void test() {
f(0);
g(0);
}
对于f(0)
,评论说
foo<int,> 的实例化上下文包括
- 翻译单元 #1 末尾的点,
- 翻译单元 #2 末尾的点,以及
- 调用 f(0) 的点,
我能理解第一点,因为这个规则
在模板的隐式实例化期间,其实例化点被指定为封闭专用化([temp.point]),实例化上下文是封闭专用化的实例化上下文的并集,如果模板是在模块 M 的模块接口单元中定义的,并且实例化点不在 M 的模块接口单元中, 主模块接口单元 M 的声明序列末尾的点(在私有模块片段之前,如果有的话)。
但是,我无法弄清楚剩余的几点,尤其是第二点。如何解读这两点?
更新:
来自@Nicol波拉斯的回答
所以
foo
的"封闭专业化的实例化上下文"就是f
的实例化上下文。其中包括 TU2 的结尾,根据您引用和强调的内容。
我不认为强调的措辞说封闭专业化的实例化上下文包括"TU2 的终结"。我认为整个 [module.context#3] 应该解析为
在模板 T 的隐式实例化期间,其实例化点被指定为封闭专用化 ([temp.point]),实例化上下文是封闭专用化的实例化上下文的并集,如果模板 T是在模块 M 的模块接口单元中定义的,并且实例化点不在 M 的模块接口单元中,M 的主模块接口单元的声明序列末尾的点(在私有模块片段之前,如果有的话)。
模板T
不指定从中实例化封闭专用化的模板。
所有这些都可以追溯到你引用的内容,但没有点击链接:"封闭专业化"。从 [温度点]/1:
对于函数模板专用化、成员函数模板专用化或类模板的成员函数或静态数据成员的专用化,如果专用化是隐式实例化的,因为它是从另一个模板专用化中引用的,并且引用它的上下文取决于模板参数,则专用化的实例化点是封闭专用化的实例化点。
在 TU2 中,函数模板foo
专用于函数模板f
。f
是foo
的"封闭专业化"。
所以foo
的"封闭专业化的实例化上下文"就是f
的实例化上下文。其中包括 TU2 的结尾,根据您引用和强调的内容。
至于第三点...这只是使用f
重复的第二点。f(0)
专门f
,从而充当其实例化上下文的一部分。因为foo
被包含在f
中,这也充当foo
实例化上下文的一部分。