Vergleichsprädikat im Konstruktor konkretisieren



  • Hallo Forum,

    Mein Anliegen ist es eine std::set zu sortieren, indem ich im Konstruktor sozusagen "Sortieroptionen" übergebe. Hier ein kleines Testprogramm, um mein Problem besser beschreiben zu können:

    #include <set>
    #include <iostream>
    using namespace std;
    
    // Operator << für std::set<T> überladen
    template <class T>
    ostream& operator << (ostream& os, const set<T>& data) {
        for (set<T>::const_iterator i = data.begin(); i != data.end(); i++)
            os << *i << ' ';
        return os << endl;
    }
    
    // Funktor (abgeleitet von less<T>), der zusätzliche Optionen per Konstruktor zulässt
    template <class T>
    struct opt_less : public less<T> {
        const bool rev;
        opt_less(bool reverse = false) : rev(reverse) {}
    
        bool operator() (const T& lhs, const T& rhs) const {
            if (!rev) return less<T>::operator() (lhs, rhs);
            else      return less<T>::operator() (rhs, lhs);
        }
    };
    
    int main() {
        // int-set mit Zahlen zwischen 1 und 9 füllen
        int ia[] = {4, 2, 7, 8, 1, 5, 9, 6, 3};
        set<int> is(ia, ia + sizeof(ia)/sizeof(ia[0]),
            // Funktionsobjekt mit Option (Ableitung von less)
            opt_less<int>(true));
    
        cout << is;
        system("pause");
    }
    

    Eigentlich sollte hier

    9 8 7 6 5 4 3 2 1
    

    ausgegeben werden. Allerdings wird immer nur less<T> anstatt opt_less<T> verwendet, und die Ausgabe ist immer

    1 2 3 4 5 6 7 8 9
    

    Weiß jemand, wie ich das bewerkstelligen kann?

    P.S. Ich weiß, dass ich einfach set<int, greater<int> > schreiben könnte, aber bool rev ist bei mir nur eine Beispieloption.



  • Vererbung ist hier eine schlechte Idee. Da als zweites Templateargument des std::set nichts spezifiziert wurde, wird per Default std::less<int> genommen. Da du dein eigenes Prädikat von std::less<int> erbst, wird eine implizite Konvertierung zur Basisklasse vorgenommen, was nicht mal einen Fehler erzeugt.

    Lösung: Gleich

    [c]std::set<int, opt_less_aber_mit_besserem_namen<int> > set;
    

    verwenden und im Konstruktor das richtige Argument übergeben.


Anmelden zum Antworten