gexicide
gexicide

Reputation: 40058

C++ Templates with unique static members

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?

Upvotes: 2

Views: 1490

Answers (6)

justin
justin

Reputation: 104698

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;
}

Upvotes: 0

PiotrNycz
PiotrNycz

Reputation: 24412

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);
};

Upvotes: 1

Kerrek SB
Kerrek SB

Reputation: 477040

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.

Upvotes: -1

BЈовић
BЈовић

Reputation: 64223

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;
}

Upvotes: 0

Chowlett
Chowlett

Reputation: 46667

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;
};

Upvotes: 5

Luchian Grigore
Luchian Grigore

Reputation: 258608

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.

Upvotes: 2

Related Questions