实例化的点是否可以延迟到翻译单元结束

Can the point-of-instantiation be delayed until the end of the translation unit?

本文关键字:迟到 翻译 单元 结束 延迟 是否 实例化      更新时间:2023-10-16

考虑以下小代码片段:

#include <iostream> 
    
template<class T> 
int test(); 
    
int main() 
{     
    std::cout << test<int>() << "n"; 
} 
// POI for test<int>() should be right here      
template<class T> 
int test() 
{ 
    return 0; 
}

编译并打印Clang和g++的0的实时示例

以下是标准草案关于函数模板实例化的引用

1.4.4.1实例化点[temp.Point]

1对于函数模板专用化、成员函数模板专用性或类模板的成员函数或静态数据成员,如果专门化是隐式实例化的因为它是从另一个模板专用化和引用它的上下文中引用的取决于模板参数,专业化的实例化点是封闭专业化的实例化。否则,这种专门化的实例化点紧跟在引用专门化的命名空间作用域声明或定义之后。

Vandevoorde和Josuttis对此有以下看法:

在实践中,大多数编译器会延迟非线性函数模板到翻译单元的末尾。这有效地移动相应模板的POI专业化到翻译单元的末尾。C++语言的设计者认为这是一个有效的实现技术,但标准并没有明确说明这一点。

问题:Clang/g++是否不符合要求,因为它们将POI延迟到翻译单元的末尾?

核心工作组缺陷报告993是为了解决这个问题而创建的:

993.在翻译单元结束时执行实例化的自由

章节:14.6.4.1[临时点]状态:C++11提交人:John Spicer日期:2009年3月6日
[在2011年3月的会议上投票通过WP。]

其目的是,在翻译单元的末尾而不是在实例化的实际点进行模板实例化是一种允许的实现技术。然而,这一想法并没有反映在现行规则中。

拟议决议(2011年1月):

将14.6.4.1[温度点]第7段更改如下:

函数模板、成员函数模板或类模板的成员函数或静态数据成员的专门化可以在翻译单元内具有多个实例化点,并且除了上述实例化点之外,对于在翻译单元中具有实例化点的任何这样的专门化,翻译单元的结束也被认为是实例化的一个点类模板的专业化。。。

C++11中的第14.6.4.1/7段是N3936中的14.6.4.1/8段:

函数模板、成员函数模板或成员函数或静态的专用化类模板的数据成员可以在翻译单元内具有多个实例化点,并且除了上面描述的实例化点之外,对于任何这样的具有点的专业化在翻译单元内的实例化中,翻译单元的末尾也被认为是实例化。类模板的专门化在翻译中最多有一个实例化点单元任何模板的专业化都可以在多个翻译单元中具有实例化点。如果实例化的两个不同点赋予模板专门化不同的含义定义规则(3.2),程序格式错误,无需诊断。

因此,是的,允许实现将模板的实例化点延迟到翻译单元的末尾。

在显式调用模板后显式专门化将在编译时失败。

#include <iostream> 
template<class T> 
int test(T y);

int main() 
{     
    std::cout << test<int>(0) << "n"; 
}
template<class T> 
int test(T y) 
{ 
    return 0; 
}
// POI for test<int>() should be right here      
template<>
int test(int y) 
{ 
    return 2; 
}

检查此处的编译错误

Compilation error    time: 0 memory: 0 signal:0
prog.cpp:21:15: error: specialization of ‘int test(T) [with T = int]’ after instantiation
int test(int y)