3

Consider the following (artificial) example:

#include <iostream>

int f() {
  return 42;
}

template <typename T>
struct S {
  static int I;
};

template <typename T>
int S<T>::I = f();

template <typename T>
int g() {
  return S<T>::I;
}

int global = g<int>();

int main() {
  std::cout << global << std::endl;
}

It prints 0 when compiled with gcc 4.8.4 and run:

$ g++ test.cc
$ ./a.out
0

This suggests that dynamic initialization for global is run before the initialization for S<T>::I>. However, according to this SO answer,

objects defined in the same translation unit (usually it means .cpp file) are initialized in order of their definitions

Why is dynamic initialization for global run before the one for S<T>::I> and not in the order of their definitions and is it possible to force global be initialized after?

vitaut
  • 49,672
  • 25
  • 199
  • 336
  • [clang gives 42](http://coliru.stacked-crooked.com/a/169879aab97b4357) (and VS2015 gives 0) – Borgleader Jul 18 '18 at 16:49
  • 4
    http://eel.is/c++draft/basic.start.dynamic#1 – Casey Jul 18 '18 at 16:52
  • I wonder if there is any trick to force the desired initialization here. – vitaut Jul 18 '18 at 17:10
  • "Why is dynamic initialization for global run before the one for S::I> and not in the order of their definitions" because `template int S::I = f();` is not a definition, it is defined when you instantiate it, when you call `g()` and that's after `global` defined – Slava Jul 18 '18 at 17:43

1 Answers1

1

Since the initialization of S<T>::I is unordered, the value for S<int>::I can be either 0 (if it is initialized after global) or 42 (if initialized before global).

While you can't force the compiler to initialize I before global, with a slight change in your code you can employ the same method used to order static variables defined in different translation units. By changing I to a function that stores its value in an internal static variable, you can ensure that it is initialized before global.

template <typename T>
struct S {
  static int I() {
    static int i = f();
    return i;
  }
};

template <typename T>
int g() {
  return S<T>::I();
}
1201ProgramAlarm
  • 32,384
  • 7
  • 42
  • 56