C++ wie befülle ich diese std::map korrekt?

thuering

Lt. Commander
Registriert
Nov. 2020
Beiträge
1.087
Guten Abend,

ich habe eine
C++:
std::map<int, int, Tile> oTilemap;
"Tile" ist eine Klasse und hat folgenden Konstruktor
C++:
Tile(std::string pSrcTileSet, int pSrcTile, int pPosX, int pPosY);
Wie kann ich die Map nun korrekt befüllen? Ich kompiliere mit VS'22 in C++20. Da hab ich gelesen, dass ich kein "pair" brauche. Es geht trotzdem nicht...

C++:
    for (int x = 0; x < 16; x++)
    {
        for (int y = 0; y < 16; y++)
        {
            oTilemap.insert(x, y, Tile("tiles.png", 10, x, y));
        }
    }

E0304 no instance of overloaded function "std::map<_Kty, _Ty, _Pr, _Alloc>::insert [with _Kty=int, _Ty=int, _Pr=Tile, _Alloc=std::allocator<std::pair<const int, int>>]" matches the argument list

Wie gehts richtig? Ich will nur eine Map, die mit Objekten vom Typ Tile gefüllt ist und die ich mit int x & y iterieren / gezielt abrufen kann.
 
Du nutzt die Templatisierung von map falsch.
Die Template Typparameter sind Key, Value, Compare, Allocate. Du kannst nur einen Key Typen angeben, nicht zwei.

Deine Map ist also gerade definiert als Key=int, Value=int, Compare=Tile. Wie auch immer du letzteres überhaupt geschafft hast.

Wenn du die Map immer über x und y Indizes zugreifen willst, dann mach zB eine std::map<int, Tile> draus und nutze als Indizes immer [x * maxY + y].
(Stichwörter 2D/1D mapping, array flatten, index flatten...)

Alternativ ginge auch eine std::map<std:: pair<int, int>, Tile>, dann erfolgt der Zugriff über ein X,Y pair/tupel.

Ed: haste selbst sogar besser erkannt, dass es da gar keine Map braucht. Feste XY Indizes kann man ganz einfach mit einem Array abbilden. Entweder 2D array oder mit obiger Variante als 1D array.

Map macht erst Sinn, wenn die Indizes nicht mehr rein sequenziell und strikt begrenzt sind.

Ergänzung ()

Fun fact: statt insert() kannst du mal emplace() probieren, das spart im Idealfall einen Konstruktor Aufruf pro eingesetztem Element: https://en.cppreference.com/w/cpp/container/map/emplace

Denn dein Insert erzeugt aktuell ein Tile Objekt (Konstruktor direkt im Code) und erzeugt dann nochmal eins für die tatsächliche Insert Operation (Copy Konstruktor). Der Compiler optimiert das vielleicht sogar raus, aber schöner isses ohne dem Umweg (auch so aus Prinzip, da komplexe Klassen mitunter spezielle Logik in diesen Konstruktoren implementieren, die dann zu ungewolltem Verhalten führt).
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: kuddlmuddl und thuering
Ich habe nochmal überlegt und geschaut, was es gibt. Die Lösung war einfach. Ich mache das so...
C++:
Tile oTilemap[128][128];

Ein gutes altes Array...
Ergänzung ()

Dennoch vielen Dank für deinen Input. Ganz offensichtlich habe ich std::map bisher völlig falsch verstanden!
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: kuddlmuddl, BeBur und Powl_0
@kuddlmuddl So weit ich verstanden habe, kann ich das aber auch nicht getrennt mit zwei ints X / Y ansteuern und daran ein Objekt packen? Ich muss wie bei der std::map eine Umrechnung X * maxY + Y her nehmen. Klar funktioniert das und std::map und std::array sind selber sauber und elegant - aber für meine Anwendung halt irgendwie nicht intuitiv.
 
Falls es um Intuition einer API geht, kannst du das ganze ja nochmal wrappen und das Interface nach außen so gestalten, dass man mit x und y als separaten Parametern drauf zugreift. Was intern passiert, interessiert den "Nutzer"/Entwickler dann nicht, und da kann es dann auch 2D/1D Mapping oder andere esoterische Dinge tun.
 
  • Gefällt mir
Reaktionen: thuering
Zurück
Oben