Non-template static counter in template

梦想与她 提交于 2020-01-05 04:48:11

问题


I've got a template Singleton class that I use for a certain amount of important components of my code. Using a Singleton code-model is not the point of this question.

Now, I'd like to add to this class a static counter that is shared by every class that use this template. Let me code that for you (the code is not exhaustive):

template <class T>
class Singleton
{
public:
   Singleton(const std::string &name){ 
      printf("%s CTOR call #%d\n", name.c_str(), _counter);  
      _counter++; 
   }
   virtual ~Singleton(){}
private:
   static int _counter; // I want this to be shared by all classes
}

// I can only initialize it like this; sadly
template<class T> 
int Singleton<T>::_counter = 0;

// main code (simplified):
Singleton<MyClass1>("MyClass1") c1;
Singleton<MyClass2>("MyClass2") c2;
Singleton<MyClass3>("MyClass3") c3;
Singleton<MyClass4>("MyClass4") c4;

Expected output:

MyClass1 CTOR call #0
MyClass2 CTOR call #1 // counter is incremented
MyClass3 CTOR call #2
MyClass4 CTOR call #3

What I get is:

MyClass1 CTOR call #0
MyClass2 CTOR call #0 // counter is not incremented
MyClass3 CTOR call #0
MyClass4 CTOR call #0

Which means the static int is not shared, but rather specific to each class.

How can I have a "not-templated" counter in my template class? Is this possible with a header-only template?


回答1:


As follows:

static int& counter()
{
  static int _counter = 0;
  return _counter;
}

Make this a member of your singleton and instead of the member variable, use this...

EDIT: I just re-read your question, you need to make this a member of another type, e.g:

struct Counter
{
   static int& counter()
   {
     static int _counter = 0;
     return _counter;
   }
};

template <class T>
class Singleton
{
public:
   Singleton(const std::string &name){ 
      std::cout << name <<Counter::counter() << std::endl;
      Counter::counter()++;
   }
   virtual ~Singleton(){}
private:
};



回答2:


You can have a separate class for Counter with internal static variable. So this is more like, "nested static" counting :).

For syntactic sugar, overload the opeartor ++ and whatever you need.

Below is the primary way of doing that:

struct Counter
{
  static unsigned int value;
  Counter& operator ++ (int) { value ++; return *this; }
  operator unsigned int () const { return value; }
};
unsigned int Counter::value = 0;

template <class T>
class Singleton
{
public:
   Singleton(const std::string &name){ 
      printf("%s CTOR call #%d\n", name.c_str(), s_counter.value);  
      s_counter++; 
   }   
   virtual ~Singleton(){}
private:
   static Counter s_counter; // shared by all classes
};

Here is a working demo.

Udpate: This is another way of 'forcing' header only template file where you don't have to define the Counter::value in a separate .cpp file; however I would prefer the above.

template<bool _true>
struct Counter
{
  static unsigned int value;
  Counter& operator ++ (int) { value ++; return *this; }
  operator unsigned int () const { return value; }
};
template<bool _true>
unsigned int Counter<_true>::value = 0;

template<>
struct Counter<false>; // disable the other alternative so no one can invoke it

template <class T>
class Singleton
{
public:
   Singleton(const std::string &name){ 
      printf("%s CTOR call #%d\n", name.c_str(), s_counter.value);  
      s_counter++; 
   }   
   virtual ~Singleton(){}
private:
   static Counter<true> s_counter; // shared by all classes
};
template<class T>
Counter<true> Singleton<T>::s_counter;



回答3:


You could put the counter in a seperate class, and make it a template as well since you want header only. Example:

template <class T> 
struct Helper
{
  static int _counter;
};

template<class T>
int Helper<T>::_counter = 0;

struct Dummy{};

template <class T> 
class Singleton 
{ 
public: 
   Singleton(const std::string &name){  
     printf("%s CTOR call #%d\n", name.c_str(), Helper<Dummy>::_counter);   
     Helper<Dummy>::_counter++;  
   } 
   virtual ~Singleton(){} 
};

edit in comparision to Nim's solution this is of course waaaay too compilcated.. but consider it a practice in learning templates



来源:https://stackoverflow.com/questions/12778581/non-template-static-counter-in-template

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!