C++17 hat Concepts



  • Arcoth schrieb:

    template<typename T>
    concept bool LessThanComparable = requires (T a, T b) {{a < b} -> bool;}
    

    Mal ne dumme Frage, die Syntax war doch mal etwa so (wenn ich mich richtig erinnere)

    template <typename T>
    concept bool LessThanComparable
    {
        bool operator<(T a, T b); // T braucht einen operator< der 2 T's nimmt und bool zurückgibt
    }
    

    Wieso ist das jetzt so "häßlich" mit =requires und Pfeil für den Rückgabewert? Das concept Schlüsselwort sollte doch ausreichen um dem Compiler zu sagen dass jetzt die requirements für T kommen, gibts einen bestimmten Grund warum man genau die Syntax gewählt hat?



  • happystudent schrieb:

    Wieso ist das jetzt so "häßlich" mit =requires und Pfeil für den Rückgabewert? Das concept Schlüsselwort sollte doch ausreichen um dem Compiler zu sagen dass jetzt die requirements für T kommen, gibts einen bestimmten Grund warum man genau die Syntax gewählt hat?

    Die neue Version ist allgemeiner. Das alte sagt lediglich, dass der operator < (a, b) vorhanden ist und bool zurueckgibt. Das neue hingegen sagt, dass diue expression a<b gueltig ist und das Ergebnis in boolean umgewandelt werden kann, quasi dass

    bool c = a<b
    

    gueltig ist.
    Mehrere requires koennen wahrscheinlich auch mit logischen operatoren verbunden werden.

    Ausserdem sieht es vermutlich besser aus, wenn man nicht alles in einer Zeile schreibt:

    template<typename T>
    concept bool LessThanComparable =
    requires (T a, T b) {
        {a < b} -> bool;
    }
    


  • Marthog schrieb:

    Die neue Version ist allgemeiner. Das alte sagt lediglich, dass der operator < (a, b) vorhanden ist und bool zurueckgibt. Das neue hingegen sagt, dass diue expression a<b gueltig ist und das Ergebnis in boolean umgewandelt werden kann, quasi dass

    bool c = a<b
    

    gueltig ist.

    Ok, also würde das concept sowohl für eine freie operator-Funktion bool operator<(T a, T b) als auch für eine Member-operator-funktion bool T::operator<(T b) funktionieren? Das ist dann natürlich ein Vorteil der Schreibweise 👍


  • Mod

    Marthog schrieb:

    Das neue hingegen sagt, dass diue expression a<b gueltig ist und das Ergebnis in boolean umgewandelt werden kann, quasi dass

    bool c = a<b
    

    gueltig ist.

    Nicht Quasi, sondern genau das.

    Mehrere requires koennen wahrscheinlich auch mit logischen operatoren verbunden werden.

    Ja, siehe §14.10.1.1.

    Ausserdem sieht es vermutlich besser aus, wenn man nicht alles in einer Zeile schreibt:

    Seh' ich nicht so.



  • Ist im aktuellen Concepts Stand auch etwas vorgesehen mit dem man Concepts für bestimmte Typen "zurechtbiegen" kann?

    Also wenn ich einen Typ X habe, wo x1 < x2 eben nicht compiliert, und ich den trotzdem in einem LessThanComparable -fordernden Template verwenden will.
    Kann ich dann eine "Spezialisierung" von LessThanComparable für X schreiben, oder muss ich wirklich "global" dafür sorgen dass x1 < x2 eben doch funktioniert?


  • Mod

    hustbaer schrieb:

    Ist im aktuellen Concepts Stand auch etwas vorgesehen mit dem man Concepts für bestimmte Typen "zurechtbiegen" kann?

    Also wenn ich einen Typ X habe, wo x1 < x2 eben nicht compiliert, und ich den trotzdem in einem LessThanComparable -fordernden Template verwenden will.
    Kann ich dann eine "Spezialisierung" von LessThanComparable für X schreiben, oder muss ich wirklich "global" dafür sorgen dass x1 < x2 eben doch funktioniert?

    Macht IMO keinen Sinn. Sahen die Verfasser des Proposals ähnlich:

    §7.1.7/7 schrieb:

    A program shall not declare an explicit instantiation (14.8.2), an explicit specialization (14.8.3), or a partial specialization of a concept definition. [ Note: This prevents users from subverting the constraint system by providing a meaning for a concept that differs from its original definition.end note ]



  • Also ich meine das was in der alten Concepts Version (die ursprünglich für IIRC C++11 vorgesehen war) mit Concept-Maps möglich war:

    concept Stack<typename X> {
        typename value_type;
        void push(X&, const value_type&);
        void pop(X&);
        value_type top(const X&);
        bool empty(const X&);
    };
    
    template<typename T> concept_map Stack<std::vector<T>> {
        typedef T value_type;
        void push(std::vector<T>& v, const T& x) { v.push_back(x); }
        void pop(std::vector<T>& v) { v.pop_back(); }
        T top(const std::vector<T>& v) { return v.back(); }
        bool empty(const std::vector<T>& v) { return v.empty(); }
    };
    

    Hier entfernt bzw. verändert die Concept-Map ja nicht die Constraints, sie definiert lediglich wie bestimmte geforderte Operationen bei einem bestimmten Typ funktionieren.

    Und das macht mMn. schon Sinn.


Anmelden zum Antworten