Ich erhalte Kompilierungsfehler bei g++ (GCC) 4.7.2
, aber nicht bei MSVC-2012
, wenn versucht wird, std::vector::push_back
ein nicht kopierbares (privater Kopierkonstruktor), aber bewegliches Objekt. Für mich sieht mein Beispiel identisch mit vielen anderen Beispielen auf SO und anderswo aus. Die Fehlermeldung lässt es als ein Problem erscheinen, dass die Struktur nicht "direkt konstruierbar" ist - ich weiß nicht, was das bedeutet, bin also doppelt unsicher, warum ein Objekt "direkt konstruierbar" sein muss, um zurückgeschoben zu werden.
Gibt Fehler
%Vor%Einfache Abhilfe aus verschiedenen Antworten:
MyStruct(const MyStruct&) = delete;
anstelle von private ctor
hack boost::noncopyable
(oder eine andere Klasse mit privatem ctor) Der Fehler ist auf eine Einschränkung von G ++ 4.7 zurückzuführen, das DR 1170 , das sehr spät im C ++ 11-Standardisierungsprozess geändert wurde, um zu sagen, dass die Zugriffsprüfung als Teil der Template-Argumentableitung durchgeführt werden sollte.
Die zugrunde liegende Ursache ist, dass libstdc ++ vector
Elemente verschiebt, wenn die move-Operation garantiert nicht geworfen wird (dh es wird noexcept
oder throw()
deklariert), ansonsten werden die Elemente kopiert, wenn der Typ kopierbar ist Wenn der Typ nicht kopierbar ist, aber eine möglicherweise auswerfende Verschiebungsoperation aufweist, wird er verschoben (und wenn eine Ausnahme ausgelöst wird, sind die Ergebnisse undefiniert ). Dies wird mit Prüfungen für% co_de implementiert % und is_nothrow_move_constructible
Typmerkmale. In Ihrem Fall ist der Typ nicht notwow move constructible, daher wird das Merkmal is_copy_constructible
überprüft. Ihr Typ hat einen Kopierkonstruktor, auf den aber nicht zugegriffen werden kann, daher erzeugt das Merkmal is_copy_constructible
einen Compilerfehler mit G ++ 4.7, da die Zugriffsprüfung nicht während der Ableitung des Vorlagenarguments erfolgt.
Wenn Sie den Verschiebungskonstruktor setzen und den Zuweisungsoperator is_copy_constructible
verschieben, wird der Typ verschoben und muss nicht kopierbar sein. Daher wird die noexcept
Eigenschaft, die fehlschlägt, nicht verwendet und der Code wird kompiliert / p>
Alternativ, (wie auch in den Kommentaren angegeben), wenn Sie den Kopierkonstruktor löschen, erhält das is_copy_constructible
Merkmal das richtige Ergebnis.
Eine andere Alternative ist die Verwendung von is_copy_constructible
, die den Kopierkonstruktor implizit löscht, so dass das Merkmal boost::noncopyable
ordnungsgemäß funktioniert (und auch mit älteren Compilern wie MSVC funktioniert, die gelöschte Funktionen nicht ordnungsgemäß unterstützen). Ich weiß nicht, was Sie damit meinen, es unmöglich zu machen, den Fehler zu finden, zeigt Ihnen MSVC nicht den vollen Zusammenhang eines Compilerfehlers?
Fazit: Verwenden Sie gegebenenfalls unique_ptr, aber machen Sie Klassen nicht explizit beweglich
Ich stimme dieser Schlussfolgerung nicht zu, es ist zu extrem. Stattdessen sollten Sie Ihre Klassen möglichst nicht bewegbar machen. Wenn möglich, verwenden Sie gelöschte Funktionen, um einen Typ nicht kopierbar anstelle von privaten + nicht implementierten Funktionen zu machen, möglicherweise unter Verwendung eines Makros für die Portabilität zu älteren Compilern, z. B.
%Vor%