考虑以下小代码片段:
#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。
这是 标准草案 引用功能模板的实例化
14.6.4.1实例化点[temp.point]
1对于函数模板特化,成员函数模板特化或特化
如果专门化是隐式实例化的,则为类模板的成员函数或静态数据成员
因为它是从另一个模板专门化和引用它的上下文中引用的
取决于模板参数,专业化的实例化点是
封闭专业化的实例化。否则,这种专业化的实例化点
紧跟在引用特化的命名空间范围声明或定义之后。
Vandevoorde和Josuttis 有以下说法:
在实践中,大多数编译器会延迟实际的实例化
非翻译功能模板到翻译单元的末尾。这个
有效地移动相应模板的POI
专业化到翻译单元的末尾。意图
C ++语言设计者认为这是一个有效的实现
技术,但标准并未明确这一点。
题:Clang / g ++不符合规定,因为它们将POI延迟到翻译单元的末尾?
核心工作组缺陷报告993 是为了解决这个问题而创建的:
993.在翻译单位结束时自由进行实例化
条:14.6.4.1 [temp.point]状态:C ++ 11发布者:John Spicer日期:2009年3月6日
[2011年3月会议上投票支持WP。]
目的是在翻译单元的末尾而不是实际的实例化点进行模板实例化是一种允许的实现技术。然而,这个想法并没有反映在现行规则中。
拟议决议(2011年1月):
更改14.6.4.1 [临时点]第7段如下:
函数模板,成员函数模板或类模板的成员函数或静态数据成员的特化可以在翻译单元中具有多个实例化点, 除了上述实例化点之外,对于在翻译单元内具有实例化点的任何这种专业化,翻译单元的末尾也被认为是实例化的点。 类模板的专业化......
C39 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)