2017-08-12 250 views
3

我想要做的是將一些類繼承爲extention類。事情是extention類必須知道它正在擴展的類。在static_assert中使用std :: is_base_of由於不完整類型而失敗

這可以簡單地實現這樣的:

template<typename Self> 
class Extention 
{ 
    public: 
     void check() const 
     { 
      std::cout << "Extention is valid: " 
         << std::boolalpha 
         << std::is_base_of<Extention, Self>::value 
        << std::endl; 
     } 
}; 
class Foo : public Extention<Foo> {}; 
class Bar : public Extention<void> {}; 

FooBar類節目好,進一步擴展的不好的用法。

Foo().check(); → Extention is valid: true 
Bar().check(); → Extention is valid: false 

我想在編譯期間檢查模板的有效性,這使我寫

template<typename Self> 
class Extention 
{ 
    static_assert(std::is_base_of<Extention, Self>::value); 
}; 

然而,GCC運輸發射車我這個static_assert是錯誤的,因爲class Foo具有不完整的類型。

我在做什麼錯?

編輯:我使用-std=c++17,錯誤不在static_assert

+1

您可以將'static_assert'放入成員函數中,但要使其正常工作,必須通過調用它來實現該函數。 – HolyBlackCat

+0

@HolyBlackCat把它放在構造函數中會起作用。不過,如果你有多個構造函數,它會是痛苦和容易出錯的... – Amxx

+0

而不是使用靜態斷言敲擊所有構造函數,而是從受保護的'Requiredived'派生模板'Extention'是'Self'選項?這會給你一個根保護的默認構造函數'RequiredBase()',在其中掛起你的靜態斷言。或者,也許我誤解了你的目標。 – WhozCraig

回答

2

缺少錯誤消息的我在做什麼錯?

由於[meta.rel]std::is_base_of要求派生類型是一個完整的類型:

如果BaseDerived都是非工會類類型,不屬於同一類型的可能CV-合格版本, Derived應是完整的類型。

在另一側,[class.mem/6]指出:

一類被認爲是在類說明符的關閉}完全定義的對象類型(或完整的類型)。 [...]

這不是你的情況。當您實例化Extension<Foo>時,Foo本身遠未完全定義。

換句話說,您不能在類作用域使用static_assert。如果你願意的話,把它放在析構函數體內(我的首選解決方案,即使它有一些缺點)或任何其他(特殊)成員方法的正文。

相關問題