2016-03-04 34 views
12

我不確定它是否是GCC編譯器或預期行爲noexcept的錯誤。
考慮下面的例子:noexcept,繼承構造函數和實際完成的不完整類型的無效使用

struct B { 
    B(int) noexcept { } 
    virtual void f() = 0; 
}; 

struct D: public B { 
    using B::B; 
    D() noexcept(noexcept(D{42})): B{42} { } 
    void f() override { } 
}; 

int main() { 
    B *b = new D{}; 
} 

如果noexcept被移除,它編譯。
無論如何,因爲它是在本例中,我從GCC V5.3.1這個錯誤:

test.cpp:8:31: error: invalid use of incomplete type ‘struct D’ 
    D() noexcept(noexcept(D{42})): B{42} { } 
          ^

據我所知,struct D是不是一個不完整的類型,但繼承構造都參與了聲明,看起來編譯器實際上正在考慮比D更多的基礎結構B的完整性。

這是預期行爲還是合法代碼?

爲了清楚起見:使用鐺3.7.1

  • here使用GCC 5.3.0
  • this link到編譯失敗

    • here編譯成功爲GCC編譯器提供bugzilla以獲取更多詳細信息。
      目前,該錯誤仍未得到證實。我會盡快更新問題。

    +0

    嗯,鏗3.7.1接受此代碼。我敢打賭這是一個GCC錯誤。 – thirtythreeforty

    +0

    我已經添加了編譯器抱怨的位置,以及未來Google員工的最終版本(本文撰寫時最新的穩定GCC)。 – thirtythreeforty

    回答

    12

    即使GCC聲明,您的代碼也是合法的。它採取進攻在這個有趣的前瞻性聲明:

    D() noexcept(noexcept(D{42})); 
    

    最外層noexceptnoexcept specifier,指出D::D()是noexcept當且僅當它的常數表達式參數的計算結果爲true。內部noexcept是一個noexcept operator,它在編譯時檢查它的參數表達式是否沒有實際評估,不會引發異常。因爲D::D(int)是不接受(從B繼承),這應該是真實的。

    cppreference.com明確指出,使用符內,允許操作者(強調):

    的noexcept運營商進行編譯時檢查,如果一個表達式聲明不拋出任何返回true例外。

    它可以在函數模板的noexcept說明符中用來聲明函數將爲某些類型引發異常,但不會引發其他異常。現在

    ,類應該算是noexcept符內完整由於第9.2節。標準的2(粗體強調):

    一類被認爲是在類說明符的閉合}完全定義的對象類型(3.9)(或完全型)。 在類構件規格,類被認爲是完整的內功能體,默認參數,使用聲明小號引入繼承構造(12.9),異常規範小號,和brace- or-equal-initializer s用於非靜態數據成員(包括嵌套類中的這些內容)。否則在其類別成員規範內被視爲不完整。

    §15.4.1一個異常規範定義爲以下語法:

    異常規範

    • 動態異常規範

    • noexcept規格

    所以GCC應該不會拒絕你的代碼。

    +0

    在撰寫本文時,我沒有看到針對此特定問題的GCC票證。也許你可以申請一個? – thirtythreeforty

    +0

    我要添加它。 [這裏](https://gcc.gnu.org/bugzilla),對吧? – skypjack

    +0

    我這麼認爲,是的!你可以鏈接回答這個答案,或者複製相關位(主要是後半部分)。 – thirtythreeforty