2015-08-28 5 views
7

Ich habe den folgenden Code, der nicht kompilieren wird und es ist Freitag und ich bin ein wenig erschüttert.C++ std :: unique_ptr gespeichert in std :: map Verwendung der gelöschten Funktion ill formed

#include <string> 
#include <memory> 
#include <utility> 
#include <map> 

template< typename T, typename ...Args > 
std::unique_ptr<T> make_unique(Args && ...args) 
{ 
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); 
} 

struct A 
{ 
}; 

std::map< std::string, std::unique_ptr<A> > _map = { { "A", make_unique<A>() } }; // <-- ERROR!! 

Die folgenden compiliert ohne Probleme

int main() 
{ 
    std::pair< std::string, std::unique_ptr<A> > p { "B", make_unique<A>() }; 
    _map.insert(std::make_pair("C", make_unique<A>())); 
} 

Der Fehler, den ich habe, ist immer (grob, wie entfernt g ++ Flaum)

use of deleted function 'constexpr std::pair<...>(const st::pair<...> &) 
'constexp std::pair<...>::pair(const std::pair<...> &) is implicitly deleted because the default definition would be illegal. 

Argghh !! Lesen Sie dies in der C++ 11 Standard.

Wenn ein Aggregat von einer Initialisiererliste initialisiert wird, wie in 8.5.4 angegeben, werden die Elemente der Initialisiererliste als Initialisierungen für die Mitglieder des Aggregats genommen, Subskript oder Mitglied in ansteigender Reihenfolge. Jedes Mitglied ist Kopie initialisiert aus den initializer-Klausel

doofen entsprechenden !!!

Wer weiß, ob es mit Initialisiererlisten einfach unmöglich ist?

+0

Ich brauche das wirklich, um mit den Initialisiererlisten zu arbeiten. Der Code, der kompiliert wurde, war nur zum Beispiel. – ScaryAardvark

+0

Hmm. Ich frage mich nur. Benötigen initialiser_lists ihre Argumente kopierbar? In diesem Fall würde der Fehler Sinn machen, da Sie kein unique_ptr kopieren können – ScaryAardvark

+3

[This] (http://stackoverflow.com/questions/8193102/initializer-list-and-move-semantics) scheint relevant .... –

Antwort

5

Sie können nicht viel dagegen tun: Elemente in einer Initialisierungsliste werden kopiert. Dies wird nicht mit Klassen, die nur bewegen sind, auskommen.

Es gibt eine Möglichkeit, diesen "Fehler" zu umgehen, aber es ist nicht sehr schön zu lesen; Sie entscheiden

using map_type = std::map< std::string, std::unique_ptr<A> >; 
using pair_type = map_type::value_type; 
pair_type elements[] = { { "A", std::make_unique<A>() }, { "B", std::make_unique<A>() } }; 

map_type myMap { std::make_move_iterator(begin(elements)), std::make_move_iterator(end(elements)) }; 

die myMap Iterierte über den Bereich machen und die Elemente innerhalb, anstatt Kopieren bewegen. Methode freundlicherweise genommen von this andere Frage.

+0

Das ist ein guter Weg, um es zu umgehen, aber es ist, wie Sie sagen, nicht nett. Da es jedoch das Problem löst, das ich gerade habe, erhältst du den goldenen Stern: o) – ScaryAardvark