簡體   English   中英

沒有初始化器或顯式默認構造函數的空類是否可用作constexpr變量?

[英]Is an empty class usable as a constexpr variable without an initializer or explicit default constructor?

給出以下代碼:

struct f {
};

int main(){
    constexpr f f1 ;
    //const f f1  ; // This also has the same issue
    //constexpr f f1 = {} ; //This works
}

clang和gcc不同意它是否有效,clang提供以下診斷( 見現場直播 ):

error: default initialization of an object of const type 'const f' without a user-provided default constructor
constexpr f f1 ;
            ^
              {}

據我所知, f是一個文字類型,它由隱式默認構造函數初始化,它應該允許它被聲明為constexpr。 誰在這里是對的?

注意,如果我顯式添加constexpr默認構造函數,clang會接受f1的聲明:

constexpr f() {} ;

答案變化是f不是聚合嗎?

如果我們從草案C ++ 14標准第7.1.5[dcl.constexpr]開始,我們可以發現constexpr對象聲明的要求是:

對象聲明中使用的constexpr說明符將對象聲明為const。 這樣的對象應具有文字類型並應初始化。 如果它是由構造函數調用初始化的,那么該調用應該是一個常量表達式(5.19)。

那么f是文字類型嗎?

3.9[basic.types]說:

類型是文字類型,如果它是:

並涵蓋以下項目中的類:

  • 具有以下所有屬性的類類型(第9節)

    • 它有一個簡單的析構函數,
    • 它是一個聚合類型(8.5.1)或者至少有一個constexpr構造函數或構造函數模板,它不是復制或移動構造函數,並且
    • 它的所有非靜態數據成員和基類都是非易失性文字類型。

所以我們對第一和第三個子彈都沒問題。 為了覆蓋第二個項目符號,我們可以注意到f是一個聚合但是如果我們稍微修改一下這個例子,例如如果f看起來像這樣:

struct f {
   private:
      int x = 0 ;
} ;

它不會是C ++ 11或C ++ 14中的聚合,但問題仍然存在。 然后我們需要證明它有一個constexpr構造函數。 f有一個constexpr構造函數嗎?

據我所知,第12.1[class.ctor]說是:

[...]如果用戶編寫的默認構造函數滿足constexpr構造函數(7.1.5)的要求,則隱式定義的默認構造函數為constexpr。 [...]

但遺憾的是,我們需要在第8.5節中提供一個用戶提供的構造函數,其中說:

如果程序要求對const限定類型T的對象進行默認初始化,則T應為具有用戶提供的默認構造函數的類類型。

所以看起來clang在這里是正確的,如果我們看下面的clang bug報告: “錯誤:const類型'const Z'對象的默認初始化需要用戶提供的默認構造函數”,即使沒有構造函數需要 因此,由於缺陷報告253目前沒有提議的措辭,並且它說( 強調我的 ),因此clang基於他們缺乏對此的支持:

8.5 [dcl.init]第9段說:

如果沒有為對象指定初始化程序,並且該對象是(可能是cv限定的)非POD類類型(或其數組),則該對象應默認初始化; 如果對象是const限定類型,則底層類類型應具有用戶聲明的默認構造函數 否則, 如果沒有為對象指定初始化程序 ,則該對象及其子對象(如果有)具有不確定的初始值; 如果對象或其任何子對象是const限定類型, 則程序格式錯誤

如果const POD對象沒有非靜態數據成員怎么辦? 這種措辭需要一個空的初始化器來處理這種情況

[...]

類似的注釋適用於非POD const對象,其所有非靜態數據成員和基類子對象都具有默認構造函數。 為什么要求這樣的對象的類具有用戶聲明的默認構造函數?

缺陷報告仍然開放,但最后一條評論說:

如果隱式默認構造函數初始化所有子對象,則不需要初始化程序。

並且還注意到:

應根據constexpr構造函數和非靜態數據成員初始值設定項再次提出此問題。

請注意,自缺陷報告出現以來,對第8.5節中的const限定類型的約束已經移動。 這是由於提案N2762:不是那么瑣碎的問題,這是微不足道的 C ++ 11之前的問題。

雖然缺陷報告仍然是開放的,但鑒於constexpr更改和非靜態數據成員初始化程序,它似乎不再是必要的限制。 特別是考慮到constexpr構造函數的以下要求:

  • 應初始化每個非變量非靜態數據成員和基類子對象(12.6.2);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM