编译 C++ 时,gcc 和 clang 似乎会推迟模板实例化的类型检查,直到程序的所有声明都已处理完毕。这在语言中得到保证吗?
详细地说,我可以在定义模板或需要模板实例化时保持类型不完整,只要我稍后在程序中的某个地方完成该类型即可:
class A;
class B;
extern A* pa;
// 1. template definition
template<typename T>
T* f() { return static_cast<T*>(pa); }
// 2. template instantiation
B* test() { return f<B>(); }
// 3. completing types
class A { };
class B : public A { };
请注意,需要 A 和 B 的定义来对模板实例化进行类型检查(以使 static_cast 有效)。如果省略步骤 3,步骤 2 将不再编译。
在我的头文件的组织中,我可以相信任何标准 C++ 编译器都会接受此顺序吗?
该规则称为“两阶段名称查找”。
不依赖于模板参数的名称在定义时查找和检查,并且从属名称在实例化点进行检查。
对于您的示例,有一个重要的细节:翻译单元的末尾也被视为函数模板的实例化点:
C++14 N4140 14.6.4.1 [温度点] P8:
函数模板、成员函数模板或者成员函数或静态的特化
类模板的数据成员可以在翻译单元内具有多个实例化点,并且
除了上面描述的实例化点之外,对于任何具有点的此类专业化
翻译单元内的实例化,翻译单元的末尾也被认为是一个点
实例化。
因此,尽管类型在发生显式实例化的点“2”处不完整,但它在文件末尾是完整的,这使得模板实例化合法。
Note:微软编译器没有完全实现这个规则,违反了标准。在 Microsoft 编译器中,所有查找都发生在实例化点(因此该示例也应该有效,但我无法访问 MSVC 进行检查)。其他主要编译器确实正确地实现了此规则。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)