模板的typedef是否保留静态初始化顺序?

Jos*_*vin 3 c++ static templates typedef initialization

在同一个编译单元中,C++标准说明了静态初始化顺序 - 它是静态对象声明的顺序.但是使用Sun Studio 12编译器我遇到了不直观的行为.我定义了一个模板化的类helper<T>,它包含一个静态_data类型T的成员和一个使用_data被调用的静态成员函数foo.在我的.cpp文件中,我有以上main():

struct A { /* some definition */ };

typedef helper<int> s0;
typedef helper<A> s1;
Run Code Online (Sandbox Code Playgroud)

请注意,对于typedef的helper<int>来自之前的的typedef helper<A>.因此,根据标准,我预计helper<int>::_data将在之前构建helper<A>::_data(记住_data是静态成员).在海湾合作委员会就是这种情况,在Sun上并非如此.

这是有问题的,因为A的构造函数使用helper<int>::_data.我只有一个编译单元,没有早期的潜在实例化helper<A>,所以我认为订单应该很好地定义.这是一个Sun编译器错误,还是typedef技术上不构成定义/实例化?我的意思是,标准允许Sun编译器的行为吗?

我有以下main():

int main()
{
    //Swapping the order of these has no effect on Sun
    s0::foo();
    s1::foo();
}
Run Code Online (Sandbox Code Playgroud)

s0或s1没有其他用途.

Joh*_*itb 6

在同一个编译单元中,C++标准说明了静态初始化顺序 - 它是静态对象声明的顺序.

在您显示的代码中,您没有声明静态数据成员.您有一个typedef-name的声明.这些与此无关,也不影响任何订单.您可能会想到这样:

如果我发出typedef声明,它将实例化helper<int>,从而首先实例化其静态数据成员声明.

问题是,该行不会导致实例化helper<int>.要做到这一点,你需要一个显式的实例化或管理让它隐式实例化它(helper<int>例如,创建一个对象,或者将其用作嵌套的名称说明符,helper<int>::...并明确引用静态成员 - 否则,创建它是中省略).

但是还有一个更深层次的问题.该顺序不是静态数据成员的声明.订单是他们的定义.考虑以下

struct C { C() { printf("hey\n"); } };
struct A { 
  static C a;
  static C b;
};

C A::b;
C A::a;
Run Code Online (Sandbox Code Playgroud)

在此代码中,b在a之前创建,即使a在b之前声明.

以下代码打印2 1:

struct C { C(int n) { printf("%d\n", n); } };

template<int N>
struct A {
  static C c;
};

template<int N>
C A<N>::c(N);

// explicit instantiation of declaration and definition
template struct A<2>;
template struct A<1>;

int main() {

}
Run Code Online (Sandbox Code Playgroud)

但是下面的代码什么都不打印,除非你在行中注释main.

struct C { C(int n) { printf("%d\n", n); } };

template<int N>
struct A {
  static C c;
};

template<int N>
C A<N>::c(N);

// implicit instantiation of declarations
A<2> a2;
A<1> a1;

int main() {
  // A<1>::c; A<2>::c;
}
Run Code Online (Sandbox Code Playgroud)

我真的不确定第二个片段的正确输出是什么.阅读标准,我无法确定订单.它在14.6.4.1"实例化点"中说:

对于函数模板特化,成员函数模板特化,或成员函数或类模板的静态数据成员的特化,如果特化是隐式实例化的,因为它是从另一个模板特化中引用的[...].否则,这种特化的实例化点紧跟在引用特化的命名空间范围声明或定义之后.

它们的定义实例化的点都出现在定义之后main.在另一个定义似乎未指定之前实例化了哪个定义.如果有人知道答案和khow其他编译器的行为(GCC打印,1 2但在main交换,打印的表达顺序2 1),请在评论中告诉我.

有关详细信息,请参阅有关静态对象生命周期的答案.