我有一个模板Singleton类,我用它来代码的一些重要组件。使用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不是共享的,而是特定于每个类。
如何在模板类中使用“未模板化”的计数器?这是否可以使用仅标题模板?
答案 0 :(得分:4)
您可以为Counter
分别设置内部static
变量的课程。所以这更像是“嵌套静态”计数:)。
对于语法糖,重载opeartor ++
以及你需要的任何东西。
以下是执行此操作的主要方式:
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
};
这是working demo。
Udpate :这是“强制”header only template文件的另一种方式,您无需在单独的.cpp文件中定义Counter::value
;但我更喜欢上述内容。
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;
答案 1 :(得分: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的解决方案相比,这当然太过于复杂了......但是将其视为学习模板的一种做法
答案 2 :(得分: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:
};