Élision de copie garantie pour l'initialisation de tableaux à accolades uniformes - Cela ne devrait-il pas être obligatoire depuis C ++ 17? [dupliquer]

Dec 06 2020

Pour autant que je comprends correctement les nouvelles règles

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

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

Ce code doit être compilé pour les compilateurs conformes à la norme 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;
}

Mais gcc 9.1.0 avec -std = c ++ 17 -O2 -Wall -pedantic dit (comme totalement attendu pour pré 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;

L'initialisation uniforme d'un tableau de cette façon est définie comme une initialisation de copie élément par élément (?) Et devrait conduire à une élision de copie, donc je ne comprends pas vraiment ce qui se passe réellement ici. Les anciennes règles pré C ++ 17 semblent être appliquées ici. Une autre curiosité est que le même code se compile correctement si je supprime m_nontrivialMember de ma MainNonTrivialClass mais que cela ne devrait pas conduire à la même erreur de compilation alors toujours puisque le cas de non-élision de copie force toujours l'existence des constructeurs de copie / déplacement correspondants. ?

Réponses

1 ecatmur Dec 06 2020 at 18:22

Cela devrait également fonctionner avant C ++ 17, où cette syntaxe est l'initialisation directe. Voir Comment initialiser un tableau de classes avec un constructeur de copie supprimé (C ++ 11) qui fait référence au bogue GCC 63707 .