我使用雙重檢查鎖(帶安全鎖)在 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;
如何修復此語法錯誤?謝謝。
uj5u.com熱心網友回復:
不要嘗試顯式特化靜態資料成員,只需為主模板本身定義它(在頭檔案中):
template<typename T>
std::atomic<singleton<T>*> singleton<T>::m_instance{nullptr};
m_instance或者在類模板定義中標記為inline(自 C 17 起)并在{nullptr}那里添加初始化。(請注意,您必須顯式初始化為nullptr。在 C 20 之前,默認建構式std::atomic不會執行正確的初始化。)
無需在源檔案中添加任何內容。
但是,整個事情是非常多余的,因為編譯器無論如何都會將整個鎖定機制添加到本地靜態存盤持續時間變數的動態初始化中(自 C 11 起)。您無需手動執行任何操作。常見的方法是將單例定義為
static auto& getInstance() {
static singleton<T> instance;
return instance;
}
沒有靜態資料成員,或者如果動態存盤持續時間對您很重要
static auto& getInstance() {
static auto instance = std::make_unique<singleton<T>>();
return *instance;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/515157.html
