#опытным
В догонку к предыдущим постам. Вот у вас есть структурка TIme из С++17:
struct Time {
int hours;
int minutes;
int seconds;
bool operator<(const Time &other) const {
return std::tie(hours, minutes, seconds) <
std::tie(other.hours, other.minutes, other.seconds);
}
};Вы как-то заполняете ее и сортируете:
std::vector<Time> times = {
{14, 30, 15}, {9, 45, 0}, {14, 30, 0}, {23, 59, 59}, {0, 0, 0}};
std::sort(times.begin(), times.end());И все работает прекрасно.
И тут решили вы перейти на С++20 и заменить все алгоритмы классической stl на алгоритмы ренджей. Синтаксис у них понятнее, да и почему бы и нет. Изменения тут будут тривиальные:
std::vector<Time> times = {
{14, 30, 15}, {9, 45, 0}, {14, 30, 0}, {23, 59, 59}, {0, 0, 0}};
std::ranges::sort(times);Запускаете сборку, а она падает с какими-то нечитаемыми ошибки, типа таких:
/usr/include/c++/15/concepts:362:13: required for the satisfaction of 'invocable<_Fn, _Args ...>' [with _Fn = std::ranges::less&; _Args = {Time&, Time&}]
/usr/include/c++/15/concepts:366:13: required for the satisfaction of 'regular_invocable<_Fn, _Args ...>' [with _Fn = std::ranges::less&; _Args = {Time&, Time&}]
/usr/include/c++/15/concepts:370:13: required for the satisfaction of 'predicate<_Rel, _Tp, _Tp>' [with _Rel = std::ranges::less&; _Tp = Time&]
/usr/include/c++/15/concepts:375:13: required for the satisfaction of 'relation<_Rel, _Tp, _Up>' [with _Rel = std::ranges::less&; _Tp = Time&; _Up = Time&]
/usr/include/c++/15/concepts:385:13: required for the satisfaction of 'strict_weak_order<_Fn&, typename std::__detail::__indirect_value<_Iter>::type, typename std::__detail::__indirect_value<_I2>::type>' [with _Fn = std::ranges::less; _I1 = __gnu_cxx::__normal_iterator<Time*, std::vector<Time, std::allocator<Time> > >; _I2 = __gnu_cxx::__normal_iterator<Time*, std::vector<Time, std::allocator<Time> > >]Нам говорили, что с концептами ошибки станут понятнее, но это только в теории. А на практике вот это.
В чем в итоге проблема?
По умолчанию в сортировке рэнджей используется компаратор std::ranges::less, а в обычной сортировке - std::less. И в их разнице и зарыта собака: std::ranges::less требует определения всех шести операторов сравнения или одного spaceship'а и все заработает:
struct Time {
int hours;
int minutes;
int seconds;
// Spaceship operator (генерирует все 6 операторов сравнения)
auto operator<=>(const Time& other) const = default;
};
std::vector<Time> times = {
{14, 30, 15}, {9, 45, 0}, {14, 30, 0}, {23, 59, 59}, {0, 0, 0}};
std::ranges::sort(times);Ну или можете пометить оператор< дефотным и передавать в сортировку std::less:
struct Time {
int hours;
int minutes;
int seconds;
bool operator<(const Time& other) const = default; // Here
};
std::vector<Time> times = {
{14, 30, 15}, {9, 45, 0}, {14, 30, 0}, {23, 59, 59}, {0, 0, 0}};
std::ranges::sort(times, std::less{}); // And hereПару раз натыкался на эту проблему, поэтому решил поделиться болью.
Give clear feedback. Stay cool.