Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

static member variable in class template

Tags:

c++

When you have a (non-templated) class that contains a static member, like:

class Foo
{
   public:

   static int x;
};

Then Foo::x must be defined in one and only one translation unit, or the compiler will complain of multiple definitions. So in somefile.cpp you'd have to define it:

int Foo::x = 10;

This way, any translation unit that accesses Foo::x is accessing the same memory address.

But what if Foo is a class template?

template <class T>
class Foo
{
   public:

   static int x;
};

Now, Foo<T>::x can be defined in a header file, by saying:

template <class T>
int Foo<T>::x = 10;

So, if class template Foo is defined in foo.hpp, and translation_unit1.cpp and translation_unit2.cpp both include foo.hpp, will the memory address of Foo<T>::x for some instantiation of template class Foo, (such as Foo<int>::x for example) be different for each translation unit?

like image 596
Channel72 Avatar asked Oct 14 '13 18:10

Channel72


People also ask

How are static members declared within a template class?

Static data members and templates (C++ only) The static declaration can be of template argument type or of any defined type. The statement template T K::x defines the static member of class K , while the statement in the main() function assigns a value to the data member for K <int> .

What is meant by a static member variable of a class?

Static variables are initialized to 0. It is initialized only once. Throughout the program, only one copy of the static member variable is created for the entire class hence static member variables are also called class variables. It is shared by all instances of the class.

Can a class have a static member?

The static member is callable on a class even when no instance of the class has been created. The static member is always accessed by the class name, not the instance name. Only one copy of a static member exists, regardless of how many instances of the class are created.

Can a template be static?

A template is referred to as being "static" if no data is inserted into it when it is created or if it is not modified in any other way by Templafy. The opposite of a static template is a dynamic template.


3 Answers

This is perfectly fine, in this case of defining it in the header the compiler will insure there is only one instance, if we see the draft C++ standard section 3.2 One definition rule paragraph 6 says(emphasis mine):

There can be more than one definition of a class type (Clause 9), enumeration type (7.2), inline function with external linkage (7.1.2), class template (Clause 14), non-static function template (14.5.6), static data member of a class template (14.5.1.3), member function

we can then go to section 14.5.1.3 Static data members of class templates paragraph 1 says:

A definition for a static data member may be provided in a namespace scope enclosing the definition of the static member’s class template.

and provides the following example:

template<class T> class X {
  static T s;
};
template<class T> T X<T>::s = 0;
like image 146
Shafik Yaghmour Avatar answered Sep 23 '22 03:09

Shafik Yaghmour


Your question is perfectly answered by 14.4 in the C++11 standard:

A template name has linkage (3.5). A non-member function template can have internal linkage; any other template name shall have external linkage...

Therefore, a class template will always have external linkage and so are its static data members (const or not). So, Foo<int>::x will always refer to the same entity in memory regardless of which translation units this expression appears in. The linker makes this happen.

like image 33
Lingxi Avatar answered Sep 23 '22 03:09

Lingxi


[basic.def.odr]/6 explicitly allows multiple definitions of "static data members of a class template" (alongside other exceptions) under some circumstances.

It then continues for such an entity D:

If the definitions of D satisfy all these requirements, then the program shall behave as if there were a single definition of D. If the definitions of D do not satisfy these requirements, then the behavior is undefined.

Therefore the address of a static data member of a template instantiated in one TU compares equal to the address of the same static data member instantiated in another TU.


The complete quote, passages mentioned above emphasized by me:

There can be more than one definition of a class type, enumeration type, inline function with external linkage, class template, non-static function template, static data member of a class template, member function of a class template, or template specialization for which some template parameters are not specified in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. Given such an entity named D defined in more than one translation unit, then

  • each definition of D shall consist of the same sequence of tokens; and
  • in each definition of D, corresponding names, looked up according to 3.4, shall refer to an entity defined within the definition of D, or shall refer to the same entity, after overload resolution and after matching of partial template specialization, except that a name can refer to a const object with internal or no linkage if the object has the same literal type in all definitions of D, and the object is initialized with a constant expression, and the value (but not the address) of the object is used, and the object has the same value in all definitions of D; and
  • in each definition of D, corresponding entities shall have the same language linkage; and
  • in each definition of D, the overloaded operators referred to, the implicit calls to conversion functions, constructors, operator new functions and operator delete functions, shall refer to the same function, or to a function defined within the definition of D; and
  • in each definition of D, a default argument used by an (implicit or explicit) function call is treated as if its token sequence were present in the definition of D; that is, the default argument is subject to the three requirements described above (and, if the default argument has sub-expressions with default arguments, this requirement applies recursively).
  • if D is a class with an implicitly-declared constructor, it is as if the constructor was implicitly defined in every translation unit where it is odr-used, and the implicit definition in every translation unit shall call the same constructor for a base class or a class member of D.

If D is a template and is defined in more than one translation unit, then the preceding requirements shall apply both to names from the template’s enclosing scope used in the template definition, and also to dependent names at the point of instantiation. If the definitions of D satisfy all these requirements, then the program shall behave as if there were a single definition of D. If the definitions of D do not satisfy these requirements, then the behavior is undefined.

like image 44
dyp Avatar answered Sep 20 '22 03:09

dyp