2017-11-25 3 views
3

Warum kann ich nicht die Klammer Initialisierung der Karte mit unique_ptr?C++ Map Brace Initialisierung und eindeutige ptr

Edit: Ich benutze gcc 7.2 in C++ 17 Modus.

Ich kann erstellen und einfügen in ungeordneter Zuordnung mit make_pair und dem Operator [].

Aber ich kann nicht herausfinden, warum es bei der Verwendung von Klammern fehlschlägt.

map.insert({"foo", std::make_unique<A>()}); // Error 

error: use of deleted function ‘std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&)

+1

Sie sind C++ 14 verwenden, denn bevor es keine 'std :: war make_unique'. – Rakete1111

+1

afaik fügt Kopien ein (unique_ptr ist nicht kopierbar), benutze emplace – Sopel

Antwort

1

Da C++ 11, Insertion assoziativen Container erfordert entweder copy-costructible lvalues ​​oder move-einführbaren veränderbare rvalues. Also, es gibt kein Problem beim Aufruf insert() zusammen mit make_pair(), wie Sie tun: Letzteres erstellt eine pair<const char[],unique_ptr>, die verwendet wird, um einen value_type rvalue zu initialisieren.

Das Problem mit der Klammer Initialisierung ist, dass (bis C++ 17) die value_type const & Überlastung bevorzugt wird (weil es & & Überlastung keine richtige value_type ist), also eine Kopie angefordert wird und ein Fehler ausgelöst wird.

In der Tat, beachten Sie, dass beide Formulare in gcc Stamm und 5 (mit libC++) im C++ 17-Modus kompilieren.


Genauer gesagt, von C++ 11 auf, die entsprechenden Einsatz semantischen Anforderungen lesen

[unord.req] If t is a non-const rvalue expression, value_type shall be MoveInsertable into X; otherwise, value_type shall be CopyInsertable into X.

die tatsächlichen Mitglieder Spezifikation ist, wo die Dinge unterscheiden; bis C 17 ++, haben wir:

pair<iterator, bool> insert(const value_type& obj); 
template <class P> pair<iterator, bool> insert(P&& obj); 
... 

wo die allgemeine Überlastung SFINAE zu std::is_constructible<value_type, P&&>::value eingeschränkt. Bei Verwendung einer braced-init-Liste wird die Überladung const & hier ausgewählt (Anmerkung: Es gibt auch eine initializer_list-Überladung, aber dies gilt nicht für den OP-Fall).

Stattdessen in C++ 17 haben wir auch

pair<iterator, bool> insert(value_type&& obj); 
+0

sieht aus wie gcc support für C++ 17 ist noch experimentell (https://gcc.gnu.org/projects/cxx-status.html), deshalb ist es nicht t kompiliere für mich (gcc 7.2). Tolle Erklärung. Vielen Dank. –

Verwandte Themen