C++:模板单例类的静态成员未编译/链接



我在c++中使用双重检查锁(带安全锁(实现了一个单例类,它可以工作。然后我尝试将其转换为模板版本,如下所示:

// singleton.h
#include <atomic>
#include <mutex>
template<typename T>
struct singleton {
~singleton() {}
static singleton<T>* getInstance(std::mutex& m);
static std::atomic<singleton<T>*> m_instance; // this is the problem.
};
template<typename T>
singleton<T> * singleton<T>::getInstance(std::mutex& m) {
auto temp = m_instance.load(std::memory_order_acquire);
if (temp == nullptr) {
std::lock_guard<std::mutex> lock(m);
temp = m_instance.load(std::memory_order_relaxed);
if (temp == nullptr) {
temp = new singleton();
m_instance.store(temp, std::memory_order_release);
}
}
return temp;
}

然后在.cpp文件中,我希望使用这个类。注意,static std::atomic<singleton<T>*> m_instance的存储需要存在于我的.cpp文件中,所以我尝试了这个:

struct M {
int m_i;
static std::mutex m;
};
std::atomic<singleton<M>*> singleton<M>::m_instance; // error:
nullity) {
auto instance1 = singleton<M>::getInstance(M::m);
auto instance2 = singleton<M>::getInstance(M::m);
}

m_instance定义报告行:

template specialization requires 'template<>'
std::atomic<singleton<M>*> singleton<M>::m_instance;

如何修复此语法错误?谢谢

不要试图显式地专门化静态数据成员,只需为主模板本身(在头文件中(定义它:

template<typename T>
std::atomic<singleton<T>*> singleton<T>::m_instance{nullptr};

或者,将类模板定义中的m_instance标记为inline(由于C++17(,并在那里添加{nullptr}初始化。(注意,必须显式初始化为nullptrstd::atomic的默认构造函数在C++20之前不会执行正确的初始化。(

不需要在源文件中添加任何内容。


尽管如此,整个过程还是非常冗余的,因为编译器无论如何都会将整个锁定机制添加到本地静态存储持续时间变量的动态初始化中(从C++11开始(。您不需要手动执行任何操作。常见的方法是将单例定义为

static auto& getInstance() {
static singleton<T> instance;
return instance;
}

没有静态数据成员,或者如果动态存储持续时间对很重要

static auto& getInstance() {
static auto instance = std::make_unique<singleton<T>>();
return *instance;
}

最新更新