2015-08-28 10 views
7

Mam następujący kod, który się nie skompiluje, a jest piątek i jestem trochę sparaliżowany.C++ std :: unique_ptr przechowywany wewnątrz std :: map użycie usuniętej funkcji źle utworzonej

#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!! 

Poniższe kompilacji bez problemu

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

Błąd Dostaję jest (w przybliżeniu, ponieważ usunięto g ++ puch)

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 !! Po prostu przeczytaj to w standardzie C++ 11.

Kiedy agregat jest inicjowany przez liście inicjatora, jak określono w 8.5.4, elementy listy inicjatora są traktowane jako inicjalizatory członków kruszywa, w zwiększaniu indeks lub członek zamówienia. Każdy członek kopiowaniem inicjowane z odpowiadające inicjator klauzula

bummer !!!

Ktoś wie, czy jest to po prostu niemożliwe z listami inicjalizującymi?

+0

Naprawdę potrzebuję tego do pracy z listami inicjalizacyjnymi. Kod, który kompiluje, był tylko na przykład. – ScaryAardvark

+0

Hmm. Zastanawiam się. Czy lista initialiser_lists wymaga, aby ich argumenty były kopiowalne? W takim przypadku błąd miałby sens, ponieważ nie można skopiować pliku unique_ptr – ScaryAardvark

+3

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

Odpowiedz

5

Nie można wiele z tym zrobić: elementy na liście inicjalizującej są kopiowane. Nie pogodzi się to z klasami przenoszącymi ruch.

Istnieje sposób na ominięcie tego "defektu", ale nie jest to zbyt miłe do odczytania; zdecydujesz

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

które uczynią myMap iteracyjne nad zakresu i przenieść elementy wewnątrz, zamiast kopiowania. Metoda uprzejmie zaczerpnięta z innego pytania z this.

+0

To dobry sposób na obejście tego, ale jest, jak mówisz, niezbyt miły. Jednakże, ponieważ rozwiązuje to problem, który mam w tej chwili, otrzymujesz złotą gwiazdę: o) – ScaryAardvark

Powiązane problemy