2016-06-10 9 views
9

Najłatwiej obviosulyskuteczny sposób, aby wstawić unique_ptr do mapy bez usuwania wskaźnik jeśli klucz już istnieje

std::map<int,std::unique_ptr<something>> mymap; 

auto f = mymap.find(5); 
std::unique_ptr<something> myptr; 

if (f == mymap.end()) 
    mymap.insert({5, std::move(myptr)}); 

Jednak to nie wygląda zbyt wydajny, jak mam znaleźć klucz na mapie dwukrotnie. Jeden, aby sprawdzić, czy klucz nie istnieje, a funkcja wstawiania również zrobi to samo.

Jeśli po prostu użyję mymap.insert({5, std::move(myptr)});, mój unikalny ptr (myptr) zniknie, jeśli pair.second zwróci wartość false (klucz już istnieje).

EDIT:

Najwyraźniej odpowiedź jest na C++ 17, z try_emplace, i to jest już dostępny w kompilator używam (vs2015), a ponieważ pracuję nad osobistym projektem, mogę pozwolić sobie na jego użycie.

+1

Dlaczego mówisz, że nie wygląda wydajny? Wygląda dobrze dla mnie. –

+0

Jeśli martwisz się złożonością 'std :: map :: find', to może używasz niewłaściwego kontenera? 'std :: unordered_map' znajduje się na szczycie tablicy, co powoduje, że niektóre operacje O (1) są zamieniane zamiast O (log n) - znalezione znalezisko. – Conduit

+6

Wygląda prawie tak, jakbyś chciał wejść w następnym standardzie ['try_emplace'] (http://en.cppreference.com/w/cpp/container/map/try_emplace) – NathanOliver

Odpowiedz

5

Jeśli nie zamierzamy przechowywać nullptr sw mapy następnie można zrobić to tak:

auto& r = mymap[5]; 
if (r == nullptr) 
    r = std::move(myptr); 
+1

To bardzo ciekawy pomysł! – James

0

Może nie całkiem zrozumieć kontekst, ale dlatego, aby przenieść i nic nie emplace go?

std::map<int,std::unique_ptr<something>> mymap; 

auto f = mymap.find(5); 

if (f == mymap.end()) 
    mymap.emplace(5, std::make_unique<something>(myptr)); 
+1

To nadal powoduje dwukrotne wyszukiwanie, podobnie jak w oryginalnym fragmencie kodu OP. –

2

Standardowa Sztuką jest, aby szukać punktu wstawiania:

auto f = mymap.lower_bound(5); 
if ((f == mymap.end()) || mymap.key_comp()(5, f->first)) { 
    mymap.insert(f, {5, std::move(myptr)}); // or mymap.emplace_hint(f, 5, std::move(myptr)) 
} 
Powiązane problemy