2016-04-06 21 views
8

Mam następujący shared_ptr do map:Inicjowanie std :: shared_ptr <std::map<>> using usztywnione inicjalizacji

std::shared_ptr<std::map<double, std::string>> 

i chciałbym zainicjować go za pomocą usztywnione inicjalizacji. Czy to możliwe?

Próbowałem:

std::string s1("temp"); 
std::shared_ptr<std::map<double, std::string>> foo = std::make_shared<std::map<double, std::string>>(1000.0, s1); 

ale daje następujący błąd podczas skompilowany przy użyciu Xcode 6.3:

/usr/include/c++/v1/map:853:14: Candidate constructor not viable: no known conversion from 'double' to 'const key_compare' (aka 'const std::__1::less<double>') for 1st argument 

Próbowałem innych odmian pierwszego parametru (1000,0), bez powodzenia .

Czy ktoś może pomóc?

+0

możliwe, ale nie ładna, 'std :: shared_ptr > foo = std :: MAK e_shared > (std :: initializer_list :: value_type> {{1000.0, s1}}); ' –

+0

lub po prostu 'std :: shared_ptr > foo = std :: make_shared > (std :: map {{1000.0, s1}}); 'ale nadal niezbyt miły –

+0

To działa. Zauważam użycie 'value_type'. Widzę jego właśnie 'typedef pair '. Dlaczego tego potrzebuję? – ksl

Odpowiedz

8

std::map ma konstruktora inicjator-listy:

map (initializer_list<value_type> il, 
    const key_compare& comp = key_compare(), 
    const allocator_type& alloc = allocator_type()); 

Możemy stworzyć mapę przy użyciu tego konstruktora dość łatwo:

std::map<double,std::string> m1{{1000.0, s1}}; 

go używać w make_shared, musimy określić, który konkretyzacji z initializer_list dostarczamy:

auto foo = std::make_shared<std::map<double,std::string>> 
      (std::initializer_list<std::map<double,std::string>::value_type>{{1000.0, s1}}); 

To wygląda naprawdę niezdarnie; ale jeśli trzeba to regularnie, można uporządkować go z aliasów:

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

std::string s1{"temp"}; 

using map_ds = std::map<double,std::string>; 
using il_ds = std::initializer_list<map_ds::value_type>; 

auto foo = std::make_shared<map_ds>(il_ds{{1000.0, s1}}); 

Można zamiast tego wolą zdefiniować funkcję szablonu zawinąć połączenia:

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

template<class Key, class T> 
std::shared_ptr<std::map<Key,T>> 
make_shared_map(std::initializer_list<typename std::map<Key,T>::value_type> il) 
{ 
    return std::make_shared<std::map<Key,T>>(il); 
} 

std::string s1{"temp"}; 
auto foo = make_shared_map<double,std::string>({{1000, s1}}); 
+2

Możesz utworzyć 'al_double_to_string' jako szablon alias, aby działał z dowolnym typem mapy. Coś takiego jak [this] (http://coliru.stacked-crooked.com/a/2e73df08f6d1070a). – TartanLlama

+0

Jeśli to ma znaczenie, użyłem GCC 4.8.2, aby przetestować powyższe. –

-2

cos podobnego do tego powinno wystarczyć ...

std::string s1("temp"); 

std::map<double, std::string> *m = new std::map<double, std::string>{{100., s1}}; 

auto foo = std::shared_ptr<std::map<double, std::string>>(m); 

lub jako oneliner

auto foo2 = std::shared_ptr<std::map<double, std::string>>(new std::map<double, std::string>{{100., s1}}); 

(Niestety, pierwszy nieodebranych wymóg liście inicjatora)

-4

zmienić klucz'S rodzaj.

to zły typ dla kluczy, ponieważ nie ma w nim operator==, a różne sekwencje bajtów mogą reprezentować tę samą wartość zmiennoprzecinkową.

+0

To nie odpowiada na pytanie. – dreamlax

+0

Jest operator == dla podwójnego - ale musisz go używać ostrożnie. –

+1

'std :: map' nie dba o' operator == 'chociaż, nie używa go. –

1

Twój problem polega na tym, że w twoim inicjatorze nie wstawiłeś żadnych nawiasów klamrowych. Potrzebowałem następujące aby zmusić go do pracy:

auto foo = std::make_shared<std::map<double, std::string> >(
         std::map<double, std::string>({{1000.0, s1}}) 
      ); 

std::map<double, std::string> podwójne błędy mnie. To naprawdę powinno być w stanie wypracować jedną z nich, biorąc pod uwagę drugą ... ale gcc 5.3.0 nie zagrałby w piłkę.

Zdecydowanie potrzebujesz podwójnych szelek. (Raz powiedzieć, że zainicjalizujesz mapę, raz, aby ograniczyć każdy wpis.)

+0

To tworzy 'initializer_list', tworzy z niej' map', a następnie kopiuje 'map'. Lepiej byłoby po prostu przekazać 'initializer_list' bezpośrednio do' make_shared' i ominąć kopię 'map'. –

+0

Zgadzam się absolutnie. (Chociaż istnieje szansa na walkę, kopia mapy będzie ruch, więc nie jest * horrendously * drogie.) Nie mogłem go uruchomić. –

+0

... a Toby Speight dostarczył prawidłową odpowiedź. –

0

można to zrobić bez std::make_shared:

std::shared_ptr<std::map<double,std::string>> ptr(new std::map<double,std::string>({{1000.0, "string"}})); 
Powiązane problemy