2008-10-30 16 views
28

Ich möchte eine Karte mit einem einheitlichen Schlüsseltyp, aber heterogenen Datentypen haben.Wie erstellt man eine heterogene boost :: map?

Ich möchte in der Lage sein, etwas zu tun, wie (Pseudo-Code):

boost::map<std::string, magic_goes_here> m; 
m.add<int>("a", 2); 
m.add<std::string>("b", "black sheep"); 

int i = m.get<int>("a"); 
int j = m.get<int>("b"); // error! 

ich einen Zeiger auf eine Basisklasse als Datentyp haben könnte, aber lieber nicht.

Ich habe noch nie Boost verwendet, aber habe die Fusion-Bibliothek angeschaut, kann aber nicht herausfinden, was ich tun muss.

Danke für Ihre Hilfe.

+2

'boost :: variant' –

+0

Wenn Sie alle möglichen Typen kennen, die Sie in der Karte stopfen möchten, dann wird' boost :: variant 'großartig funktionieren. Wenn Sie buchstäblich jeden Typ wollen, dann ist 'boost :: any' der richtige Weg. – Kurt

Antwort

34
#include <map> 
#include <string> 
#include <iostream> 
#include <boost/any.hpp> 

int main() 
{ 
    try 
    { 
     std::map<std::string, boost::any> m; 
     m["a"] = 2; 
     m["b"] = static_cast<char const *>("black sheep"); 

     int i = boost::any_cast<int>(m["a"]); 
     std::cout << "I(" << i << ")\n"; 

     int j = boost::any_cast<int>(m["b"]); // throws exception 
     std::cout << "J(" << j << ")\n"; 
    } 
    catch(...) 
    { 
     std::cout << "Exception\n"; 
    } 

} 
+1

Anstelle der umständlichen_Sendung können Sie 'std :: decay' verwenden. –

+0

ist es nicht nur mit std :: map statt boost map als initialisiert [hier] (http://www.boost.org/doc/libs/1_35_0/libs/fusion/doc/html/fusion/container/map. html)? – Tab

9

How can I build a <favorite container> of objects of different types?

Sie können nicht, aber Sie können gefälschte es ziemlich gut. In C/C++ sind alle Arrays homogen (d. H. Die Elemente sind alle vom selben Typ). Mit einer zusätzlichen indirekten Ebene können Sie jedoch den Eindruck eines heterogenen Containers geben (ein heterogener Container ist ein Container, in dem die enthaltenen Objekte unterschiedliche Typen aufweisen).

Es gibt zwei Fälle mit heterogenen Containern.

Der erste Fall tritt ein, wenn alle Objekte, die Sie in einem Container speichern möchten, öffentlich aus einer gemeinsamen Basisklasse abgeleitet werden. [...]

Der zweite Fall tritt auf, wenn die Objekttypen disjunkt sind - sie teilen keine gemeinsame Basisklasse.
Der Ansatz hier ist, eine Handle-Klasse zu verwenden. Der Container ist ein Container mit Handle-Objekten (nach Wert oder per Zeiger, Ihre Auswahl; nach Wert ist einfacher). Jedes Handle-Objekt weiß, wie man an einem der Objekte, die in den Container eingefügt werden sollen, "festhält" (d. H. Einen Zeiger auf dieses Objekt hält). Sie können entweder eine einzelne Handle-Klasse mit mehreren verschiedenen Zeigertypen als Instanzdaten oder eine Hierarchie von Handle-Klassen verwenden, die die verschiedenen Typen schattieren, die Sie enthalten möchten (der Container muss aus Handle-Basisklassenzeigern bestehen). Der Nachteil dieses Ansatzes besteht darin, dass die Handle-Klasse (n) für die Wartung jedes Mal geöffnet werden, wenn Sie die Menge der Typen ändern, die enthalten sein können. Der Vorteil ist, dass Sie die Handle-Klasse (n) verwenden können, um den größten Teil der Hässlichkeit der Speicherverwaltung und Objektlebensdauer einzukapseln. Somit kann die Verwendung von Griffobjekten auch im ersten Fall vorteilhaft sein.

5

Wenn Sie möchten, dass eine begrenzte Anzahl von Typen unterstützt wird, sollte Boost.Variant den Trick machen.

5

Danke David, das war was ich brauchte. Hier ist die Arbeitslösung.

#include <iostream> 
using std::cout; 
using std::endl; 

#include <map> 
#include <boost/any.hpp> 

using boost::any_cast; 
typedef std::map<std::string, boost::any> t_map; 


int main(int argc, char **argv) 
{ 

    t_map map; 
    char *pc = "boo yeah!"; 

    map["a"] = 2.1; 
    map["b"] = pc; 

    cout << "map contents" << endl; 
    cout << any_cast<double>(map["a"]) << endl; 
    cout << any_cast<char*>(map["b"]) << endl; 

    return 0; 
} 
+1

sollte dies sein 'const char * pc =" boo yeah! ";' –

0

Boost jeder funktioniert sicherlich, aber ich denke, Int mit Typ Technologie als der Schlüssel-Typ der Fusion Karte ist eine bessere Lösung. Kein Typ löschen und möglicherweise schneller

Verwandte Themen