Chúng tôi đang sử dụng curiously recurring template pattern để triển khai thực đơn. Tuy nhiên, với các phiên bản Clang gần đây, chúng tôi nhận được cảnh báo -Wundefined-var-template. Bản sửa lỗi được đề xuất là thêm "tuyên bố khởi tạo rõ ràng".Làm thế nào để khắc phục một thiếu mục đích của một "tuyên bố instantiation rõ ràng" khi biên dịch một CRTP Singleton với Clang?
Tôi đã cố gắng để làm điều này, nhưng sau đó tôi nhận được lỗi về "chuyên môn hóa rõ ràng sau khi instantiation" trong đơn vị biên soạn nơi định nghĩa của singleton mẫu biến thành viên lớp.
Cấu trúc thích hợp để khắc phục vấn đề được đánh dấu bởi cảnh báo này là gì?
Giản chi tiết (nhiều logic đã được gỡ bỏ, để thực hiện một MCVE):
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);
Khi chúng tôi biên dịch bằng phiên bản tiếng kêu gần đây (3.9.0; nhưng không phải với clang 3.7), chúng tôi nhận được cảnh báo khi biên dịch các tệp khác ngoài Singleton.cc. (Với -std = C++ 11 và -Werror)
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.
tôi đã thêm dòng sau vào cuối Singleton.hh, vì nó là những gì tôi lead to believe cú pháp khai instantiation rõ ràng nên.
extern template Singleton* SingletonBase< class Singleton >::instance_;
Trong khi điều này khắc phục vấn đề với biên soạn OtherFile.cc, nó kết quả trong một lỗi mới khi biên soạn Singleton.cc
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.
Những gì tôi nên làm gì ở đây để sửa chữa những cảnh báo/lỗi? Có một cú pháp thích hợp hơn cho khai báo instantiation rõ ràng mà tôi không hiểu?
Nhưng tại sao oh lý do tại sao? Bạn đã tạo một thành viên tĩnh var và không khóa, do đó nó không an toàn thread. Bạn có thể đặt static đó trong 'get_instance()', phụ thuộc nếu, có thread-safe. Lớp cơ sở của bạn không đảm bảo rằng đây là một singleton, nhưng nó đòi hỏi một hàm create_instance. Tôi có thể, tại bất kỳ điểm nào, tạo ra hai trường hợp 'Singleton' w/o thậm chí chạm vào giao diện của bạn. Bạn không thể phá hủy - tái tạo nó. Bạn có thể có cơ sở và con cháu độc thân cùng một lúc. Bạn đang bị rò rỉ và không bao giờ gọi là destructor. Việc sửa chữa? Xóa các nguồn này và bắt đầu lại. (Không có vi phạm, chúng tôi có thể hướng dẫn bạn để có một thích hợp) – lorro
@Iorro Hãy nhớ rằng tôi đã tách ra hầu hết các chi tiết (bao gồm cả các bit thread-an toàn) để cung cấp cho bạn một MCVE. Nếu bạn có một thực thi Singleton bạn xem xét "thực hành tốt nhất", cảm thấy tự do để liên kết nó trong một bình luận, nhưng câu hỏi ban đầu của tôi vẫn đứng. –
Đây là _very_ quan trọng, tôi đề nghị bạn thêm một nhận xét về điều đó trong phần câu hỏi chính, nếu không mọi người sẽ cố gắng khắc phục những lỗi này, chứ không phải lỗi trình biên dịch. Biến thành viên -> chức năng sửa lỗi tĩnh có hoạt động cho bạn hay bạn có lý do để giữ cho nó là thành viên không? – lorro