Daily bit(e) C++. std::equal_to, std::not_equal_to, std::greater, std::less, std::greater_equal, std::less_equal and std::compare_three_way
Daily bit(e) C++ #227, функциональные объекты компараторов: std::equal_to
, std::not_equal_to
, std::greater
, std::less
, std::greater_equal
, std::less_equal
и std::compare_three_way
.
Функциональные объекты: std::equal_to
, std::not_equal_to
, std::greater
, std::less
, std::greater_equal
, std::less_equal
и (C++20) std::compare_three_way
реализуют соответствующие операции сравнения.
Эти объекты могут служить компараторами для алгоритмов, которые их принимают. Это избавляет нас от необходимости писать лямбду только для того, чтобы вернуть результат сравнения двух аргументов.
#include <functional>
#include <algorithm>
#include <vector>
struct A {};
struct B {};
bool operator<(A,B) { return false; }
std::vector<int> data{8,4,1,3,2,9,6,5,7};
// Версия с явной специализацией:
std::ranges::sort(data, std::greater<int>{});
// data == {9,8,7,6,5,4,3,2,1}
// Явная специализация может вызвать проблемы
// с неявными преобразованиями.
std::vector<double> fpoint{4.2,4.1,4.3,4.4,4.9,4.5};
std::ranges::sort(fpoint, std::greater<int>{});
// Неуказанный порядок, но технически это должно быть запрещено.
// Причина: все элементы равны при преобразовании в int.
// Специализация <void> с выводом типа из C++14
std::ranges::sort(fpoint, std::greater<>{});
// Аргументы компаратора будут выведены как double.
// fpoint == {4.9,4.5,4.4,4.3,4.2,4.1}
// Версия для диапазонов из C++20, аргументы выводятся всегда.
std::ranges::sort(data, std::ranges::greater{});
// При использовании с неоднородными типами поведение отличается.
int x = 4; double y = 4.2;
// Старый стиль, явно указанный тип с принудительным
// неявным преобразованием
bool cmp1 = std::less<int>{}(x,y);
bool cmp2 = std::less<double>{}(x,y);
// cmp1 == false, cmp2 == true
// C++14, выводятся оба аргумента, operator< потенциально
// применяется к разнородному типу.
bool cmp3 = std::less<>{}(x,y); // <int,double>
// cmp3 == true
// C++20, выводятся оба аргумента,
// но ограничено более строгой семантикой.
bool cmp4 = std::ranges::less{}(x,y);
// cmp4 == true
std::less<>{}(A{},B{}); // OK
// std::ranges::less{}(A{},B{}); // не скомпилируется
Открыть пример на Compiler Explorer.