Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are static members of template classes not unique

Take a look at the following code:

#include <iostream>

template <typename T>
class Foo
{
    public:
    static T bar;
};

template <typename T> typename T Foo<T>::bar;

int main() {
    std::cout << "Foo<int>::bar : " << &Foo<int>::bar << std::endl;
    std::cout << "Foo<double>::bar : " << &Foo<double>::bar << std::endl;
    return 0;
}

This will print out 2 different addresses. I can understand why in this case, bar is of type T and thus instantiations of different T's in Foo<T> will get you different static members. However, if we change bar to a type we already know ( e.g. static int bar ) this still happens.

Why is this the case? Why just not re-use bar for multiple template instantiations? How would I be able to get just 1 bar object throughout different instantiations?

like image 201
Hatted Rooster Avatar asked May 20 '16 11:05

Hatted Rooster


People also ask

What happens when there is a static member in template class?

The static member is declared or defined inside the template< … > class { … } block. If it is declared but not defined, then there must be another declaration which provides the definition of the member.

Can a static function be template?

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 the difference between class template and template class?

A class template is a template that is used to generate classes whereas a template class is a class that is produced by a template.

What are static members of a class how are they different from normal members?

Inside a class, a normal member belongs to an object. A static member is shared between all objects of that type, and even exists before any object of that class is created.


Video Answer


2 Answers

There is nothing really surprising going on here.

template <typename T>
class Foo
{
    //...
};

Is not a class, it is a template to stamp out classes. That means Foo<A> is a completely different class from Foo<B>. As such all static members are unique to the different instantiated classes — and the fact that class template being same has no relevance in this context, as it is after all a template, the blueprint of the instantiated classes.

If you want all the different kinds of Foo's to share a common state then you can have them inherit from the same base class and put the common information there. Here is a very boiled down example:

struct Foo_Base
{
    static int bar;
};

int Foo_Base::bar = 10;

template<typename T>
struct Foo : Foo_Base {};

int main()
{   
    Foo<int> foo_i;
    Foo<double> foo_d;
    std::cout << foo_i.bar << "\n";
    foo_i.bar += 10;
    std::cout << foo_d.bar;
}

output:

10
20

Live Example

like image 142
NathanOliver Avatar answered Nov 15 '22 04:11

NathanOliver


From the standard, $14.7/6 Template instantiation and specialization [temp.spec]

Each class template specialization instantiated from a template has its own copy of any static members.

Foo<int> and Foo<double> are irrelevant classes, even though they're instantiated from the same template, and they will have their own static member bar, even though their types are same (e.g. both int).

like image 43
songyuanyao Avatar answered Nov 15 '22 04:11

songyuanyao