Garantierte Kopierentfernung für eine einheitliche Array-Initialisierung - Sollte dies seit C ++ 17 nicht obligatorisch sein? [Duplikat]

Dec 06 2020

Soweit ich die neuen Regeln richtig verstehe

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

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

Dieser Code sollte für standardkonforme C ++ 17-Compiler kompiliert werden

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;
}

Aber gcc 9.1.0 mit -std = c ++ 17 -O2 -Wall -pedantic sagt (wie für vor C ++ 17 völlig erwartet)

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;

Eine einheitliche Array-Initialisierung auf diese Weise wird als elementweise Kopierinitialisierung (?) Definiert und sollte zur Kopierelision führen, sodass ich nicht wirklich verstehe, was hier tatsächlich vor sich geht. Die alten Regeln vor C ++ 17 scheinen hier angewendet zu werden. Eine weitere Kuriosität ist, dass derselbe Code gut kompiliert wird, wenn ich m_nontrivialMember aus meiner MainNonTrivialClass entferne, aber nicht immer zum gleichen Kompilierungsfehler führen sollte, da der Fall der Nicht-Kopier-Elision immer die Existenz der entsprechenden Kopier- / Verschiebungskonstruktoren erzwingt ?

Antworten

1 ecatmur Dec 06 2020 at 18:22

Dies sollte auch vor C ++ 17 funktionieren, wo diese Syntax eine direkte Initialisierung ist. Siehe Initialisieren eines Klassenarrays mit einem gelöschten Kopierkonstruktor (C ++ 11), der auf den GCC-Fehler 63707 verweist .