2016-01-05 5 views
13

Im latest paper on concepts N3701 gibt es das folgende Beispiel mit dem sort Algorithmus:Warum Sortierkonzept erfordert total geordneten Werttyp, während Std :: Sort nur "weniger als" vergleichbar erfordert?

template<typename Cont> 
    requires Sortable<Cont>() 
void sort(Cont& cont) 

wo Sortable Konzept als

definiert ist
template<typename T> 
concept bool Sortable() 
{ 
    return Permutable_container<T>() && Totally_ordered<Value_type<T>>(); 
} 

wo Totally_ordered, nicht überraschend, als

template<typename T> 
constexpr bool Totally_ordered() 
{ 
    return Weakly_ordered<T>() && Equality_comparable<T>(); 
} 
definiert ist

und wiederum Equality_comparable ist definiert als

template<typename T> 
constexpr bool Equality_comparable() 
{ 
    return requires(T a, T b) { 
    {a == b} -> bool; 
    {a != b} -> bool; 
    }; 
} 

Ich fand nicht die Definition von Weakly_ordered, aber ich glaube, es sollte wie folgt aussehen (bin ich richtig?)

template<typename T> 
constexpr bool Weakly_ordered() 
{ 
    return requires(T a, T b) { 
    {a < b} -> bool; 
    {a <= b} -> bool; 
    {a > b} -> bool; 
    {a >= b} -> bool; 
    }; 
} 

Unterm Strich in dieser Definition, wenn ich will zu sortieren std::vector<T>, ich brauche T alle Vergleichsoperatoren <, bieten <=, >, >=, ==, !=. Während der gesamten Lebensdauer von C++, std::sort, wird jedoch nur der erforderliche Operator < benötigt! Hier ist, was cppreference sagt über std::sort:

Sortiert die Elemente im Bereich [first, last) in aufsteigender Reihenfolge. Es ist nicht garantiert, dass die Reihenfolge der gleichen Elemente beibehalten wird. Die erste Version verwendet Operator <, um die Elemente zu vergleichen, die zweite Version verwendet das angegebene Vergleichsfunktionsobjekt comp.

Also, was bedeutet, dass in Zukunft C++ mit Konzepten für v vom Typ std::vector<T> wo T nur operator< bietet, std::sort(v.begin(), v.end()) kompilieren, während std::sort(v) nicht? Das klingt verrückt.

Ich habe dies in der aktuellen ranges-v3 implementation von Eric Niebler überprüft, und es funktioniert genauso wie ich beschrieben habe. Code wird nicht kompiliert, wenn nicht alle Operatoren bereitgestellt werden.

Siehe auch Siehe auch: https://github.com/ericniebler/range-v3/issues/271

Antwort

11

Die Konzepte TS nicht die Standard-Bibliothek ist konzeptionieren. Es war nur ein Beispiel; nichts mehr.

Die TS-Version von sort erfordert Sortable, die ihre Vergleichsklasse standardmäßig auf std::less<> setzt. Es scheint jedoch, dass std::less<>::operator() die Anforderung TotallyOrdered auf die Arten seiner Parameter auferlegt. Von daher kommt es. Es gibt eine entsprechende Anmerkung in P0021R0 (PDF):

[Anmerkung der Redaktion: Entfernen Tabelle [lessthancomparable] in [utility.arg.requirements].Ersetzen Sie die Verwendung von LessThanComparable durch TotallyOrdered () und bestätigen Sie, dass dies eine brechende Änderung ist, die die Typanforderungen strenger macht (). Ersetzen Sie Verweise auf [weniger als vergleichbar] mit Verweisen auf [concepts.lib.compare.tallyallyordered]]

Hervorhebung hinzugefügt. Die allgemeinen Probleme rund um diese appear to be on-hold, anhängig andere Sprachfunktionen (wie implizite Erstellung aller anderen nur auf operator< oder Somesuch basierenden Operatoren).

Sie könnten einfach eine (gesunde) Version einer Vergleichsfunktion verwenden. Oder Sie könnten einfach die std::sort Iterator-Version verwenden, die keine Konzepte jeglicher Art verwendet.


Es ist auch darauf hingewiesen, dass mit the introduction von the "spaceship operator" in C++ 20 werden soll (die frühest wir die Bereiche TS in den Standard integriert sehen können), ist diese ganze Diskussion effektiv strittig wird. Eine einfache auto operator<=>(const MyType &) = default; Deklaration in der Klasse, und plötzlich ist Ihr Typ total geordnet.

+0

Ich habe dies in der aktuellen Reichweiten-v3-Implementierung von Eric Niebler (https://github.com/ericnebler/range-v3) überprüft, und es funktioniert genau wie ich beschrieben habe. Code wird nicht kompiliert, wenn nicht alle Operatoren bereitgestellt werden. Diese Implementierung erfordert jedoch "IndirectCallableRelation". – Mikhail

+0

@Mikhail: Ich lese weiter in der Spezifikation. –

+0

Danke. Siehe auch https://github.com/ericnebler/range-v3/issues/271 – Mikhail

Verwandte Themen