wake-up-neo.com

Wie kann ich Objekte unterschiedlichen Typs in einem C++ - Container speichern?

Gibt es einen C++ - Container, den ich verwenden oder erstellen könnte, der int- und string- und double-Typen enthalten kann? Das Problem, mit dem ich konfrontiert bin, ist, dass immer, wenn ich versuche, eine Karte, einen Vektor oder eine Liste mit den folgenden Angaben zu füllen:

int x;
string y;
double z;

Ich bin mit dem Format eingeschränkt:

list<int> mycountainer;
vector<string> mycontainer;

welche mycontainer zwingt, nur aus einem Typ zu bestehen.

Bevor irgendjemand Generics vorschlägt, würde dies auch nicht funktionieren, da die vector- und list-Standardcontainer, die mit C++ geliefert werden, bereits generisch sind - sie können Container für beliebige Typen sein, jedoch nicht mehrere Typen.

Ich würde Boost auch gerne vermeiden, wenn überhaupt möglich - ich würde es vorziehen, wenn es eine einfache Möglichkeit gibt, dies selbst zu programmieren.

Hey, vielen Dank für Ihre Vorschläge - ich sollte erklären, wie ich diesen Container verwende, aber es ist ein bisschen kompliziert, daher die (große) Vereinfachung oben. Ich denke, die beste Option von hier ist die Verwendung des Boost. Danke noch einmal.

24
Ramsey

Sie können boost::any verwenden (oder erneut implementieren) und Instanzen von boost::any in einem Container speichern. Das wäre am sichersten, da boost::any sich wahrscheinlich mit den meisten Edge-Fällen und der Komplexität befasst hat, die bei der Lösung dieser Art von Problemen im allgemeinen Fall erforderlich sind.

Wenn Sie etwas schnell und schmutzig machen möchten, erstellen Sie eine Struktur oder eine Vereinigung, die Mitglieder aller möglichen Typen zusammen mit einer Aufzählung oder einem anderen Indikator enthält, welcher Typ im Objekt "aktiv" ist. Seien Sie besonders vorsichtig bei Gewerkschaften, da sie einige interessante Eigenschaften haben (z. B. das Aufrufen von undefiniertem Verhalten, wenn Sie das falsche Gewerkschaftsmitglied lesen. Nur eines der Mitglieder kann zu einem Zeitpunkt "aktiv" sein, in das zuletzt geschrieben wurde).

Ich bin neugierig, was Sie tun, dass Sie so ein Konstrukt brauchen.

21
Josh

Nun, die erste Frage wäre:Warum müssen Sie Objekte verschiedener, völlig unabhängiger Typen in demselben Container speichern?Das kommt mir fischig vor. 

Wenn ich die Notwendigkeit hätte, würde ich nach boost::variant oder boost::any suchen. 

13
sbi

Was Sie wollen, wird als "hetrogener Container" bezeichnet. C++ unterstützt sie in der STL technisch nicht, Boost jedoch.

Angesichts dessen, denke ich, werden Sie Ihre Antwort in dieser Frage finden: Wie-machst-du-eine-heterogene-Boostmap

6
T.E.D.

Sie können entweder Strukturen oder Klassen oder std :: pair verwenden.

[bearbeiten]

Für Klassen und Strukturen:

struct XYZ {
    int x;
    string y;
    double z;
};
std::vector<XYZ> container;

XYZ el;
el.x = 10;
el.y = "asd";
el.z = 1.123;
container.Push_back(el);

Für std :: pair:

#include <pair>
typedef std::pair<int, std::pair<string, double> > XYZ;
std::vector<XYZ> container;
container.Push_back(std::make_pair(10, std::make_pair("asd", 1111.222)));
2
ssmir

Die einfachste Methode ist natürlich, eine Struktur oder Klasse zu definieren, die Mitglieder jedes Typs enthält, den Sie speichern möchten. Joshs Antwort schlägt Boost.Any vor, was so ziemlich alles aufnehmen wird . Wenn Sie die Werte nur auf die Typen int, double und std::string beschränken möchten, wählen Sie bessere Wahl wäre Boost.Variant .

Wenn Sie Boost einfach nicht verwenden möchten , dann schlage ich vor, dass Sie Ihre Probleme überwinden und es trotzdem verwenden. "Nicht hier erfunden" ist eine selbstzerstörerische Politik. Wenn Sie Boost nicht verwenden können , können Sie stattdessen Ihre eigene Variantenklasse schreiben. Andrei Alexandrescu schrieb vor ein paar Jahren eine dreiteilige Serie zu diesem Thema ( Teil 1 , Teil 2 , Teil ) und inspirierte sein Design der Boost verwendet.

0
Rob Kennedy

Sie können eine Struktur verwenden, die alle drei enthält.

struct Data
{
    int intVal;
    std::string stringVal;
    double doubleVal;
};

Dann können Sie einfach list mycontainer<Data> deklarieren und den entsprechenden Wert verwenden, vorausgesetzt, Sie kennen den Werttyp. Wenn nicht, fügen Sie der Struktur ein zusätzliches Feld hinzu, das Sie darüber informiert, welcher der drei Datentypen verwendet wird.

struct Data
{
    enum DATATYPE { DT_INT, DT_STRING, DT_DOUBLE } type;

    int intVal;
    std::string stringVal;
    double doubleVal;
};

Wenn Sie sich Sorgen um die Speicherauslastung machen, könnten Sie wahrscheinlich eine Vereinigung verwenden, obwohl ich sie normalerweise nicht nutze. Es könnte jedoch unnötige Paranoia sein.

0
James

Wenn Sie über eine begrenzte Anzahl von Elementen verfügen, die Sie speichern müssen, legen Sie sie in eine Klasse oder Struktur.

Wenn für die Elemente, die Sie in diesem Container aufbewahren müssten, keine Begrenzung besteht, sollten Sie eine andere Vorgehensweise suchen. Die einzige Möglichkeit besteht darin, sie als Objekt zu speichern und sie dann in einen eigenen Typ umzuwandeln müssen auf sie zugreifen.

Wenn sich jedoch möglicherweise ein Element im Container befindet, können Sie nicht wissen, um welche Art von bestimmten Elementen sich der Container handelt. Daher können Sie sie nicht umsetzen.

Wenn C++ Reflektion enthielt, wäre dies möglicherweise möglich, aber C++ hat keine Reflektion.

0
jcvandan