title: non-deferred static member initialization for templates in gcc?
body: <p>Does gcc have any guarantees about static member initialization timing, especially regarding template classes?</p>
  
  <p>I want to know if I can get a hard guarantee that static members (<code>PWrap_T&lt;T&gt;::p_s</code>) will be initialized before <code>main()</code>, when classes are instantiated across multiple compilation units. It isn't practical to try to manually touch a symbol from each compilation unit at the start of main, but it isn't clear to me that anything else would work.</p>
  
  <p>I've tested with methods like <code>bar()</code> in different units and <em>always</em> gotten the desired result, but I need to know when/if ever gcc will yank the rug out and whether it's preventable.</p>
  
  <p>Furthermore, will all static members from a DSO be initialized before a library finishes loading?</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;deque&gt;
  
  struct P;
  inline std::deque&lt;P *&gt; &amp;ps() { static std::deque&lt;P *&gt; d; return d; }
  void dump();
  
  struct P {
    P(int id, char const *i) : id_(id), inf_(i) { ps().push_back(this); }
    void doStuff() { std::cout &lt;&lt; id_ &lt;&lt; " (" &lt;&lt; inf_ &lt;&lt; ")" &lt;&lt; std::endl; }
    int  const        id_;
    char const *const inf_;
  };
  
  template &lt;class T&gt;
  struct PWrap_T { static P p_s; };
  
  // *** Can I guarantee this is done before main()? ***
  template &lt;class T&gt;
  P PWrap_T&lt;T&gt;::p_s(T::id(), T::desc());
  
  #define PP(ID, DESC, NAME) /* semicolon must follow! */  \
  struct ppdef_##NAME  {                                   \
    constexpr static int         id()   { return ID; }     \
    constexpr static char const *desc() { return DESC; }   \
  };                                                       \
  PWrap_T&lt;ppdef_##NAME&gt; const NAME
  
  // In a compilation unit apart from the template/macro header.
  void dump() {
    std::cout &lt;&lt; "[";
    for (P *pp : ps()) { std::cout &lt;&lt; " " &lt;&lt; pp-&gt;id_ &lt;&lt; ":" &lt;&lt; pp-&gt;inf_; }
    std::cout &lt;&lt; " ]" &lt;&lt; std::endl;
  }
  
  // In some compilation unit.
  void bar(int cnt) {
    for (int i = 0; i &lt; cnt; ++i) {
      PP(2, "description", pp);
      pp.p_s.doStuff();
    }
  }
  
  int main() {
    dump();
    PP(3, "another", pp2);
    bar(5);
    pp2.p_s.doStuff();
  }
  </code></pre>
  
  <blockquote>
    <p><strong>(C++11 §3.6.2/4 - [basic.start.init]:)</strong></p>
    
    <p>It is implementation-defined whether the dynamic initialization of a non-local variable with static storage duration is done before the ﬁrst statement of main. <strong>If the initialization is deferred to some point in time after the ﬁrst statement of main, it shall occur before the ﬁrst odr-use (3.2) of any function or variable defined in the same translation unit as the variable to be initialized.</strong></p>
    
    <p>... A non-local variable with static storage duration having initialization with side-effects must be initialized even if it is not odr-used (3.2, 3.7.1).</p>
  </blockquote>
  
  <p>Also, trying <code>__attribute__ ((init_priority(int)))</code> or <code>__attribute__ ((constructor))</code> for the template member's initialization yielded <code>warning: attributes after parenthesized initializer ignored</code>, and I know no other tricks regarding static initialization.</p>
  
  <p>Thanks in advance to anyone who can give me an answer about this!</p>