Designkonzept für Container



  • Hallo Leute,
    ich stehe hier vor einem Problem:
    Ich möchte Objekte in einen Container einlesen. Die Objekte haben 3 Eigenschaften (alles zahlen), mit denen Sie in der container indiziert werden müssen.
    Im Moment mache ich es so, dass ich aus den 3 Eigenschaften einen einmaligen Hashwert berechne und dann in einer std::map<int, object> speichere.
    Gibt es eine elegantere lösung? Also am besten wäre so eine Lösung:

    CONTAINERTYPE < int, int, int, T > container;
    
    container.insert(4, 6, 2, mein_object);
    
    std::cout<< container(4,6,2); //gibt mein object aus
    

    Wie würdet ihr so ein Problem angehen? Gleich eine eigene Containerklasse zu schreiben möchte ich gerne vermeiden


  • Mod

    Theoretisch könnte man natürlich eine dreifach verschachtelte Map nehmen, aber in der Praxis dürfte die Lösung mit dem Hashwert weit überlegen sein. Ich würde mir einen Wrapper für die Map schreiben, welche automatisch die Hash-Operationen durchführt, so dass man die Map dann so benutzen kann, wie man es kennt.



  • Fasse die int-Tripel in eine Klasse zusammen und definiere operator<, damit kannst du sie als Key in der map verwenden.



  • So?

    #include <map>
    #include <string>
    #include <iostream>
    
    struct Key
    {
      int a;
      int b;
      int c;
    
      Key( int a, int b, int c ) : a(a), b(b), c(c) {}
    
      bool operator< ( const Key& rhs ) const 
      {
        return a < rhs.a 
          ||
          ( a == rhs.a && b < rhs.b )
          ||
          ( a == rhs.a && b == rhs.b && c < rhs.c );
      }
    };
    
    int main()
    {
      std::map<Key, std::string> m;
    
      m[ Key( 1, 2, 3 ) ] = "Hallo";
      m[ Key( 4, 5, 6 ) ] = "Welt";
    
      std::cerr << m[ Key( 1, 2, 3 ) ] << " " << m[ Key( 4, 5, 6 ) ] << std::endl;
    }
    

    Lars



  • WOW! Das nenne ich mal schnelle Antworten!
    Bisher gefällt mir der Ansatz von SeppJ ganz gut, ungefähr so:

    typedef std::map<int, object> my_map;
    
    void add_obj(int a, int b, int c, object o, my_map& m)
    {
       m.insert<std::make_pair(a*100+b*10+c, o);
    }
    
    object get_obj(int a, int b, int c, const my_map& m)
    {
       return m[a*100+b*10+c];
    }
    


  • typedef std::map<int, object> my_map;
    
    void add_obj(int a, int b, int c, object o, my_map& m)
    {
       m.insert<std::make_pair(a*100+b*10+c, o);
    }
    
    object get_obj(int a, int b, int c, const my_map& m)
    {
       return m[a*100+b*10+c];
    }
    

    Ich hoffe deine Zahlen sind nur einstellig, sonst ist (1,1,1) und (1,0,11) Identisch ... dann könntest du ganz auf das Wrappen der Map verzichten und einfach einen int als key verwenden.
    Abgesehen davon verstehe ich das make_pair nicht ... du brauchst einen int und ein Objekt ... also eher m.insert(a*100+b*10+c, o) ...



  • Mit manni66s Lösung benötigst du keine Wrapperklassen und hast keinerlei Bereichsrestriktionen für deine Schlüsselteile.



  • padreigh schrieb:

    Abgesehen davon verstehe ich das make_pair nicht ... du brauchst einen int und ein Objekt ... also eher m.insert(a*100+b*10+c, o) ...

    Das make_pair benötigst du an der map.insert-Funktion, da diese zum einfügen ein "pair" möchte. Aber wie oben war es falsch sollte eigentlich so geschrieben werden:

    m.insert( make_pair( a*100+b*10+c, 0 ) )
    

    Mfg marco


Anmelden zum Antworten