Reputation: 36513
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?
Upvotes: 5
Views: 152
Reputation: 181068
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
Upvotes: 11
Reputation: 173044
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
).
Upvotes: 9
Reputation: 18451
Foo<int>::bar
and Foo<double>::bar
are two different global (statically accessible class-level) variables. they are not same. Consider this code:
template <typename T>
class Foo
{
public:
static T var1;
static int var2;
};
What do you think the relative placement of var2
be (assume compiler places var2
just after var1
)? In one case, it may be relatively just 1 byte ahead (foo<char>
), but 8 bytes ahead in case of other datatype.
Upvotes: 0