考虑以下小代码片段:
#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;
}
Live Example为Clang和g ++编译并打印0。
这是关于功能模板实例化的draft Standard引用
14.6.4.1实例化点[temp.point]
1用于函数模板特化,成员函数模板特化或特殊化 如果专门化是隐式实例化的,则为类模板的成员函数或静态数据成员 因为它是从另一个模板特化和引用它的上下文中引用的 取决于模板参数,专业化的实例化点是 封闭专业化的实例化。否则,这种专业化的实例化点 紧跟在引用特化的命名空间范围声明或定义之后。
Vandevoorde and Josuttis有以下说法:
在实践中,大多数编译器会延迟实际的实例化 非翻译功能模板到翻译单元的末尾。这个 有效地移动相应模板的POI 专业化到翻译单元的末尾。意图 C ++语言设计者认为这是一个有效的实现 技术,但标准没有明确这一点。
问题:Clang / g ++是否符合规定,因为它们会将POI延迟到翻译单元的末尾?
答案 0 :(得分:7)
Core Working Group defect report 993是为了解决此问题:
<强> 993。自由在翻译单元结束时执行实例化
栏目:14.6.4.1 [temp.point]状态:C ++ 11发布者:John Spicer日期:2009年3月6日
[在2011年3月的会议上投票进入WP。]目的是在翻译单元的末尾而不是实际的实例化点进行模板实例化是一种允许的实现技术。然而,这个想法并没有反映在现行规则中。
提议的决议(2011年1月):
将14.6.4.1 [temp.point]第7段改为:
函数模板,成员函数模板或类模板的成员函数或静态数据成员的特化可能在翻译单元中具有多个实例化点,以及实例化点之外如上所述,对于在翻译单元中具有实例化点的任何此类专业化,翻译单元的结尾也被视为实例化点。类模板的专门化......
C ++ 11中的第14.6.4.1/7段在N3936中是14.6.4.1/8:
功能模板,成员函数模板或成员函数或静态的特化 类模板的数据成员可以在翻译单元内具有多个实例化点,以及 除了上面描述的实例化点之外,对于任何具有重点的专业化 在翻译单元内的实例化中,翻译单元的末尾也被认为是一个点 实例。类模板的特化在翻译中最多只有一个实例化点 单元。任何模板的特化可以在多个翻译单元中具有实例化点。如果 两个不同的实例化点给出了模板特化根据一个不同的含义 定义规则(3.2),程序格式错误,无需诊断。
所以是的,允许实现将模板实例化的时间延迟到翻译单元的末尾。
答案 1 :(得分:3)
在编译时显式调用模板后显式专门化。
#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;
}
检查编译错误here
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)