map mit struct und variant
-
Moin zusammen!
Folgenden Code habe ich:
#include <variant> #include <string> #include <map> #include <iostream> struct sbasic{ unsigned short int length; // laenge unsigned short int width; // breite unsigned short int height; // hoehe unsigned short int type; // art unsigned long long int x; // Position unsigned long long int y; // Position unsigned long long int z; // Position }; //zuladung struct spayload{ unsigned short int type; // art }; //zuladung menge struct spayloadamount{ unsigned short int type[64]; // art unsigned short int amount[64]; // menge an zuladung }; int main(int argc, char *argv[]) { std::map<sbasic, std::variant<spayload,spayloadamount>> mm; mm.insert ( std::pair<unsigned short int,unsigned short int,unsigned short int,unsigned short int,unsigned long long int,unsigned long long int,unsigned long long int>(100,100,100,100,100,100,100) ) return 0; }Mein Ziel ist es, eine map zu erstellen mit variablen Inhalt.
Soll heißen, je nachdem welchen Wert die Variable "type" in "sbasic" hat, möchte ich die beiden anderen struct Strukturen mit einbeziehen.Leider bekomme ich jetzt schon folgende Fehlermeldung:
[Error] wrong number of template arguments (7, should be 2)
Auch wenn ich nur 2 Argumente habe, wird das Kompilieren mit Fehlern abgebrochen.
Könnt ihr mir bitte weiter helfen?
Vielen Dank im Voraus.
-
@no_name1991 Nur kurz vom Handy:
So funktioniert das mit Maps und Pairs nicht.
Ein pair ist ein Tuple aus genau zwei Typen.
Eine Map ist ein Container von einem Pair Typen. Die Doku redet dabei von "key value Pairs". Dabei ist wichtig, dass der Key Teil Vergleichbar ist. Wenn der Typ nicht einfach vergleichbar ist, musst du das selbst definieren und implementieren.
-
@Schlangenmensch sagte in map mit struct und variant:
Vergleichbar
Genauer gesagt, sollte es einen Comperator und Hasher geben, je nachdem, welche Map Implementierung man wählt (unordered_map ist die schnellste)...
(Auch ich schreibe gerade vom Handy, man möge daher Rechtschreibfehler bitte billigen...)
-
@dubios Hier im Post nutzt der TE eine
std::mapund keinestd::unordered_map. Diestd::maphat keinen Hasher.
-
Die Problemstellung ist also, dass Du eine polymorphe Map haben willst, deren value type von dem Wert des keys abhängt.
Das ist ein bereits gelöstes Problem mit vielen Lösungswegen:
- map value kann einfach ein
variantwerden, den Du dann manuell entsprechend demtypeinitialisierst - Du kannst einen polymorphen Map container benutzen, entweder mit vollwertiger type erasure oder variants, siehe e.g. Boost PolyCollection und aehnliches
- Du machst die Klassen
spayloadamountetc. selbst polymorph mit einer Basisklasse, die dann zum map value wird
Pauschal ist 3. fuer mich am saubersten, in diesem Fall scheint es eine Art composite pattern zu sein, musst Du aber selbst entscheiden.
- map value kann einfach ein
-
@Schlangenmensch sagte in map mit struct und variant:
eine std::map und keine std::unordered_map
ich sage doch, je nachdem, welche Map man will. eine std::map ist selten die sinnvollste Wahl.
-
@no_name1991 Ich hatte vorhin einen kurzen Schnack mit Copilot... ich glaube, du meintest das so:
#include <iostream> #include <map> #include <optional> #include <tuple> struct sbasic { unsigned short int length; // laenge unsigned short int width; // breite unsigned short int height; // hoehe unsigned short int type; // art unsigned long long int x; // Position unsigned long long int y; // Position unsigned long long int z; // Position bool operator<(const sbasic &other) const { return std::tie(length, width, height, type, x, y, z) < std::tie(other.length, other.width, other.height, other.type, other.x, other.y, other.z); } }; // zuladung struct spayload { unsigned short int type; // art bool operator<(const spayload &other) const { return type < other.type; } }; // zuladung menge struct spayloadamount { unsigned short int type[64]; // art unsigned short int amount[64]; // menge an zuladung }; int main(int argc, char *argv[]) { std::map<spayload, std::map<sbasic, std::optional<spayloadamount>>> m; m.insert(std::make_pair(spayload{1}, std::map<sbasic, std::optional<spayloadamount>>{})); m.insert(std::make_pair(spayload{2}, std::map<sbasic, std::optional<spayloadamount>>{})); m[spayload{1}].insert(std::make_pair(sbasic{10, 20, 30, 1, 100, 200, 300}, spayloadamount{{1, 2}, {10, 20}})); m[spayload{1}].insert(std::make_pair(sbasic{15, 25, 35, 2, 150, 250, 350}, spayloadamount{{3, 4}, {30, 40}})); m[spayload{2}].insert(std::make_pair(sbasic{20, 30, 40, 3, 200, 300, 400}, std::nullopt)); m[spayload{2}].insert(std::make_pair(sbasic{25, 35, 45, 4, 250, 350, 450}, std::nullopt)); for (const auto &[payload, basicMap] : m) { std::cout << "Payload Type: " << payload.type << std::endl; for (const auto &[basic, payloadAmountOpt] : basicMap) { std::cout << " Basic: Length=" << basic.length << ", Width=" << basic.width << ", Height=" << basic.height << ", Type=" << basic.type << ", Position=(" << basic.x << ", " << basic.y << ", " << basic.z << ")" << std::endl; if (payloadAmountOpt) { const auto &payloadAmount = *payloadAmountOpt; std::cout << " Payload Amounts:" << std::endl; for (size_t i = 0; i < 64; ++i) { if (payloadAmount.type[i] != 0) { // Assuming type 0 means no payload std::cout << " Type: " << payloadAmount.type[i] << ", Amount: " << payloadAmount.amount[i] << std::endl; } } } else { std::cout << " No payload amount available." << std::endl; } } } return 0; }Also eine Map, die wieder eine Map hält - anstatt das Variant-Gedengele...