C++ 为什么这个循环模板实例化是合法的?
我不明白编译器在这里做什么:C++ 为什么这个循环模板实例化是合法的?,c++,templates,instantiation,circular-reference,C++,Templates,Instantiation,Circular Reference,我不明白编译器在这里做什么: #include <iostream> using namespace std; // non-default-constructable struct struct X { X(int v) : x(v) {} const int x; }; template< typename T> struct A { static const X a; }; // trigger a compiler error if
#include <iostream>
using namespace std;
// non-default-constructable struct
struct X
{
X(int v) : x(v) {}
const int x;
};
template< typename T>
struct A
{
static const X a;
};
// trigger a compiler error if we try to instantiate the default template
template< typename T >
const X A<T>::a;
template<>
struct A<int>
{
static const X a;
};
template<>
struct A<float>
{
static const X a;
};
// is this not infinitely circular?
const X A<int>::a = X(A<float>::a.x + 1);
const X A<float>::a = X(A<int>::a.x + 1);
int main() {
// error as expected, A<bool>::a cannot be default-constructed
// cout << A<bool>::a.x << endl;
// this compiles and prints "1 2"
cout << A<int>::a.x << " " << A<float>::a.x << endl;
return 0;
}
#包括
使用名称空间std;
//非默认可构造结构
结构X
{
X(intv):X(v){}
常数int x;
};
模板
结构A
{
静态常数xa;
};
//如果尝试实例化默认模板,则触发编译器错误
模板
常数xa::A;
模板
结构A
{
静态常数xa;
};
模板
结构A
{
静态常数xa;
};
//这不是无限循环吗?
常数xa::A=X(A::A.X+1);
常数xa::A=X(A::A.X+1);
int main(){
//错误如预期,无法默认构造A::A
//cout这恰好是非局部变量初始化的副作用。标准规定:
3.6.2非局部变量的初始化[basic.start.init]
具有静态存储持续时间(3.7.1)或线程存储持续时间(3.7.2)的变量应初始化为零(8.5)
在进行任何其他初始化之前…
…应在进行任何动态初始化之前执行静态初始化。
具有静态存储持续时间的非局部变量的动态初始化是无序的,如果该变量是
隐式或显式实例化专门化,否则是有序的[注:显式专门化
静态数据成员或变量模板专门化已命令初始化。-结束说明]变量
如果在单个翻译单元内定义了有序初始化,则应按照其顺序初始化
翻译单位中的定义
这正是这里发生的事情:
A::A
和A::A
都初始化为0
- 然后按照定义的顺序初始化它们
- 首先
A::A
读取A::A
中的内容,由于之前的0初始化,该内容为0,添加1,并用1完全初始化
- 然后
A::A
获取现在完全初始化的A::A
的值,该值为1,加1,并用2完全初始化
这意味着这是一个结构良好的计划
但同一段后来说:
如果对象obj1的初始化引用命名空间范围的对象obj2
它可能需要动态初始化,稍后在同一翻译单元中定义,未指定
使用的obj2值是否将是完全初始化的obj2的值(因为obj2是静态的)
初始化)或将是obj2的值仅初始化为零
因此,我不确定输出是否需要为12,或者如果A::A
的动态初始化首先触发A::A的动态初始化,它是否可以为2,1不,它不是,它是未定义的行为。A::A在A:A之前没有被赋值,这意味着您只是在读取随机内存