Spec-Zone.ru › C++

std::ranges::minmax, std::ranges::minmax_result

Определено в заголовке <algorithm>
Подпись вызова
template< class T, class Proj = std::identity,
          std::indirect_strict_weak_order<
              std::projected<const T*, Proj>> Comp = ranges::less >
constexpr ranges::minmax_result<const T&>
    minmax( const T& a, const T& b, Comp comp = {}, Proj proj = {} );
(1) (с C++20)
template< std::copyable T, class Proj = std::identity,
          std::indirect_strict_weak_order<
              std::projected<const T*, Proj>> Comp = ranges::less >
constexpr ranges::minmax_result<T>
    minmax( std::initializer_list<T> r, Comp comp = {}, Proj proj = {} );
(2) (с C++20)
template< ranges::input_range R, class Proj = std::identity,
          std::indirect_strict_weak_order<
              std::projected<ranges::iterator_t<R>, Proj>> Comp = ranges::less >
requires std::indirectly_copyable_storable<ranges::iterator_t<R>, ranges::range_value_t<R>*>
constexpr ranges::minmax_result<ranges::range_value_t<R>>
    minmax( R&& r, Comp comp = {}, Proj proj = {} );
(3) (с C++20)
Вспомогательные типы
template< class T >
using minmax_result = ranges::min_max_result<T>;
(4) (с C++20)

Возвращает наименьшее и наибольшее из заданных спроецированных значений.

1) Возвращает ссылки на меньшее и большее из a и b.
2) Возвращает наименьшее и наибольшее из значений в списке инициализации r.
3) Возвращает наименьшее и наибольшее из значений в диапазоне r.

Функциональные сущности, описанные на этой странице, являются niebloids, то есть:

  • Явные списки аргументов шаблона не могут быть указаны при вызове любого из них.
  • Ни один из них не виден для поиска аргументов по зависимости от контекста.
  • Когда любой из них найден обычным неуточнённым поиском как имя слева от оператора вызова функции, поиск аргументов по зависимости от контекста ингибируется.

На практике они могут быть реализованы как объекты функций или с помощью специальных расширений компилятора.

Параметры

a, b - значения для сравнения
r - непустой диапазон значений для сравнения
comp - сравнение для применения к спроецированным элементам
proj - проекция для применения к элементам

Возвращаемое значение

1) {b, a} если, согласно их соответственно спроецированному значению, b меньше a; в противном случае возвращает {a, b}.
2,3) {s, l}, где s и l соответственно наименьшее и наибольшее значения в r, согласно их спроецированному значению. Если несколько значений эквивалентны наименьшему и наибольшему, возвращает самое левое наименьшее значение и самое правое наибольшее значение. Если диапазон пуст (определяется ranges::distance(r)), поведение не определено.

Сложность

1) Ровно одно сравнение и две применения проекции.
2,3) Не более 3 / 2 * ranges::distance(r) сравнений и вдвое больше применений проекции.

Возможная реализация

struct minmax_fn
{
    template<class T, class Proj = std::identity,
             std::indirect_strict_weak_order<
                 std::projected<const T*, Proj>> Comp = ranges::less>
    constexpr ranges::minmax_result<const T&>
         operator()(const T& a, const T& b, Comp comp = {}, Proj proj = {}) const
    {
        if (std::invoke(comp, std::invoke(proj, b), std::invoke(proj, a)))
            return {b, a};
 
        return {a, b};
    }
 
    template<std::copyable T, class Proj = std::identity,
             std::indirect_strict_weak_order<
                 std::projected<const T*, Proj>> Comp = ranges::less>
    constexpr ranges::minmax_result<T>
        operator()(std::initializer_list<T> r, Comp comp = {}, Proj proj = {}) const
    {
        auto result = ranges::minmax_element(r, std::ref(comp), std::ref(proj));
        return {*result.min, *result.max};
    }
 
    template<ranges::input_range R, class Proj = std::identity,
             std::indirect_strict_weak_order<
                 std::projected<ranges::iterator_t<R>, Proj>> Comp = ranges::less>
    requires std::indirectly_copyable_storable<ranges::iterator_t<R>,
                                               ranges::range_value_t<R>*>
    constexpr ranges::minmax_result<ranges::range_value_t<R>>
        operator()(R&& r, Comp comp = {}, Proj proj = {}) const
    {
        auto result = ranges::minmax_element(r, std::ref(comp), std::ref(proj));
        return {std::move(*result.min), std::move(*result.max)};
    }
};
 
inline constexpr minmax_fn minmax;

Примечания

Для перегрузки (1), если один из параметров является временным, ссылка, возвращённая, становится висящей ссылкой в конце полного выражения, содержащего вызов minmax:

int n = 1;
auto p = std::ranges::minmax(n, n + 1);
int m = p.min; // ok
int x = p.max; // undefined behavior
 
// Note that structured bindings have the same issue
auto [mm, xx] = std::ranges::minmax(n, n + 1);
xx; // undefined behavior

Пример

#include <algorithm>
#include <array>
#include <iostream>
#include <random>
 
int main()
{
    namespace ranges = std::ranges;
 
    constexpr std::array v{3, 1, 4, 1, 5, 9, 2, 6, 5};
 
    std::random_device rd;
    std::mt19937_64 generator(rd());
    std::uniform_int_distribution<> distribution(0, ranges::distance(v)); // [0..9]
 
    // auto bounds = ranges::minmax(distribution(generator), distribution(generator));
    // UB: dangling references: bounds.min and bounds.max have the type `const int&`.
 
    const int x1 = distribution(generator);
    const int x2 = distribution(generator);
    auto bounds = ranges::minmax(x1, x2); // OK: got references to lvalues x1 and x2
 
    std::cout << "v[" << bounds.min << ":" << bounds.max << "]: ";
    for (int i = bounds.min; i < bounds.max; ++i)
        std::cout << v[i] << ' ';
    std::cout << '\n';
 
    auto [min, max] = ranges::minmax(v);
    std::cout << "smallest: " << min << ", " << "largest: " << max << '\n';
}

Возможный вывод:

v[3:9]: 1 5 9 2 6 5 
smallest: 1, largest: 9

См. также

ranges::min
(C++20)
возвращает меньшее из заданных значений
(niebloid)
ranges::max
(C++20)
возвращает большее из заданных значений
(niebloid)
ranges::minmax_element
(C++20)
возвращает наименьшие и наибольшие элементы в диапазоне
(niebloid)
ranges::clamp
(C++20)
ограничивает значение между парой граничных значений
(niebloid)
minmax
(C++11)
возвращает меньшее и большее из двух элементов
(шаблон функции)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/algorithm/ranges/minmax

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API