41

Başlangıçta bir std::array başlatılması gerektiğini varsayalım.Std :: array başlatımında Brace elision

std::array<int, 2> x = {{0, 1}}; 
std::array<int, 2> x{{0, 1}}; 

bağ elision eksik parantez ilgilenir gibi, aynı zamanda iyi eski agrega başlatma tek parantez sıkıntı yoktur::

std::array<int, 2> x = {0, 1}; 

Ancak, bir çift parantez kullanarak, sorun değil liste-başlatmayı tek parantez ile kullanmak tamam mı? GCC bunu kabul eder, Clang, "doğrudan liste başlatmayı kullanırken alt nesnenin başlatılması etrafında parantez atlayamaz" ifadesini reddeder.

tüm örtülü türü dönüşüm (Madde 4) olarak kabul edilir toplam elemanı ile başlatırken:

std::array<int, 2> x{0, 1}; 

bağ elision belirtilen standart sadece bir bölümünü diyor 8.5.1/12, olduğu bir atama-ifade. Atama ifadesi bir üyeyi başlatabilirse, üye başlatılır. Aksi halde, eğer üye kendi başına bir alt-grup ise, parantez seçimi kabul edilir ve atama-ifadesi alt-topluluğun ilk üyesinin ilklendirilmesi için kabul edilir.

8.5.1 özellikle toplu başlatma hakkında, dolayısıyla Clang'ın reddetme doğru olduğu anlamına gelmelidir, doğru mu? Çok hızlı değil. 8.5.4/3 der aşağıdaki gibi bir nesne ya da T türü referansının

listesi-başlatma tanımlanır:

[...]

- Aksi takdirde, T bir agrega ise, agrega başlatma gerçekleştirilir (8.5.1).

Bunun anlamı, küme düzeltmesi de dahil olmak üzere, toplu başlatma da dahil olmak üzere, tam olarak aynı kuralların, GCC'nin kabul edilmesinin doğru olduğu anlamına geldiği anlamına geldiğini düşünüyorum.

İtiraf etmeliyim ki, ifade özellikle açık değildir. Yani, hangi derleyici üçüncü snippet'in tedavisinde doğrudur? Destek başlatması liste başlatma işleminde gerçekleşiyor mu, yoksa yapmıyor mu?

+0

Güzel soru! Kullandığınız standarttan bahsetmeye değer olabilir. C++ 11 standardı veya değilse, hangi taslak. – juanchopanza

+0

"atama benzeri başlatma", kopya başlatma başlatılır. Atama operatörünü değil, kopya kurucuyu çağırır. – TemplateRex

+0

@TemplateRex: Bu yüzden "beğen" çalışmasını kullandım. – Fanael

cevap

20

Brace seçimi geçerlidir, ancak C++ 11'de değil. C++ 14'te, http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1270 nedeniyle uygulanacaklar. Eğer şanslıysanız Clang, C++ 11 moduna geri dönecektir (umarız umarız!).

+0

Şu an itibariyle, archlinux'daki 'clang-5.0' hala '-std = C++ 17' ile bile brace seçimini desteklemiyor. –

3

İlgili: Kısacası http://en.cppreference.com/w/cpp/language/aggregate_initialization

,

struct S { 
    int x; 
    struct Foo { 
     int i; 
     int j; 
     int a[3]; 
    } b; 
}; 
S s1 = { 1, { 2, 3, {4, 5, 6} } }; 
S s2 = { 1, 2, 3, 4, 5, 6}; // same, but with brace elision 
S s3{1, {2, 3, {4, 5, 6} } }; // same, using direct-list-initialization syntax 
S s4{1, 2, 3, 4, 5, 6}; // error in C++11: brace-elision only allowed with equals sign 
         // okay in C++14