Zuweisung an den Index-Operator?



  • Hallo,
    ich habe hier eine Klasse die den Zugriff auf eine mehrdimensionale
    Map hinter einem Index-Operator verbirgt. Ungefähr so:

    class A {
      privat:
        static map< string, map<string,string> > data;
        string section;
      public:
        A( string str ); // str wird nach pruefung section zugewiesen
        ~A() {};
        string operator[](string name) {return data[section][name];};
    }
    

    Jetzt will ich eine Methode schreiben die bei der Zuweisung an den
    Index-Operator angesprochen wird. Etwa so:

    A default("mySettings");
    default["logfile"]="/var/log/myprog.log";
    

    Ich will hier nicht direkt an date[][] zuweisen, sonst könnte ich ja eine Referenz zurückgeben, sondern nur wenn data["mySettings"]["logfile"].empty().
    Was mir fehlt ist die richtige deklaration des operator[]= oder wie
    auch immer der dann aussehen muss.

    Danke!

    Peanut

    [ Dieser Beitrag wurde am 10.04.2003 um 21:32 Uhr von Peanut editiert. ]



  • Original erstellt von Peanut:
    **Ich will hier nicht direkt an date[][] zuweisen, sonst könnte ich ja eine Referenz zurückgeben, sondern nur wenn data["mySettings"]["logfile"].empty().
    Was mir fehlt ist die richtige deklaration des operator[]= oder wie
    auch immer der dann aussehen muss.
    **

    kapiere ich nicht



  • dann liefer eine referenz auf den string zurück...

    string& operator[](string &name) {return data[section][name];}
    

    auch name solltest du per referenz übergeben da sonst eine überflüssige kopie erstellt wird...



  • Original erstellt von japro:
    auch name solltest du per referenz übergeben da sonst eine überflüssige kopie erstellt wird...

    aber als const referenz!



  • Das mit der const-Referenz ist klar, ist nur bei der Vereinfachung für das Beispiel draufgegangen!

    Was ich suche:

    string& A::operator[]= (string const& index, string const& zuweisung) { 
      // diesen operator gibt es eben nicht!
      if ( name[section][index].empty() ){
        name[section][index]=zuweisung;
        return zuweisung;
      }
      else {
        return name[section][index];
      }
    }
    

    Bei der Frage wurde ich vom Mod des de.comp.lang.iso-c++ auf http://www.voyager.prima.de/cpp/proxy.html aufmerksam gemacht. Obwohl ich das Beispiel inzwischen am laufen habe ( vector::... muss durch vector<T, Assoc> ersetzt werden ) kann ich das gezeigte nicht auf mein Problem anwenden 😞

    Weitere Anfragen wurden mit in d.c.l.iso-c++ wurden mit
    "Halte Dich nicht mit Syntaxspielereien auf. Wenn es
    einfacher ist, zwei Methoden »read« und »write« zu schreiben, dann
    tue das, statt ewig nach einem Gimmick zu suchen, der »=« verwendet."
    abgetan.

    Aber ich bin der Meinung ich mache mir lieber einmal die Gedanken und ärgere mich nicht später immer wenn ich die Klasse benutze weil sie unhandlich ist. Ausserdem ist da ja auch die Sache mit dem Lerneffekt!

    Danke

    Mario

    [ Dieser Beitrag wurde am 10.04.2003 um 21:30 Uhr von Peanut editiert. ]



  • Hallo,
    also ich habe dein Vorhaben auch nicht verstanden. Kannst du das vielleicht mal an ein paar Beispielen erklären?



  • Ich nehm mal an, du willst folgendes:

    A a;
    a["Blub"] = "Bla";
    

    a["Blub"] = "Bla";
    hier werden aber zwei operatoren aufgerufen:
    a.operator [] ("Blub").operator = ("Bla");
    das heißt du musst für a den operator [] überladen und für den Rückgabewert von A::operator [] den operator = überladen.

    [ Dieser Beitrag wurde am 10.04.2003 um 18:40 Uhr von Noesis editiert. ]



  • @HumeSikkins: Nimm die Klassen definition aus den ersten posting mit der Elementfunktion aus dem zweiten und du hast ein Beispiel!

    @Noesis: Ahh, wenigstens einer versteht mich!

    OK, Rückgabewert von A::operator [] gibt einen String zurück. String liegt nicht in meiner Gewalt also neue Klasse definieren:

    class dummyString : public std::string{
      string operator=(const string& str) {cout << "put code here" << endl;
          string::operator=(str);
      }
    }
    

    und dann den return-Wert von A::operator[] auf dummyString gesetzt. Dann fingen die Probleme aber erst an, der Compiler meinte einen dummyString niht in einen String umwandeln zu können aber dummyStrings sind ja eigentlich Strings. Ich als Beginner habe dann gedacht, ich sei völlig auf dem Holzweg und habe um Hilfe geschrieen. Aber wenn der Ansatz stimmt werde ich mich nochmal in die Richtung orientieren und komme dann mit entsprechenden Problemen bei der Umsetzung nochmal auf euch zurück.

    Bis hierher schon mal Danke!

    Peanut



  • probiers mal mit
    operator string & ()
    oder
    operator const string & () const



  • Ok, einen kleinen Teil habe ich glaube ich! Nur das eigentliche zuweisen will nicht!😕

    class dummyString : public std::string {
      public:
        string& operator=(string const& str) {
          cout << "put your code here!" << endl;
          return std::string::operator=(str);
        }
        dummyString ( string const& str ) : std::string::basic_string(str){}
    
    };
    
    class A {
      privat:
        static map< string, map<string,string> > data;
        string section;
      public:
        A( string str ); // str wird nach pruefung section zugewiesen
        ~A() {};
        dummyString operator[](string name) {return data[section][name];};
    }
    
    int main(void) {
      A a("name"); 
      cout << "notconft:" << a["notconft"] >> endl;
      a["notconft"]="Hello World!";
      cout << "notconft:" << a["notconft"] >> endl;
    }
    

    Dabei kommt aber:

    notconft:
    put your code here!
    notconft:

    und nicht

    notconft:
    put your code here!
    notconft: Hello World!

    raus 😡

    Hinweise? Meine vermutung ist das

    A::operator[]
    

    eine Referenz zurückgeben muss damit

    dummyString::operator=
    

    dieser dann einen Wert zuweisen kann. Aber wenn ich den return-Wert von

    A::operator[]
    

    auf dummyString& ändere bekomme ich

    initializing non-const `dummyString &' with `basic_string<char,string_char_traits<char>,__default_alloc_template<false,0> >' will use a temporary

    PS: Bitte noch keine Call-by...Hinweise, ich arbeite dran! 😉



  • du erzeugst ja ein temporäres dummyString objekt aus einem std::string. und dann willst du eine referenz darauf zurückgeben, das geht nicht.
    Wenn du das Schlüsselwort "explicit" vor dummyStrings Konstruktor dazutust, wirst du den Fehler vielleicht erst erkennen.
    du änderst mal deine map in

    map< string, map<string,dummyString> > data;
    

    und den operator [] lässt du jetzt eine Referenz zurückgeben

    Allerdings frage ich mich, wieso du nicht einfach eine Referenz auf einen std::string zurückgibst. Irgendwelche speziellen Prüfungen im dummyString::operator= notwendig?

    edit: Smileys weg

    [ Dieser Beitrag wurde am 11.04.2003 um 13:56 Uhr von davie editiert. ]



  • So, jetzt tut es! Hässlich ist nur, dass der dummyString eine globale-Klasse geworden ist. Kann man den in die A-Klasse (nicht die von Mercedes!) integrieren?

    Naja, so läuft es ja erstmal!

    Nochmal besten Dank an davie der doch auch Noesis war 😕 !

    #include <iostream>
    #include <string>
    #include <map>
    
    class dummyString : public std::string {
      public:
        string& operator=(string const& str) {
          cout << "put your code here!" << endl;
          return std::string::operator=(str);
        }
        dummyString ( string const& str ) : std::string::basic_string(str){}
        dummyString ( ) : std::string::basic_string(){}
    
    };
    
    class A {
      private:
        static map< string, map<string,dummyString> > data;
        string section;
      public:
        A( string str ) : section(str){};
        ~A() {};
        dummyString& operator[](string name) {return data[section][name];};
    };
    
    map< string, map<string,dummyString> > A::data;
    int main(void) {
      A a("name");
      cout << "notconft:" << a["notconft"] << endl;
      a["notconft"]="Hello World!";
      cout << "notconft:" << a["notconft"] << endl;
    }
    


  • Letzte Fassung!
    Jetzt ist es so wie ich mir das vorgestellt habe!

    #include <iostream>
    #include <string>
    #include <map>
    
    class A {
      public:
        class dummyString : public std::string {
          public:
            string& operator=(string const& str) {
              cout << "put your code here!" << endl;
              return std::string::operator=(str);
            }
            dummyString ( string const& str ) : std::string::basic_string(str){}
            dummyString ( ) : std::string::basic_string(){}
    
        };
    
      private:
        static map< string, map<string,A::dummyString> > data;
        string section;
      public:
        A( string str ) : section(str){};
        ~A() {};
        A::dummyString& operator[](string name) {return data[section][name];};
    };
    
    map< string, map<string,A::dummyString> > A::data;
    int main(void) {
      A a("name");
      cout << "notconft:" << a["notconft"] << endl;
      a["notconft"]="Hello World!";
      cout << "notconft:" << a["notconft"] << endl;
    }
    

Anmelden zum Antworten