Namespaces
Variants

std::ranges::clamp

С ru.cppreference.net
 
 
Библиотека алгоритмов
Ограниченные алгоритмы и алгоритмы над диапазонами (C++20)
Ограниченные алгоритмы, например ranges::copy, ranges::sort, ...
Немодифицирующие операции над последовательностями    
Групповые операции
(C++17)
Операции поиска
Модифицирующие операции над последовательностями
Операции копирования
(C++11)
(C++11)
Операции обмена
Операции преобразования
Операции генерации
Операции удаления
Операции изменения порядка
(до C++17)(C++11)
(C++20)(C++20)
Операции выборки
(C++17)

Сортировка и связанные операции
Операции разбиения
(C++11)    

Операции сортировки
Операции бинарного поиска
(по разбитым диапазонам)
Операции над множествами (по отсортированным диапазонам)
Операции слияния (по отсортированным диапазонам)
Операции с кучей
Операции минимума/максимума
(C++11)
(C++17)
Операции лексикографического сравнения
Операции перестановки


Политики выполнения (C++17)
(только для демонстрации*)(C++26)

Численные операции
(C++11)
(C++17)
(C++17)    

Специализированные <memory> алгоритмы

Специализированные <random> алгоритмы
Библиотека C









 
Ограниченные алгоритмы
Все имена в этом меню принадлежат пространству имён std::ranges
Немодифицирующие операции над последовательностями
Модифицирующие операции над последовательностями
Операции разбиения
Операции сортировки
Операции бинарного поиска (по отсортированным диапазонам)
       
       
Операции над множествами (по отсортированным диапазонам)
Операции с кучей
Операции минимума/максимума
       
       
Операции перестановки
Операции свёртки
Операции над неинициализированной памятью
Типы возврата
 
Определено в заголовке <algorithm>
Сигнатура вызова
template< class T, class Proj = std::identity,
          std::indirect_strict_weak_order<std::projected<const T*, Proj>> Comp =
              ranges::less >
constexpr const T&
    clamp( const T& v, const T& lo, const T& hi, Comp comp = {}, Proj proj = {} );
(начиная с C++20)

Если значение v находится в пределах [lo, hi], возвращает v; в противном случае возвращает ближайшую границу.

Поведение не определено, если lo больше, чем hi.

Функциональные объекты, описанные на этой странице, являются объектами-функциями алгоритмов (неформально известными как niebloids), то есть:

Параметры

v - значение для зажима
lo, hi - границы, к которым применяется зажим v
comp - сравнение, применяемое к проекции элементов
proj - проекция, применяемая к v, lo и hi

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

Ссылка на lo, если проекция значения v меньше, чем проекция значения lo, ссылка на hi, если проекция значения hi меньше, чем проекция значения v, в противном случае ссылка на v.

Сложность

Не более двух сравнений и трех применений проекции.

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

struct clamp_fn
{
    template<class T, class Proj = std::identity,
             std::indirect_strict_weak_order<std::projected<const T*, Proj>>
                 Comp = std::ranges::less>
    constexpr const T& operator()(const T& v, const T& lo, const T& hi,
                                  Comp comp = {}, Proj proj = {}) const
    {
        auto&& pv = std::invoke(proj, v);

        if (std::invoke(comp, std::forward<decltype(pv)>(pv), std::invoke(proj, lo)))
            return lo;

        if (std::invoke(comp, std::invoke(proj, hi), std::forward<decltype(pv)>(pv)))
            return hi;

        return v;
    }
};

inline constexpr clamp_fn clamp;

Примечания

Захват результата std::ranges::clamp по ссылке приводит к висячей ссылке, если один из параметров является временным и этот параметр возвращается:

int n = -1;
const int& r = std::ranges::clamp(n, 0, 255); // r is dangling

Если v сравнивается как эквивалентный любой из границ, возвращает ссылку на v, а не на границу.

Эту функцию не следует использовать одновременно с проекцией, возвращающей по значению, и компаратором, принимающим аргументы по значению, если только перемещение из типа результата проекции в тип параметра компаратора не эквивалентно копированию. Если сравнение через std::invoke изменит результат проекции, поведение не определено из-за семантических требований std::regular_invocable (поглощено std::indirect_strict_weak_order).

Стандарт требует, чтобы категория значения результата проекции сохранялась, и proj может вызываться только для v один раз, что означает, что результат проекции, являющийся prvalue, должен быть кэширован и перемещен дважды для двух вызовов компаратора.

  • libstdc++ не соответствует этому и всегда передает результат проекции как lvalue.
  • libc++ ранее запускал проекцию дважды, что было исправлено в Clang 18.
  • MSVC STL ранее запускал проекцию дважды, что было исправлено в VS 2022 17.2.

Пример

#include <algorithm>
#include <cstdint>
#include <iomanip>
#include <iostream>
#include <string>

using namespace std::literals;
namespace ranges = std::ranges;

int main()
{
    std::cout << "[raw] [" << INT8_MIN << ',' << INT8_MAX << "] "
                 "[0" << ',' << UINT8_MAX << "]\n";
    for (int const v : {-129, -128, -1, 0, 42, 127, 128, 255, 256})
        std::cout << std::setw(4) << v
                  << std::setw(11) << ranges::clamp(v, INT8_MIN, INT8_MAX)
                  << std::setw(8) << ranges::clamp(v, 0, UINT8_MAX) << '\n';
    std::cout << std::string(23, '-') << '\n';

    // Projection function
    const auto stoi = [](std::string s) { return std::stoi(s); };

    // Same as above, but with strings
    for (std::string const v : {"-129", "-128", "-1", "0", "42",
                                "127", "128", "255", "256"})
        std::cout << std::setw(4) << v
                  << std::setw(11) << ranges::clamp(v, "-128"s, "127"s, {}, stoi)
                  << std::setw(8) << ranges::clamp(v, "0"s, "255"s, {}, stoi)
                  << '\n';
}

Вывод:

[raw] [-128,127] [0,255]
-129       -128       0
-128       -128       0
  -1         -1       0
   0          0       0
  42         42      42
 127        127     127
 128        127     128
 255        127     255
 256        127     255
-----------------------
-129       -128       0
-128       -128       0
  -1         -1       0
   0          0       0
  42         42      42
 127        127     127
 128        127     128
 255        127     255
 256        127     255

Смотрите также

возвращает меньшее из заданных значений
(объект-функция алгоритма)
возвращает большее из заданных значений
(объект-функция алгоритма)
(C++20)
проверяет, находится ли целое значение в диапазоне заданного целого типа
(шаблон функции)
(C++17)
зажимает значение между парой граничных значений
(шаблон функции)