Note that there are some explanatory texts on larger screens.

plurals
  1. POnon-deferred static member initialization for templates in gcc?
    text
    copied!<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 first statement of main. <strong>If the initialization is deferred to some point in time after the first statement of main, it shall occur before the first 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>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload