在编译C++时,gcc和clang似乎推迟了模板实例化的类型检查,直到处理完所有程序声明之后.这种语言有保证吗?
为了详细说明,我可以在定义模板或需要模板实例化的位置保持类型不完整,只要我在程序的后面某处完成类型:
class A; class B; extern A* pa; // 1. template definition templateT* f() { return static_cast (pa); } // 2. template instantiation B* test() { return f(); } // 3. completing types class A { }; class B : public A { };
请注意,A和B的定义需要键入检查模板实例化(以使static_cast有效).如果省略步骤3,则不再编译第2步.
在我的标题组织中,我可以依赖任何标准C++编译器接受此顺序吗?
该规则称为"两阶段名称查找".
在定义时查找并检查不依赖于模板参数的名称,并在实例化时检查从属名称.
对于您的示例,有一个重要细节:翻译单元的结尾也被视为功能模板的实例化点:
C++ 14 N4140 14.6.4.1 [temp.point] P8:
函数模板,成员函数模板或类模板的成员函数或静态数据成员的特化可以在翻译单元内具有多个实例化点,并且除了上述实例化的点之外,对于任何这样的实例化.在翻译单元内具有实例化点的专门化,翻译单元的末尾也被认为是实例化的点.
因此,虽然类型在点"2"处是不完整的,但是在发生显式实例化的情况下,它在文件末尾完成,这使得模板实例化合法.
注意:Microsoft编译器未完全实现此规则,违反了标准.在Microsoft编译器中,所有查找都在实例化时发生(因此该示例也应该有效,但我无法访问MSVC进行检查).其他主要编译器确实正确实现了此规则.