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
=requiresund Pfeil für den Rückgabewert? DasconceptSchlü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
=requiresund Pfeil für den Rückgabewert? DasconceptSchlü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<bgueltig 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<bgueltig 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-funktionbool T::operator<(T b)funktionieren? Das ist dann natürlich ein Vorteil der Schreibweise
-
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<bgueltig 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
Xhabe, wox1 < x2eben nicht compiliert, und ich den trotzdem in einemLessThanComparable-fordernden Template verwenden will.
Kann ich dann eine "Spezialisierung" vonLessThanComparablefürXschreiben, oder muss ich wirklich "global" dafür sorgen dassx1 < x2eben doch funktioniert?
-
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
Xhabe, wox1 < x2eben nicht compiliert, und ich den trotzdem in einemLessThanComparable-fordernden Template verwenden will.
Kann ich dann eine "Spezialisierung" vonLessThanComparablefürXschreiben, oder muss ich wirklich "global" dafür sorgen dassx1 < x2eben 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.