W latest paper on concepts N3701, jest następujący przykład z algorytmu sort
:Dlaczego koncepcja Sortable wymaga całkowicie uporządkowanego typu wartości, podczas gdy std :: sort wymaga tylko "mniej niż" porównywalnego?
template<typename Cont>
requires Sortable<Cont>()
void sort(Cont& cont)
gdzie Sortable
koncepcja jest zdefiniowana jako
template<typename T>
concept bool Sortable()
{
return Permutable_container<T>() && Totally_ordered<Value_type<T>>();
}
gdzie Totally_ordered
, nie jest zaskoczeniem, jest zdefiniowany jako
template<typename T>
constexpr bool Totally_ordered()
{
return Weakly_ordered<T>() && Equality_comparable<T>();
}
, a z kolei Equality_comparable
jest zdefiniowana jako
template<typename T>
constexpr bool Equality_comparable()
{
return requires(T a, T b) {
{a == b} -> bool;
{a != b} -> bool;
};
}
nie znalazłem definicji Weakly_ordered
, ale wierzę, że powinno to wyglądać tak (mam rację?)
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;
};
}
dolnej linii, w tej definicji, jeśli chcę uporządkować std::vector<T>
, muszę T dostarczenie wszystkie porównanie operatorów <
, <=
, >
, >=
, ==
, !=
. Jednak w ciągu całego życia C++, std::sort
wymagany jest tylko operator <
! Oto co mówi o std::sort
cppreference:
Sortuje elementy w przedziale [pierwsza, ostatnia) w porządku rosnącym. Nie można zagwarantować, że kolejność równych elementów zostanie zachowana. Pierwsza wersja wersja używa operatora < do porównania elementów, druga wersja wykorzystuje podaną funkcję porównania comp obiektu.
Więc co, to znaczy, że w przyszłości C++ z koncepcjami, na v
typu std::vector<T>
gdzie T
przewiduje jedynie operator<
, std::sort(v.begin(), v.end())
zostanie skompilowany, a std::sort(v)
nie będzie? Brzmi to szalenie.
Sprawdziłem to w bieżącym ranges-v3 implementation przez Eric Niebler, i działa tak, jak opisałem. Kod nie jest kompilowany, chyba że dostarczono wszystkich operatorów.
Zobacz również związany dyskusji: https://github.com/ericniebler/range-v3/issues/271
Sprawdziłem to w obecnej implementacji range-v3 przez Erica Nieblera (https://github.com/ericniebler/range-v3) i działa tak, jak to opisałem. Kod nie jest kompilowany, chyba że dostarczono wszystkich operatorów. Ta implementacja wymaga jednak 'IndirectCallableRelation'. – Mikhail
@Mikhail: Czytałem dalej w specyfikacji. –
Dziękuję. Zobacz także https://github.com/ericniebler/range-v3/issues/271 – Mikhail