何时检查C ++模板实例化类型?

时间:2015-12-10 14:32:11

标签: c++ templates

在编译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 ++编译器接受此顺序吗?

1 个答案:

答案 0 :(得分:5)

该规则称为“两阶段名称查找”。

在定义时查找并检查不依赖于模板参数的名称,并在实例化时检查依赖名称

对于您的示例,有一个重要细节:翻译单元的结尾也被视为功能模板的实例化点:

C ++ 14 N4140 14.6.4.1 [temp.point] P8:

  

功能模板,成员函数模板或成员函数或静态的特化   类模板的数据成员可以在翻译单元内具有多个实例化点,以及   除了上面描述的实例化点之外,对于任何具有重点的专业化   在翻译单元内的实例化中,翻译单元的末尾也被认为是一个点   实例

因此,尽管类型在点“2”处是不完整的,但是在显式实例化发生时,它在文件末尾完成,这使得模板实例化合法。

注意:Microsoft编译器未完全实施此规则,违反了标准。在Microsoft编译器中,所有查找都在实例化时发生(因此该示例也应该有效,但我无法访问MSVC进行检查)。其他主要编译器确实正确实现了此规则。