[英]Explicit defaulted default constructor and aggregates
當我編譯以下代碼的#if 0
和#if 1
版本時,如何解釋差異:
#include <cstdlib>
struct A
{
explicit A() = default; // explicitly defaulted or deleted constructors are allowed for aggregates (since C++11)
#if 1
private :
#endif
int i;
};
int
main()
{
A a = {};
return EXIT_SUCCESS;
}
#if 0
一切都很好,編譯成功。 #if 1
編譯失敗,錯誤消息:
錯誤:選擇的構造函數在復制初始化中是顯式的
表達式A a = {};
什么區別A a = {};
取決於A
是否是萬能?
TL; DR:Clang和GCC拒絕您的代碼是錯誤的。 無論選擇的默認構造函數是否explicit
CWG 1630的分辨率都使得默認初始化格式良好。
在i
private
代碼的變體中, A
不是聚合,因為它們不能擁有私有成員。 但是,只要i
是public
, A
就是聚合1 ,並且由於執行了聚合初始化而沒有調用構造函數(參見藍框),所以你的構造函數是explicit
是無關緊要的。
但是,只要您引入私有成員,就需要根據紅色框進行值初始化。 因此[dcl.init] /(8.2)適用:
[dcl.init] /(7.1)定義了這種情況的默認初始化:
並且§13.3.1.3給出
對於默認初始化,候選函數是正在初始化的對象的類的所有構造函數。
在任何時候都不考慮原始上下文 - 復制或直接初始化。 (§13.3.1.7也不適用。)事實上,這是有意的; 見CWG#1518 :
問題1630的解決方案解決了這個問題 : 默認初始化現在使用13.3.1.3 [over.match.ctor],現在允許顯式構造函數進行默認初始化。
Clang和GCC(以及VC ++)尚未實現相應的DR,因此在拒絕C ++ 14模式中的代碼時是不正確的。
1)您的類具有用戶聲明的構造函數,但它不是用戶提供的 ,即不會阻止您的類成為聚合。 回想一下[dcl.init.aggr] / 1中的定義:
聚合是一個數組或類(第9條),沒有用戶提供的構造函數(12.1),沒有私有或受保護的非靜態數據成員(第11條),沒有基類(第10條),沒有虛函數(10.3) )。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.