1

consider the following code:

//header.h
template<class T>
class A
{
    static int x;
};

template<class T>
int A<T>::x = 0;

//source1.cpp
#include "header.h"
void f(){} // dummy function


//main.cpp
#include "header.h"
int main(){}

In this case code compiles perfectly without errors, but if I remove the template qualifier from class

class A
{
    static int x;
};

int A::x = 0;
  1. In this case compiler erred with multiple definition of x. Can anybody explain this behavior?
  2. And when the template class's static variable is initialized / instantiated??
4
  • 1) Class template members are only instantiated when needed. 2) that's a tricky question. Commented Apr 27, 2015 at 7:40
  • possible duplicate of Template static variable Commented Apr 27, 2015 at 7:50
  • In short, never instantiate statics in header files, this will almost every time make trouble. Every time the header file gets included, the statics gets instantiated. Commented Apr 27, 2015 at 8:35
  • Actually, when your class is template, compiler handles the multiple definition. My question is, is this static in initialized and instantiated without using this class? Commented Apr 27, 2015 at 9:52

4 Answers 4

3

Compiler will remove duplicate template instantiations on its own. If you turn your template class into regular one, then its your duty to make sure only one definition of static variable exists (otherwise linker error will appear). Also remember that static data members are not shared between instatiations of templates for different types. With c++11 you can control instatiations on your own using extern templates: using extern template (C++11).

As for the point of instatiation for static members:

14.6.4.1 Point of instantiation [temp.point] 1 For a function template specialization, a member function template specialization, or a specialization for a member function or static data member of a class template, if the specialization is implicitly instantiated because it is referenced from within another template specialization and the context from which it is referenced depends on a template parameter, the point of instantiation of the specialization is the point of instantiation of the enclosing specialization. Otherwise, the point of instantiation for such a specialization immediately follows the namespace scope declaration or definition that refers to the specialization.

so point of instatiation should be ie. right after main() if you use your type for the first time inside main().

Sign up to request clarification or add additional context in comments.

2 Comments

So when C++ standard insists that all static data should be initializes before main does not bother this case, am I correct?
Constructors of static members of template class will surely be executed before main executes. POI (Point Of Instation) is created when a code construct referes to a template specialization in such a way that its definition is required.
0

Templates as the name suggest are the the fragments of code that will be used several times for different parameters. For templates the compiler is to ensure if their methods and static fiels definition are linked only ones. So if you create a static field with its default value the compiler is obliged to provide single memory cell (for the same template parameter set) even though the template class header is included several times. Unfortunetly non-template classes you need to be managed by yourself.

As for the second question, I believe the standard does not state when the static fields need to be initialized, each compiler can implement then it in its own manner.

Comments

0
  1. It is necessary to instantiate/initialize static members in cpp files not in headers. Static members are property of class not property of objects, so if you include header file in more cpp files, it looks like you are initializing it more times.

  2. Answer to this question is more complex. Template is not one class. It is instantiating on demand. It means that every different use of template is one standalone "template instance". For example if you use A<int> and A<float> than you will have 2 different classes therefore you would need to initialize A<int>::x and A<float>::x.

For more info see this answer: https://stackoverflow.com/a/607335/1280316

1 Comment

It's not only good practice, it's a requirement or the ODR. Unless none of your header is included by several TU's.
0

A class (be it a template or not) can (and should) be declared in any compilation unit that referes to it.

A static field initialization does defines a variable, and as such it should exist only in one compilation unit -> that's the reason why you get an error when class A is not a template.

But when you declare a template, nothing is really created untill you instantiate it. As you never instantiate the template, the static field is never defined and you get no error.

If you had two different instantiations in source1.cpp (say A<B>) and main.cpp (say A<C>) all will still be fine : you would get A<B>::x in source1 and A<C>::x in main => two different variables since A<B> and A<C> are different classes.

The case where you instantiate same class in different compilation units is trickier. It should generate an error, but if it did, you could hardly declare special fields in templates. So it is processed as a special case by the compiler as it is explained in this other answer to generate no errors.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.