std::clamp(3)
π std::clamp
okay so bestie, you've landed on the std::clamp(3) page from the C++ Standard Library manual (section 3, naturally π
). Buckle up, because this little function is about to become your new fave. β¨
πΈ NAME
std::clamp β that's it, that's the name. std::clamp. Short, sweet, and it ate. π
π¦ Synopsis
Defined in header <algorithm>:
template< class T > (1)
(since C++17)
constexpr const T& clamp( const T& v, const T& lo, const T& hi );
template< class T, class Compare >
constexpr const T& clamp( const T& v, const T& lo, const T& hi, (2)
(since C++17)
Compare comp );
Here's the tea β β if the value of v is within [lo, hi], it returns v; otherwise it returns the nearest boundary. That's the whole vibe check.
- Uses
operator<(until C++20) orstd::less{}(since C++20) to compare the values. IfTis notLessThanComparable, the behavior is undefined.^[1] - Uses the comparison function
compto compare the values.
β οΈ Iflois greater thanhi, the behavior is undefined. Like, don't do that. Fr fr. π
- β If
NaNis avoided,Tcan be a floating-point type.
π§ Parameters
vβ the value to clamp, bestie. The main character.lo,hiβ the boundaries to clampvto. The supporting cast that keepsvin line.compβ comparison function object (i.e. an object that satisfies the requirements ofCompare) which returnstrueif the first argument is less than the second.
The signature of the comparison function should be equivalent to the following:
bool cmp(const Type1& a, const Type2& b);
While the signature does not need to have const&, the function must not modify the objects passed to it and must be able to accept all values of type (possibly const) Type1 and Type2 regardless of value category (thus, Type1& is not allowed, nor is Type1 unless for Type1 a move is equivalent to a copy (since C++11)). The types Type1 and Type2 must be such that an object of type T can be implicitly converted to both of them. π (yes that was a lot, but every word is load-bearing, iykyk)
π Return value
Reference to lo if v is less than lo, reference to hi if hi is less than v, otherwise reference to v. Simple as that, no cap. β¨
π₯ Complexity
- At most two comparisons using
operator<(until C++20) orstd::less{}(since C++20). - At most two applications of the comparison function
comp.
Two. That's literally it. So efficient it's giving overachiever. π«Ά
π Possible implementation
clamp (1)
template<class T>
constexpr const T& clamp(const T& v, const T& lo, const T& hi)
{
return clamp(v, lo, hi, less{});
}
clamp (2)
template<class T, class Compare>
constexpr const T& clamp(const T& v, const T& lo, const T& hi, Compare comp)
{
return comp(v, lo) ? lo : comp(hi, v) ? hi : v;
}
Look at that ternary. Chef's kiss. π
π Notes
Capturing the result of std::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::clamp(n, 0, 255); // r is dangling
π Do NOT do this. That r is dangling. It is not okay. It is going through things.
If v compares equivalent to either bound, returns a reference to v, not the bound. Noted and filed away, bestie. π
Feature-test macro time, and honestly the table is a vibe:
- Feature-test macro:
__cpp_lib_clamp - Value:
201603L - Std:
(C++17) - Feature:
std::clamp
π Example
// Run this code
#include <algorithm>
#include <cstdint>
#include <iomanip>
#include <iostream>
int main()
{
std::cout << "[raw] "
"[" << INT8_MIN << ',' << INT8_MAX << "] "
"[0," << UINT8_MAX << "]\n";
for (const int v : {-129, -128, -1, 0, 42, 127, 128, 255, 256})
std::cout << std::setw(4) << v
<< std::setw(11) << std::clamp(v, INT8_MIN, INT8_MAX)
<< std::setw(8) << std::clamp(v, 0, UINT8_MAX) << '\n';
}
β Output
[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
See how -129 got yanked up to -128 and 256 got yanked down to 255? That's clamping, baby. Boundaries respected. Boundaries slayed. π₯
π¦ See also
minβ returns the smaller of the given values (function template)maxβ returns the greater of the given values (function template)in_rangeβ checks if an integer value is in the range of a given integer type (C++20) (function template)ranges::clampβ clamps a value between a pair of boundary values (C++20) (niebloid)
okay that's the whole page, bestie! π«Ά this icon was brought to you by http://cppreference.com, version 2024.06.10, filed under std::clamp(3) β go forth and clamp responsibly, mwah ππ
π¦ where this page comes from
- nixpkgs unstable: stdman 2024.07.05
- opensuse-leap 16.0: stdman 2024.07.05-bp160.1.9 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms