1

我有一个模板 Singleton 类,用于我的代码的一定数量的重要组件。使用单例代码模型不是这个问题的重点。

现在,我想为这个类添加一个静态计数器,它由使用这个模板的每个类共享。让我为您编写代码(代码并不详尽):

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;

预期输出:

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

我得到的是:

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

这意味着静态 int 不是共享的,而是特定于每个类的。

如何在我的模板类中有一个“非模板”计数器?仅使用标题模板可以做到这一点吗?

4

3 回答 3

4

您可以有一个单独的类用于Counter内部static变量。所以这更像是“嵌套静态”计数:)。

对于语法糖,重载 theopeartor ++和任何你需要的东西。

以下是这样做的主要方法:

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

这是一个工作演示

更新:这是另一种“强制”仅标头模板文件的方式,您不必Counter::value在单独的 .cpp 文件中定义;但是我更喜欢上面的。

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;
于 2012-10-08T09:34:57.183 回答
3

您可以将计数器放在单独的类中,并将其设为模板,因为您只需要标题。例子:

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

与 Nim 的解决方案相比进行编辑,这当然太复杂了.. 但将其视为学习模板的一种做法

于 2012-10-08T09:26:58.893 回答
1

如下:

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

使它成为你的单例的成员,而不是成员变量,使用这个......

编辑:我刚刚重新阅读了您的问题,您需要将其设为另一种类型的成员,例如:

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:
};
于 2012-10-08T09:26:15.290 回答