2013-01-22 107 views
4

我有一個派生自某個基類的類的註冊器的實現。目的是讓每個派生類自己註冊,並且在這個過程中提供一些關於它自己的信息,在下面的例子中是通過一個字符串提供的。強制派生類型的註冊

我缺少的是強制從Base派生的類通過初始化靜態成員reg註冊自己的方法。換句話說,如果派生類沒有定義/初始化靜態成員,是否有可能讓編譯器產生錯誤? void blah() { }然後從CRTP基類的一個虛設的構造調用它:

public: 
    Base() { reg.blah(); } 

我可以

struct Registrar { 
    Registrar(string type) { 
    registry().push_back(type); 
    } 
    static vector<string> & registry() { 
    static vector<string> * derivedTypes = new vector<string>; 
    return *derivedTypes; 
    } 
}; 

//CRTP 
template <typename Derived> 
class Base 
{ 
    static Registrar reg; 
}; 

class Derived1 : public Base<Derived1> {/*Class definition*/}; 
class Derived2 : public Base<Derived2> {/*Class definition*/}; 
class Derived3 : public Base<Derived3> {/*Class definition*/}; 
//... 

//Initialize the static members of each derived type 
//Commenting out any of the following 3 lines doesn't produce an error. 
//Ideally, I want it to produce a compile error. 
template<> Registrar Base<Derived1>::reg("Derived1"); 
template<> Registrar Base<Derived2>::reg("Derived2"); 
template<> Registrar Base<Derived3>::reg("Derived3"); 

int main() { 

    cout << "Registered Types:" << endl; 
    for(vector<string>::const_iterator it = Registrar::registry().begin(); 
     it != Registrar::registry().end(); ++it) { 
    cout << *it << endl; 
    } 

    return 0; 
} 
+1

最好我能想到的是一個鏈接器錯誤(不是編譯錯誤),唯一的方法就是以某種方式訪問​​'Base'類中的'reg'(比如在構造函數中) - 這應該觸發一個鏈接器錯誤(與您確實使用的派生類型有問題的地方...) – Nim

+0

@Nim:我想的完全一樣;-) – Nawaz

回答

1

可以至少通過添加虛擬函數到註冊導致克++接頭錯誤沒有看到更加優雅的方式來解決這個問題。