Is static member variable initialized in a template class if the static menber is not used?
Asked Answered
O

2

3

Is static member variable initialized in a template class if the static member is not used? I use it to register the type.

template<class T>
class A
{
    static bool d;
};

template<class T> bool A<T>::d = [](){regist<A<T>>(); return true;}();

int main()
{
   A<int> a;
   return 0;
}

I find a way to test it. It prints 1 other than 2. The regist() is not called abd the static member is not initialized. My testing is on VC110 compilter. And I also test it online

#include <iostream>
using namespace std;

int i = 1;

template<class T>
void regist()
{
    ++i;
}

template<class T>
class A
{
    static bool d;
};

template<class T> bool A<T>::d = [](){regist<A<T>>(); return true;}();

int main()
{
    A<int> a;
    cout << i << endl;
    return 0;
}
Octogenarian answered 13/10, 2013 at 2:53 Comment(2)
You may want to read this Q&A for a cleaner-looking way to do initialization (although it would share the same approach as yours).Organdy
The other thing is that in your example you even make a declaration of A and it has the same behavior as if you don'tLynd
S
3

The relevant section of the C++ draft standard comes under 14 Templates which is 14.7.1 Implicit instantiation paragraph 2 which says(emphasis mine):

Unless a member of a class template or a member template has been explicitly instantiated or explicitly specialized, the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist; in particular, the initialization (and any associated side-effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist.

We can also see paragraph 8 which says:

The implicit instantiation of a class template does not cause any static data members of that class to be implicitly instantiated.

However if you add an explicit instantiation to the second case as follows you will see 2 as the results:

template<> bool A<int>::d = [](){regist<A<int>>(); return true;}();
Stockjobber answered 13/10, 2013 at 3:41 Comment(0)
L
2

Yes it is initialized run this sample program, but only because it is forced to exist.

template <class T>                                                                 
struct A                                                                           
{                                                                                  
    static int b;                                                                  
};                                                                                 
template <class T> int A<T>::b = 10;                                               
#include <iostream>                                                                
using namespace std;                                                               
int main() {                                                                       
    cout << A<int>::b << endl;                                                     
    return 0;                                                                      
}   

I believe this quote from the standard may clarify any doubts

[Note: Once the static data member has been defined, it exists even if no objects of its class have been created. [ Example: in the example above, run_chain and running exist even if no objects of class process are created by the program. — end example ] — end note ]

Here is a relavent part of the standard that confirms your suspicisions.

Unless a class template specialization has been explicitly instantiated (14.7.2) or explicitly specialized (14.7.3), the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined object type or when the completeness of the class type affects the se- mantics of the program. The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions or default arguments, of the class member func- tions, member classes, static data members and member templates; and it causes the implicit instantiation of the definitions of member anonymous unions. Unless a member of a class template or a member template has been explicitly instantiated or explicitly specialized, the specialization of the member is implicitly in- stantiated when the specialization is referenced in a context that requires the member definition to exist; in particular, the initialization (and any associated side-effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist.

The two parts I highlighted in bold I think clear up your issue. Clearly the reason for this behavior is that if no explicit specialization is given the compiler has no way to decide how many times the code should be executed (infinite possible types)

Lynd answered 13/10, 2013 at 2:59 Comment(11)
It is a different case where the static member is used to print.Octogenarian
@Octogenarian why, am I not understanding something about the question, if you use it you use itLynd
@Lynd OP wants the variable to remain completely unused. He does not care for its value, all he wants is the side effect of initialization to take place. He does not want to force an access to the variable to see that it is not "optimized out", either.Organdy
@dasblinkenlight do you think it will be optimized out, IMO noLynd
@Lynd If you could find something in a standard that says that it wouldn't, that would be an answer to the OP's question. I do not think that the variable would get optimized out, but I cannot remember a place in the standard where it would say something like that about unused static members. EDIT : I just read your edit, I think that's it!Organdy
@dasblinkenlight that's not surprising if you remember the whole standard than you are a god among menLynd
See my testing code posted above. It print 1 other than 2. Thus the static member is not initialized.Octogenarian
@Octogenarian strange, there may be something in the standard saying static member initialization cannot have side effectsLynd
@Lynd If putting the static member in normal class, what you said is right.Octogenarian
@Octogenarian well you see the weird thing is regist can't be called because how could the compiler decide how many times to call it, try getting rid of regist's template and see what happnesLynd
let us continue this discussion in chatLynd

© 2022 - 2024 — McMap. All rights reserved.