简体   繁体   中英

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?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM