Tekil uygulamak için curiously recurring template pattern kullanıyoruz. Ancak, son Clang sürümleriyle, bir Wundefined-var-template uyarısı alıyoruz. Önerilen düzeltme, "açık bir örnekleme bildirimi" eklemektir.Bir CRTP Singleton'u Clang ile derlerken bir "açık örnek bildirimi" eksikliğini nasıl giderebilirim?
Bunu yapmayı denedim, ancak sonra singleton şablon sınıf üyesi değişkenin tanımının olduğu derleme biriminde "somutlaştırmadan sonra açık uzmanlık" hakkında hatalar alıyorum.
Bu uyarı ile vurgulanan sorunu gidermek için uygun yapı nedir?
Basitleştirilmiş Detaylar (mantığının pek bir MCVE yapmak, kaldırılmıştır):
SingletonBase.hh:
template < class T > class SingletonBase {
public:
static T * get_instance() {
if (! instance_) {
instance_ = T::create_singleton_instance();
}
return instance_;
}
private:
static T * instance_;
};
Singleton.hh:
#include "SingletonBase.hh"
class Singleton : public SingletonBase<Singleton> {
friend class SingletonBase<Singleton>;
public:
int do_stuff(int v) { return v+2; }
private:
static Singleton * create_singleton_instance() {
return new Singleton;
}
};
Singleton.cc:
#include "Singleton.hh"
template <> Singleton * SingletonBase<Singleton>::instance_(nullptr);
Güncel bir clang sürümü ile derlediğimizde (3.9.0; ancak clang 3.7 ile değil, Singleton.cc dışındaki dosyaları derlerken bir uyarı alırız. ben açık örnekleme beyanı sözdizimi olmalıdır lead to believe olduğum iş bu şekilde (-std = C++ 11 ve -Werror kullanmamak ile)
In file included from OtherFile.cc:2:
In file included from ./Singleton.hh:2:
./SingletonBase.hh:5:16: warning: instantiation of variable 'SingletonBase<Singleton>::instance_' required here, but no definition is available [-Wundefined-var-template]
if (! instance_) {
^
OtherFile.cc:5:25: note: in instantiation of member function 'SingletonBase<Singleton>::get_instance' requested here
return Singleton::get_instance()->do_stuff(4);
^
./SingletonBase.hh:11:18: note: forward declaration of template entity is here
static T * instance_;
^
./SingletonBase.hh:5:16: note: add an explicit instantiation declaration to suppress this warning if 'SingletonBase<Singleton>::instance_' is explicitly instantiated in another translation unit
if (! instance_) {
^
1 error generated.
Ben Singleton.hh sonuna aşağıdaki satırı eklendi. Bu OtherFile.cc derleme ilgili sorunları düzeltir iken Singleton.cc
derlerken
extern template Singleton* SingletonBase< class Singleton >::instance_;
, yeni bir hata ile sonuçlanır
Singleton.cc:3:57: error: explicit specialization of 'instance_' after instantiation
template <> Singleton * SingletonBase<Singleton>::instance_(nullptr);
^
./Singleton.hh:14:66: note: explicit instantiation first required here
extern template Singleton* SingletonBase< class Singleton >::instance_;
^
1 error generated.
Bu uyarıların/hataları düzeltmek için burada yapıyor olması gerekenler
? Anlamadığım açık örnekleme bildirimi için daha uygun bir sözdizimi var mı?
template<class T>
struct SingletonBase {
static T& get_instance() {
static T instance;
return instance;
}
};
It adlı parçacığı güvenli ve uyarıyı kaldırmak:
Ama neden ah neden? Statik bir üye var yarattınız ve kilitlenmeyiniz, bu yüzden diş güvenli değildir. Bu durağanlığı get_instance() 'a koyabilirsiniz, eğer varsa, emniyete alın. Temel sınıfınız bunun bir singleton olmasını sağlamaz, ancak bir create_instance işlevi gerektirir. Herhangi bir noktada, arayüzünüze dokunmadan bile iki 'Singleton' örneği oluşturabilirim. Onu yok edemezsin. Aynı anda taban ve soyunan tektonlara sahip olabilirsiniz. Sızıyorsun ve asla yok ediciyi aramıyorsun. Çözüm? Bu kaynakları silin ve baştan başlayın. (Hiçbir suçlama, size uygun bir tane olması için size rehberlik edebiliriz) – lorro
@Iorro Size bir MCVE vermek için ayrıntıların çoğunu (iplik güvenlik bitleri dahil) yıprattığımı unutmayın. Eğer bir Singleton uygulamanız varsa, "en iyi uygulamalar" ı düşünürsünüz, yorumda bağlantı kurabilirsiniz, ancak asıl sorum hala geçerli. –
Bu, _very_ önemli, ana soru bölümünde buna bir yorum eklemenizi öneririm, aksi halde insanlar bunları düzeltmeye çalışır, derleyici hatası değil. Üye değişkeni - değişkeni durağan değişkeni sizin için çalışır mı, yoksa üye tutmak için nedenleriniz var mı? – lorro