2016-04-06 53 views
8

Ho il seguente shared_ptr ad un map:Inizializzazione std :: shared_ptr <std::map<>> utilizzando rinforzato-init

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

e vorrei inizializzare utilizzando rinforzato-init. È possibile?

ho provato:

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

ma che dà il seguente errore quando compilato utilizzando 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 

Ho provato altre varianti del primo parametro (1000.0) senza successo .

Qualcuno può aiutare?

+0

possibile, ma non abbastanza, 'std :: shared_ptr > foo = std :: mak e_shared > (std :: initializer_list :: value_type> {{1000.0, s1}}); ' –

+0

o solo 'std :: shared_ptr > foo = std :: make_shared > (std :: map {{1000.0, s1}}); 'ma ancora non bello –

+0

Che funziona. Prendo atto dell'uso di 'value_type'. Vedo la sua semplice 'typedef pair '. Perché ne ho bisogno? – ksl

risposta

8

std::map ha un inizializzatore-list costruttore:

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

Siamo in grado di creare una mappa utilizzando questo costruttore abbastanza facilmente:

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

Per utilizzarlo in make_shared, abbiamo bisogno di specificare quale esemplificazione di initializer_list stiamo fornendo:

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

Sembra davvero maldestro; ma se avete bisogno di questo regolarmente, si potrebbe riordinare in su con gli alias:

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

si potrebbe invece preferire di definire una funzione template per avvolgere la chiamata:

#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

Si potrebbe fare 'il_double_to_string' un modello alias in modo che possa funzionare con qualsiasi tipo di mappa. Qualcosa come [questo] (http://coliru.stacked-crooked.com/a/2e73df08f6d1070a). – TartanLlama

+0

Nel caso abbia importanza, ho usato GCC 4.8.2 per testare quanto sopra. –

-2

Someting simile a questo dovrebbe farlo ...

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

o come oneliner

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

(Siamo spiacenti, prima mancava il requisito di lista di inizializzazione)

-4

cambiare la chiave del genere.

double è un tipo errato per le chiavi perché non esiste lo operator== e le sequenze di byte diverse possono rappresentare lo stesso valore in virgola mobile.

+0

Questo non risponde alla domanda. – dreamlax

+0

C'è un operatore == per il doppio - ma è necessario usarlo con attenzione. –

+1

'std :: map' non si preoccupa di' operator == 'tuttavia, non lo usa. –

1

Il tuo problema è che in realtà non hai inserito alcuna parentesi nel tuo inizializzatore. Avevo bisogno di seguito per farlo funzionare:

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

Le doppie std::map<double, std::string> bug me. Dovrebbe essere in grado di risolvere uno di questi dati ... ma gcc 5.3.0 non giocherà a palla.

Avrete sicuramente bisogno delle doppie coppie. (Una volta per dire che stai inizializzando una mappa, una volta per delimitare ogni voce.)

+0

Questo crea un 'initializer_list', costruisce una' map' da esso, quindi copia la 'map'. Sarebbe meglio passare semplicemente 'initializer_list' direttamente a' make_shared' ed evitare la copia 'map'. –

+0

D'accordo assolutamente. (Anche se c'è una possibilità di combattere la copia della mappa sarà una mossa, quindi non è * orrendamente * costoso.) Non riuscivo a farlo funzionare. –

+0

... e Toby Speight ha prodotto la risposta giusta. –

0

si può fare senza std::make_shared:

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