什么时候检查C ++模板实例化类型? [英] When is a C++ template instantiation type checked?

查看:122
本文介绍了什么时候检查C ++模板实例化类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当编译C ++时,gcc和clang似乎推迟了模板实例化的类型检查,直到程序的所有声明都被处理完毕。这是在语言中保证的吗?



要详细说明,我可以保持一个类型不完整的点,模板定义或模板实例化需要,只要我在程序后面的某处完成类型:

 类A; 
class B;

extern A * pa;

// 1.模板定义
模板< typename T>
T * f(){return static_cast< T *>(pa); }

// 2.模板实例化
B * test(){return f< B(); }

// 3.完成类型
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检查)。其他主要编译器会正确实现此规则。


When compiling C++, gcc and clang seems to postpone the type-checking of template instantiations until after all declarations of the program have been processed. Is this guaranteed in the language?

To elaborate, I can keep a type incomplete at the point where a template is defined or a template instantiation is needed, as long as I complete the type somewhere later in the program:

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 { };

Note that the definitions of A and B are required to type check the template instantiation (to make the static_cast valid). If you leave out step 3, step 2 will no longer compile.

In the organisation of my headers, can I rely that this order will be accepted by any standard C++ compiler?

解决方案

The rule is called "two-phase name lookup".

The names, which are not dependant on the template parameters, are looked up and checked at definition, and the dependent names are checked at the point of instantiation.

For your example, there is one important detail: the end of translation unit is also considered a point of instantiation for function templates:

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

A specialization for a function template, a member function template, or of a member function or static data member of a class template may have multiple points of instantiations within a translation unit, and in addition to the points of instantiation described above, for any such specialization that has a point of instantiation within the translation unit, the end of the translation unit is also considered a point of instantiation.

Thus, although the type is incomplete at point "2", where explicit instantiation happens, it is complete at the end of file, which makes the template instantiation legitimate.

Note: Microsoft compiler does not implement this rule in full, violating the standard. In Microsoft compiler, all the lookup happens at the point of instantiation (thus the example should also work, but I don't have access to MSVC to check). Other major compilers do implement this rule correctly.

这篇关于什么时候检查C ++模板实例化类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆