a template class has all static members replicated for each instanciation of it. If I want a static member that exists only once for all instanciations, what should I do? Use a normal static field outside of the class template? Would work, but seems unelegant since there is no more association to the template class. Is there a way to somehow associate such unique static member with a template class?
No; each template class is a completely separate object.
What you could do is create a common ancestor class with the static member:
class Parent
{
public:
static int commonStatic;
};
template <typename T>
class MyTempl : public Parent
{
static int nonSharedStatic;
};
a template class has all static members replicated for each instanciation of it.
Nope. It has different statics for each specialization , but different specializations are different classes. Make no mistake about it, vector<int>
and vector<char>
are totally separate. Think of it as writing IntVector
and CharVector
.
EDIT: Don't use inheritance for this. Introducing a base class just so you can share a static member is definitely the wrong way to go.
If you want stuff shared between different classes, do it like you would usually do it. Wrap some statics in a third class and that's it.
Define some base class for the template class. Include in this base class all common members:
class ExampleBase {
public:
static int foo;
};
int ExampleBase::foo = 0;
template <class A>
class Example : private ExampleBase {
public:
static void setFoo(int f) { foo = f; }
static int getFoo() { return foo; }
};
Then each of Example instances has the common static member ExampleBase::foo
:
int main() {
Example<int>::setFoo(7);
assert(Example<float>::getFoo() == 7);
};
Put a global variable somewhere.
Something like this :
#include <iostream>
// header.hpp
extern int someValue;
template< typename T >
struct A
{
int foo() const
{
return someValue;
}
};
// source.cpp
int someValue = 5;
int main()
{
std::cout << A< float >().foo() << std::endl;
std::cout << A< int >().foo() << std::endl;
}
Use a normal static field outside of the class template?
exactly; just plop it into a function outside of the template declaration.
if really want to restrict access in this scenario, you could use something like this:
class t_shared {
static int& Shared() {
static int s(0);
return s;
}
public:
template < typename T >
class t_template {
public:
void f() {
std::cout << ++Shared() << std::endl;
}
};
};
int main(int argc, const char* argv[]) {
t_shared::t_template<int>().f();
return 0;
}
Class templates are actually a bit different from ordinary classes with respect to static members. The following is perfectly fine, even when foo.hpp
is included by every translation unit:
foo.hpp:
template <typename T> struct TmplFoo
{
static double d;
};
struct OrdFoo
{
static double e;
}
foo.cpp:
#include "foo.hpp"
double OrdFoo::e = -1.5;
Note that we never need a separate definition of TmplFoo<T>::d
. The linker knows how figure out that all local references to TmplFoo<T>::d
(for a given T
) refer to the same object.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.