2015-11-04 53 views
12

如何解釋這一差別,當我編譯#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編譯失敗,錯誤消息:

    error: chosen constructor is explicit in copy-initialization

爲多少取決於A是否aggreagate或不表達A a = {};區別?

+2

我想你自己回答了。 當您收到錯誤A不是聚合結構。 所以你不能使用初始化列表來初始化它。 – Jonathan

+0

@Jonathan我自己的理解(愚蠢的「它取決於聚合性」)並不十分清楚。我想聽到確切的解釋。 – Orient

回答

8

TL; DR:Clang和GCC在拒絕你的代碼時是錯誤的。 CWG 1630的分辨率使默認初始化格式良好,無論選擇的默認構造函數是否爲explicit


在你的代碼的變化,其中iprivateA不是彙總,因爲這些不能有私有成員。只要ipublic,但是,A是一個合計,並且自從執行聚合初始化(請參閱藍色框)以來沒有構造函數被調用,所以您的構造函數是explicit是無關緊要的。

enter image description here

然而,一旦你介紹的私有成員,你必要的值初始化爲每紅色框。因此[dcl.init] /(8.2)適用:

[dcl.init] /(7.1)定義缺省初始化對於這種情況:

enter image description here

而且§13.3 .1.3給出

For […] default-initialization, the candidate functions are all the constructors of the class of the object being initialized.

沒有考慮原始上下文 - 複製或直接初始化。 (§13.3.1.7也不適用)。實際上,這是有意的;見CWG #1518

This issue is resolved by the resolution of issue 1630 : default initialization now uses 13.3.1.3 [over.match.ctor], which now permits explicit constructors for default-initialization.

鏘和GCC(和VC++)還沒有實現相應的DR但並因此在拒絕在C++ 14模式的代碼不正確。


1) 你們班有一個用戶聲明的構造,但提供,即不是從一種聚合阻礙你的類是不針對用戶。回想[dcl.init.aggr]/1中的定義:

An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).

+2

是不是[CWG 1518](http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1518)與此案有關? – bogdan

+0

@bogdan等等,我的初步結論是否正確? – Columbo

+0

我會這麼說,但我不是100%確定自己:-)。 – bogdan