Pengambilan salinan dijamin untuk inisialisasi array braced yang seragam - Bukankah ini harus diwajibkan sejak C ++ 17? [duplikat]

Dec 06 2020

Sejauh saya memahami aturan baru dengan benar

https://en.cppreference.com/w/cpp/language/copy_elision

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0135r0.html

Kode ini harus dikompilasi untuk kompiler kepatuhan standar C ++ 17

struct NonTrivialClass
{
    ~NonTrivialClass( ){  }
};

class MainNonTrivialClass 
{
public:
  MainNonTrivialClass(int t) : m_simpleTypeMember(t) { }
 
  virtual void makeMySelfNonTrivial() {}

  MainNonTrivialClass( const MainNonTrivialClass& other) = delete;
  MainNonTrivialClass& operator=( const MainNonTrivialClass& other) = delete;
  MainNonTrivialClass(MainNonTrivialClass&& other) = delete;
  MainNonTrivialClass& operator=(MainNonTrivialClass&& other) = delete;
  
  NonTrivialClass m_nontrivialMember;
  int m_simpleTypeMember;
};

class ArrayContainer
{
public:
  ArrayContainer() : m_array{{1}, {2} } {}

private:
  MainNonTrivialClass m_array[2];
};


int main()
{
  ArrayContainer accContainer;
}

Tapi gcc 9.1.0 dengan -std = c ++ 17 -O2 -Wall -pedantic mengatakan (seperti yang diharapkan untuk pra C ++ 17)

main.cpp: In constructor 'ArrayContainer::ArrayContainer()':
main.cpp:25:39: error: use of deleted function 'MainNonTrivialClass::MainNonTrivialClass(MainNonTrivialClass&&)'
   25 |   ArrayContainer() : m_array{{1}, {2} } {}
      |                                       ^
main.cpp:15:3: note: declared here
   15 |   MainNonTrivialClass(MainNonTrivialClass&& other) = delete;

Inisialisasi seragam array dengan cara ini didefinisikan sebagai inisialisasi salinan berdasarkan elemen (?) Dan harus mengarah pada penghapusan salinan jadi saya tidak begitu mengerti, apa yang sebenarnya terjadi di sini. Aturan pra C ++ 17 yang lama tampaknya diterapkan di sini. Keingintahuan lebih lanjut adalah, bahwa kode yang sama dikompilasi dengan baik jika saya menghapus m_nontrivialMember dari MainNonTrivialClass saya tetapi bukankah seharusnya itu menyebabkan kesalahan kompilasi yang sama maka selalu karena kasus non-copy-elision memaksa keberadaan konstruktor salin / pindahkan yang sesuai selalu ?

Jawaban

1 ecatmur Dec 06 2020 at 18:22

Ini juga harus berfungsi sebelum C ++ 17, di mana sintaks ini adalah inisialisasi langsung. Lihat Cara menginisialisasi array kelas dengan konstruktor salinan yang dihapus (C ++ 11) yang merujuk ke bug GCC 63707 .