std::clamp
| 受约束算法及范围上的算法 (C++20) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 受约束算法: std::ranges::copy, std::ranges::sort, ... | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 执行策略 (C++17) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 不修改序列的操作 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 修改序列的操作 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Partitioning operations | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 划分操作 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 排序操作 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 二分搜索操作 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 集合操作(在已排序范围上) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 堆操作 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 最小/最大操作 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 排列 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 数值运算 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 未初始化存储上的操作 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| C 库 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
在标头
<algorithm>
定义
|
||
|
template<class T>
constexpr const T& clamp( const T& v, const T& lo, const T& hi ); |
(1) | (C++17 起) |
|
template<class T, class Compare>
constexpr const T& clamp( const T& v, const T& lo, const T& hi, Compare comp ); |
(2) | (C++17 起) |
v 小于 lo ,则返回
lo ;若 v 大于 hi ,则返回 hi ;否则返回 v
。使用 operator< 比较值。comp 比较值。若 lo 的值大于 hi 则行为未定义。
参数
| v | - | 要夹住的值 |
| lo,hi | - | 夹 v 的边界
|
| comp | - | 比较函数对象(即满足比较 (Compare)
要求的对象),如果 lo 小于 v 且 v 小于
hi,那么返回 true。比较函数的签名应等价于如下: bool cmp(const Type1 &a, const Type2 &b); 虽然签名不必有 const &,函数也不能修改传递给它的对象,而且必须接受(可有 const
限定的)类型 |
| 类型要求 | ||
- 为使用重载 (1), T 必须符合可小于比较 (LessThanComparable)
的要求。然而若避免了 NaN ,则 T 能为浮点类型。
|
||
返回值
若 v 小于 lo 到则为 lo 的引用,若 hi 小于 v
则为到 hi 的引用,否则为到 v 的引用。
复杂度
至多二次比较
可能的实现
| 版本一 |
|---|
template<class T> constexpr const T& clamp( const T& v, const T& lo, const T& hi ) { assert( !(hi < lo) ); return v < lo ? lo : hi < v ? hi : v; } |
| 版本二 |
template<class T, class Compare> constexpr const T& clamp( const T& v, const T& lo, const T& hi, Compare comp ) { assert( !comp(hi, lo) ); return comp(v, lo) ? lo : comp(hi, v) ? hi : v; } |
注解
std::clamp 的结果会产生一个悬垂引用:
int n = -1; const int& r = std::clamp(n, 0, 255); // r 悬垂
若 v 与边界之一比较相等,则返回到 v 的引用,而非到边界者。
示例
#include <cstdint> #include <algorithm> #include <iostream> #include <iomanip> #include <random> int main() { std::mt19937 g(std::random_device{}()); std::uniform_int_distribution<> d(-300, 300); std::cout << " raw clamped to int8_t clamped to uint8_t\n"; for(int n = 0; n < 5; ++n) { int v = d(g); std::cout << std::setw(4) << v << std::setw(20) << std::clamp(v, INT8_MIN, INT8_MAX) << std::setw(21) << std::clamp(v, 0, UINT8_MAX) << '\n'; } }
可能的输出:
.raw clamped to int8_t clamped to uint8_t 168 127 168 128 127 128 -137 -128 0 40 40 40 -66 -66 0
参阅
| 返回各给定值中的较小者 (函数模板) |
|
| 返回各给定值中的较大者 (函数模板) |
|
|
(C++20)
|
检查整数值是否在给定整数类型的范围内 (函数模板) |
|
(C++20)
|
在一对边界值间夹一个值 (niebloid) |