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??
Eduard Rostomyan
  • 7,050
  • 2
  • 37
  • 76
  • 1) Class template members are only instantiated when needed. 2) that's a tricky question. – Kerrek SB Apr 27 '15 at 07:40
  • possible duplicate of [Template static variable](http://stackoverflow.com/questions/1553854/template-static-variable) – Quentin Apr 27 '15 at 07: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. – bkausbk Apr 27 '15 at 08: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? – Eduard Rostomyan Apr 27 '15 at 09:52

4 Answers4

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().

Community
  • 1
  • 1
marcinj
  • 48,511
  • 9
  • 79
  • 100
  • So when C++ standard insists that all static data should be initializes before main does not bother this case, am I correct? – Eduard Rostomyan Apr 27 '15 at 08:45
  • 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. – marcinj Apr 27 '15 at 09:20
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.

W.F.
  • 13,888
  • 2
  • 34
  • 81
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

Community
  • 1
  • 1
Chemik
  • 1,459
  • 13
  • 23
  • It's not only good practice, it's a requirement or the ODR. Unless none of your header is included by several TU's. – Quentin Apr 27 '15 at 07:53
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.

Community
  • 1
  • 1
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252