Klasse mit Konstante in map einfügen



  • Hallo!
    Ich habe eine Klasse mit einer Konstante die ich in eine Map einfügen will.

    #include <map>
    
    class A {
    public:
        A() : i(5) {}
    private:
        const int i;
    };
    
    int main() {
        std::map<int, A> m;
        m[10] = A();
    }
    

    Die Fehlermeldung lautet:
    Die Funktion 'operator =' ist in 'A' nicht verfügbar

    Warum ist das so und kann man den Fehler beheben, damit es korrekt funktioniert?



  • Hallo,
    sobald eine Klasse konstante oder Referenz-Member hat, wird der copy-assignmet-Operator nicht mehr automatisch erzeugt.
    In diesem Fall kannst du darauf aber verzichten, wenn du die "richtige" Version zum Einfügen in eine Map verwendest:

    int main() {
        std::map<int, A> m;
        m.insert(std::map<int, A>::value_type(10, A()));
    }
    

    Ansonsten musst du halt den op= implementieren. Eine mögliche Implementation könnte so aussehen:

    class A
    {
    public:
    A& operator=(const A& rhs)
    {
        return *this;
    }
    ...
    };
    

    [ Dieser Beitrag wurde am 25.03.2003 um 15:39 Uhr von HumeSikkins editiert. ]



  • m.insert(std::map<int, A>::value_type(10, A()));

    Ich hab das bisher mit m.insert(std::make_pair(10,A())); gelöst.

    Kannst Du bitte kurz das mit value_type erläutern ?

    thx



  • Ich hab das bisher mit m.insert(std::make_pair(10,A())); gelöst.

    Ist auch ne schöne Möglichkeit. Hat aber seine Nachteile. Komme ich gleich drauf.
    make_pair sieht so aus:

    template<class T, class U>
        pair<T, U> make_pair(const T& x, const U& y);
    

    value_type für eine Map mit Schlüssel T und Value U so:

    template <class T, class U/*...*/>
    class map
    {
    //...
    public:
    typedef pair<const T, U> value_type;
    //...
    };
    

    value_type ist also ein typedef auf das für eine map passendes pair.

    make_pair ist nichts weiter als eine Bequemlichkeits-Funktion. Sie liefert ein passendes std::pair für eine map ohne das man die Typen für Schlüssel und Wert explizit angeben muss.

    Der Nachteil von make_pair liegt in der Form der Parameterübergabe. Die Referenzübergabe von x verhindert die bequeme Nutzung von make_pair in Verbindung mit Zeichenketten-Literalen.
    Die Konvertierung eines Zeichenketten-Literals in einen Zeiger-auf-(const)-char findet bei Templateargumenten nur bei nicht-Referenzparametern statt.

    Hat man nun eine map<string, int> oder map<const char*, int> und ein Aufruf der Form:

    map<const char*, int> m;
    m.insert(make_pair("Hallo", 22));    // error
    map<string, int> m2;                 
    m2.insert(make_pair("Hallo", 22));   // error
    

    erhält man beim insert jeweils ein Error.
    Dies liegt daran, dass "Hallo" nicht nach const char* konvertiert. Vielmehr wird T nach const char[6] hergeleitet.
    Damit haben wir ein pair<const char[6], int>.
    Das führt aber zu einem Fehler, da im Ctor von pair nun versucht wird dem Array eine Zeichenkette zuzuweisen.

    Das ist der eine Grund, warum ich make_pair selten verwende.
    Der zweite Grund ist, dass durch die Verwenund von make_pair häufig unnötige Konvertierungen auftreten.
    Beispiel:

    map<double, int> m;
    m.insert(make_pair(22, 10));
    

    make_pair(22, 10) erzeugt erstmal ein pair<int, int>. Da dieses Objekt aber nicht vom Typ map<double, int>::value_type ist, kann es nicht direkt in die map eingefügt werden.

    Allerdings besitzt pair einen Template-Copy-Ctor. Dieser wird hier augerufen um aus dem vorhandenen pair<int, int> ein für die map passendes pair<double, int> zu machen.

    Es wird hier also ein überflüssiges pair-Objekt erzeugt.

    Beim Aufruf von :

    map<double, int> m;
    m.insert(map<double, int>::value_type(22, 10));
    

    geschieht das nicht. Hier wird ein pair<double, int> direkt mit den beiden int-Werten initialisiert.

    Naja, wie auch immer. Prinzipiell ist make_pair eine gute Sache. Ich bevorzuge nur einfach value_type 🙂

    [ Dieser Beitrag wurde am 25.03.2003 um 19:24 Uhr von HumeSikkins editiert. ]



  • Vielen Dank für die erklärung, wie immer gut 🤡

    thx


Anmelden zum Antworten