Die emplace
Funktionen aufrufen Konstruktor zum http://eel.is/c++draft/container.requirements.general#15.5
in der Norm beschriebenen
T
ist EmplaceConstructible
in X
von args
, für null oder mehr Argumente args
, bedeutet, dass der folgende Ausdruck ist wohlgeformt :
allocator_traits<A>::construct(m, p, args)
Dies bedeutet, dass es letztlich zu Ihrem Allokator kommt. Mit Blick auf die Referenz für das, was das bedeutet nennt, können wir http://en.cppreference.com/w/cpp/memory/allocator_traits/construct
überprüfen Wir sehen, dass, wenn der Zuordner nicht über ein Konstrukt Elementfunktion, oder wenn es std::allocator
ist, dann ist der Anruf entspricht
::new (static_cast<void*>(p)) T(std::forward<Args>(args)...)
Für std::map<int, A>
ist der Typ T
in Ihrem Ausdruck std::pair<int const, A>
und args...
ist . Um zu wissen, ob Ihr Anruf bei emplace
wohlgeformt ist, müssen wir nur entscheiden, ob ein Anruf an std::pair<int const, A>(1, 2)
gültig ist.Also für das, schauen wir auf die Dokumentation für std::pair
: http://en.cppreference.com/w/cpp/utility/pair/pair
Der Konstruktor in Frage steht auf der Liste /*EXPLICIT*/ constexpr pair(const T1& x, const T2& y);
(vorausgesetzt, C++ 17). Mit anderen Worten, es ist wie beim Aufruf einer regulären Funktion, die int const &
als erstes Argument und A const &
als zweites Argument annimmt. A
ist nur explizit von int
konstruierbar, also ist Ihr Anruf schlecht gebildet. Der Aufruf emplace
speichert Sie nur von explicit
auf alle Objekte, die Sie direkt erstellen, in diesem Fall nur std::pair
, keine Argumente für diesen Typ.
Dies hat mit den bedingten expliziten Konstruktoren zu tun, die formell in C++ 17 hinzugefügt wurden, aber von neueren Versionen von GCC in C++ 11 und später implementiert wurden. –
Ich benutzte C++ 14 Flags, aber ich habe gcc Version 4.9.2. Ich habe versucht mit gcc 6.2 und jetzt beide "m.insert (Paar (1, 2)) und m.emplace (1, 2);" kompilieren. Auch für map.emplace glaube ich nicht, dass make_pair benutzt werden muss. –