Внутри той же единицы компиляции стандарт 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;
В этом коде b создается перед , даже если 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() {
}
Но следующий код ничего не печатает, если вы не прокомментируете строку в 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;
}
Я не совсем уверен, что правильный вывод для этого второго фрагмента. Читая стандарт, я не могу определить порядок. В 14.6.4.1
«Точка инстанции» говорится:
Для специализации шаблона функции, специализации шаблона функции-члена или специализации для функции-члена или статического члена данных шаблона класса, если специализация создается неявно, так как на нее ссылаются из другой специализации шаблона [... ]. В противном случае точка создания такой специализации сразу следует за объявлением или определением области пространства имен, относящимся к специализации.
Точка создания их определений появляется сразу после определения main
. Какое определение создается до того, как другое определение, кажется, не определено. Если кто-то знает ответ и как другие компиляторы ведут себя (GCC печатает 1 2
, но с порядком выражений в main
swapped, печатает 2 1
), пожалуйста, дайте мне знать в комментарии.
Подробнее см. этот ответ о времени жизни статического объекта .