2016-04-06 15 views
8

Ich habe folgend shared_ptr zu einem map:Initialisierung std :: shared_ptr <std::map<>> mit verspannten-init

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

und ich würde es initialisieren wie verspannt-init. Ist es möglich?

Ich habe versucht:

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

aber das gibt den folgenden Fehler, wenn 6.3 unter Verwendung von Xcode kompiliert:

/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 

ich andere Variationen des ersten Parameters versucht haben (1000.0) ohne Erfolg .

Kann jemand helfen?

+0

möglich, aber nicht hübsch, 'std :: shared_ptr > foo = std :: mak e_shared > (std :: initialisiererliste :: wertetyp> {{1000.0, s1}}); ' –

+0

oder einfach 'std :: shared_ptr > foo = std :: make_shared > (std :: map {{1000.0, s1}}); 'aber immer noch nicht nett –

+0

Das funktioniert. Ich bemerke die Verwendung von 'value_type'. Ich sehe es nur 'typedef Paar '. Warum brauche ich das? – ksl

Antwort

8

std::map eine Initialisierer-Liste Konstruktor hat:

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

Wir diesen Konstruktor erstellen können ganz einfach eine Karte mit:

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

Um es in make_shared zu verwenden, müssen wir die Instanziierung angeben von initializer_list wir bieten:

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

Das sieht wirklich tollpatschig aus; aber wenn Sie dies regelmäßig benötigen, können Sie es aufzuräumen mit Aliasnamen:

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

Sie könnten stattdessen lieber eine Template-Funktion definieren, um den Anruf zu wickeln:

#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

Sie könnten "il_double_to_string" eine Alias-Vorlage erstellen, damit sie mit jedem Kartentyp funktioniert. Etwas wie [dies] (http://coliru.stacked-crooked.com/a/2e73df08f6d1070a). – TartanLlama

+0

Falls es darauf ankommt, habe ich GCC 4.8.2 verwendet, um das Obige zu testen. –

-2

Someting ähnlich wie diese es tun sollten ...

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

oder als oneliner

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

(Sorry, zunächst die Forderung nach Initialisiererliste verpasst)

-4

Ändern Sie den Schlüssel des Art.

double ist ein falscher Typ für Schlüssel, da es kein operator== für es gibt und verschiedene Bytefolgen den gleichen Gleitkommawert darstellen können.

+0

Dies beantwortet die Frage nicht. – dreamlax

+0

Es gibt einen Operator == für Doppel - aber Sie müssen es vorsichtig verwenden. –

+1

'std :: map' kümmert sich nicht um' operator == 'obwohl es nicht verwendet wird. –

1

Ihr Problem besteht darin, dass Sie in Ihrem Initialisierer keine geschweiften Klammern eingefügt haben. Ich brauchte die folgende, um es zu arbeiten: me

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

Die Doppel std::map<double, std::string> Bugs. Es sollte wirklich in der Lage sein, einen von ihnen mit dem anderen auszuarbeiten ... aber gcc 5.3.0 würde keinen Ball spielen.

Sie werden auf jeden Fall die Doppelstreben brauchen. (Einmal sagen Sie, dass Sie eine Karte initialisieren, einmal um jeden Eintrag zu begrenzen.)

+0

Das erstellt eine 'initializer_list', erstellt daraus eine' map' und kopiert dann die 'map'. Es wäre besser, die 'initializer_list' direkt an' make_shared' zu übergeben und die 'map' Kopie zu vermeiden. –

+0

Stimme absolut zu. (Obwohl es eine kämpferische Chance gibt, wird die Kartenkopie ein Zug sein, also ist es nicht * horrend * teuer.) Ich konnte es nicht zum Laufen bringen. –

+0

... und Toby Speight hat die richtige Antwort geliefert. –

0

Sie es tun können ohne std::make_shared:

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