The Wayback Machine - https://web.archive.org/web/20220518055544/https://en.cppreference.com/w/cpp/algorithm/ranges/clamp
Namespaces
Variants
Views
Actions

std::ranges::clamp

From cppreference.com
< cpp‎ | algorithm‎ | ranges
 
 
Algorithm library
Constrained algorithms and algorithms on ranges (C++20)
Constrained algorithms, e.g. ranges::copy, ranges::sort, ...
Execution policies (C++17)
Non-modifying sequence operations
(C++11)(C++11)(C++11)
(C++17)
Modifying sequence operations
Partitioning operations
Sorting operations
(C++11)
Binary search operations
Set operations (on sorted ranges)
Heap operations
(C++11)
Minimum/maximum operations
(C++11)
(C++17)

Permutations
Numeric operations
Operations on uninitialized storage
(C++17)
(C++17)
(C++17)
C library
 
Constrained algorithms
Non-modifying sequence operations
Modifying sequence operations
Partitioning operations
Sorting operations
Binary search operations
Set operations (on sorted ranges)
Heap operations
Minimum/maximum operations
ranges::clamp

Permutations
Constrained numeric operations
Operations on uninitialized storage
Return types
 
Defined in header <algorithm>
Call signature
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 = {} );
(since C++20)

If v compares less than lo, returns lo; otherwise if hi compares less than v, returns hi; otherwise returns v.


The behavior is undefined if lo is greater than hi.

The function-like entities described on this page are niebloids, that is:

In practice, they may be implemented as function objects, or with special compiler extensions.

Contents

[edit] Parameters

v - the value to clamp
lo, hi - the boundaries to clamp v to
comp - the comparison to apply to the projected elements
proj - the projection to apply to v, lo and hi

[edit] Return value

Reference to lo if the projected value of v is less than the projected value of lo, reference to hi if the projected value of hi is less than the projected value of v, otherwise reference to v.

[edit] Complexity

At most two comparisons and three applications of the projection.

[edit] Possible implementation

struct clamp_fn {
  template<class T, class Proj = std::identity,
           std::indirect_strict_weak_order<std::projected<const T*, Proj>> Comp = 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);
 
      return std::invoke(comp, std::forward<decltype(pv)>(pv), std::invoke(proj, lo)) ? lo
           : std::invoke(comp, std::invoke(proj, hi), std::forward<decltype(pv)>(pv)) ? hi : v;
  }
};
 
inline constexpr clamp_fn clamp;

[edit] Notes

Capturing the result of std::ranges::clamp by reference produces a dangling reference if one of the parameters is a temporary and that parameter is returned:
int n = 1;
const int& r = std::ranges::clamp(n-1, n+1);
// r is dangling

If v compares equivalent to either bound, returns a reference to v, not the bound.

[edit] Example

#include <algorithm>
#include <cstdint>
#include <iostream>
#include <iomanip>
#include <string>
 
using namespace std::literals;
 
int main()
{
    std::cout << " raw   clamped to int8_t   clamped to uint8_t\n";
    for(int const v: {-129, -128, -1, 0, 42, 127, 128, 255, 256}) {
        std::cout << std::setw(04) << v
                  << std::setw(20) << std::ranges::clamp(v, INT8_MIN, INT8_MAX)
                  << std::setw(21) << std::ranges::clamp(v, 0, UINT8_MAX) << '\n';
    }
    std::cout << '\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(04) << v
                  << std::setw(20) << std::ranges::clamp(v, "-128"s, "127"s, {}, stoi)
                  << std::setw(21) << std::ranges::clamp(v, "0"s, "255"s, {}, stoi) << '\n';
    }
}

Output:

 raw   clamped to int8_t   clamped to uint8_t
-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

[edit] See also

returns the smaller of the given values
(niebloid) [edit]
returns the greater of the given values
(niebloid) [edit]
(C++20)
checks if an integer value is in the range of a given integer type
(function template) [edit]
(C++17)
clamps a value between a pair of boundary values
(function template) [edit]