[英]constexpr variable at namespace scope without explicit inline definition and with
[英]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.