std::map::iterator in std::set speichern



  • Hi,

    ist so ein Konstrukt erlaubt?

    typedef std::map<char, double>Parameter;
    Parameter parameters;
    
    std::set<Parameter::iterator>params;
    

    Hierbei sollen Iteratoren der map parameters in dem set gespeichert werden.

    Denn beim Komplieren bekomme ich den Fehler

    Fehler	C2678	Binärer Operator "<": Es konnte kein Operator gefunden werden, der einen linksseitigen Operanden vom Typ "const std::_Tree_iterator<std::_Tree_val<std::_Tree_simple_types<std::pair<const _Kty,_Ty>>>>" akzeptiert (oder keine geeignete Konvertierung möglich)
    

    trotz des das ein solcher Operator definiert ist

    bool operator <(const Parameter::iterator &rhs, const  Parameter::iterator &lhs) {
    	if (rhs->first < lhs->first)
    		return true;
    	else
    		return false;
    }
    

    Wo liegt jetzt mein Fehler?



  • Iteratoren zu speichern ist ungünstig, da iteratoren auch invalid werden können, wenn sich etwas am entsprechenden container was ändert


  • Mod

    axels. schrieb:

    ist so ein Konstrukt erlaubt?

    typedef std::map<char, double>Parameter;
    Parameter parameters;
    
    std::set<Parameter::iterator>params;
    

    ...
    Denn beim Komplieren bekomme ich den Fehler

    Fehler	C2678	Binärer Operator "<": Es konnte kein Operator gefunden werden,...
    

    trotz des das ein solcher Operator definiert ist

    bool operator <(const Parameter::iterator &rhs, const  Parameter::iterator &lhs) {
    	if (rhs->first < lhs->first)
    		return true;
    	else
    		return false;
    }
    

    Der Komparator, den std::set benutzt, ist nicht der < Operator selbst, sondern std::lessParameter::iterator.
    Wie sieht std::less aus? Im Prinzip so:

    namespace std {
        template <class T = void> struct less {
            constexpr bool operator()(const T& x, const T& y) const {
                return x < y;
            }
        };
    }
    

    Wo liegt das Problem?
    less liegt im Namensraum std. D.h. bei der unqualifizierten Suche nach einer passenden Überladung des < Operators, wird auch in diesem Namensraum angefangen. Und da die Standardbibliothek den < Operator für diverse Typen überlädt, werden auch einige Kandidaten gefunden. Diese Kandidaten verhindern, dass die unqualifizierte Suche im globalen Namensraum, in dem sich dein Operator vermutlich befindet, forgesetzt wird: die Deklarationen im Namensraum std verdecken die im globalen Namensraum.
    ADL kann den globalen Namensraum ebenfalls nicht durchsuchen, denn std::map<char, double>::iterator ist offensichtlich nur mit der Klasse std::map<char, double> und dem Namensraum std assoziert.

    Welche mögliche Abhilfe besteht?
    1. Verschieben des < Operators in den Namensraum std. = nach Standard verboten
    2. Spezialisieren von std::less für std::map<char, double>::iterator = ebenfalls nach Standard verboten, da kein UDT involviert ist
    3. Benutzung eines eigen Komparators und Verwendung mit std::set:

    struct my_less {
        template <typename T>
        constexpr bool operator()(const T& x, const T& y) const {
            return x < y;
        }
    };
    

    (im selben Namensraum, in dem sich auch deine < Operatorfunktion befindet).

    std::set<Parameter::iterator, my_less> params;
    


  • Danke für die ausführliche Antwort! Hat mir sehr geholfen! 🙂


Log in to reply