跳到主要内容

std::ranges::clamp() 算法

// (1)
constexpr const T&
clamp( const T& v, const T& lo, const T& hi, Comp comp = {}, Proj proj = {} );

参数类型是泛型的,并具有以下约束

  • T - (无)
  • Proj - (无)
  • Comp - std::indirect_strict_weak_order<std::projected<const T*, Proj>>
  • 如果 v 小于 lo,则返回 lo

  • 否则,如果 v 大于 hi,则返回 hi

  • 否则返回 v

  • (1) 使用 operator< 比较值。

  • (2)(1) 相同,但使用 comp 比较值。

未定义行为

行为未定义

如果 lo 的值大于 hi

参数

v

要限制的值。

lo
hi

要限制的元素范围。

comp

应用于投影元素的比较操作。

proj

应用于 vlohi 的投影操作。

返回值

如果 v 的投影值小于 lo 的投影值,则返回 lo 的引用;如果 hi 的投影值小于 v 的投影值,则返回 hi 的引用;否则返回 v 的引用。

复杂度

最多进行两次比较和三次投影应用。

异常

(无)

可能的实现

clamp(1) 和 clamp(2)
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;

备注

未定义行为

如果其中一个参数是临时值且该参数被返回,则通过引用捕获 std::ranges::clamp 的结果会产生悬空引用。

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

如果 v 与任一边界进行等价比较,则返回 v 的引用,而不是边界的引用。

示例

Main.cpp
#include <algorithm>
#include <cstdint>
#include <iomanip>
#include <iostream>
#include <string>

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

int main()
{
for (std::cout << " raw clamped to int8_t clamped to uint8_t\n";
int const v: {-129, -128, -1, 0, 42, 127, 128, 255, 256})
std::cout << std::setw(04) << v
<< std::setw(20) << ranges::clamp(v, INT8_MIN, INT8_MAX)
<< std::setw(21) << 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) << ranges::clamp(v, "-128"s, "127"s, {}, stoi)
<< std::setw(21) << ranges::clamp(v, "0"s, "255"s, {}, stoi)
<< '\n';
}
输出

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
本文源自 此 CppReference 页面。它可能经过修改以进行改进或适应编辑者偏好。点击“编辑此页面”查看本文档的所有更改。
悬停查看原始许可证。

std::ranges::clamp() 算法

// (1)
constexpr const T&
clamp( const T& v, const T& lo, const T& hi, Comp comp = {}, Proj proj = {} );

参数类型是泛型的,并具有以下约束

  • T - (无)
  • Proj - (无)
  • Comp - std::indirect_strict_weak_order<std::projected<const T*, Proj>>
  • 如果 v 小于 lo,则返回 lo

  • 否则,如果 v 大于 hi,则返回 hi

  • 否则返回 v

  • (1) 使用 operator< 比较值。

  • (2)(1) 相同,但使用 comp 比较值。

未定义行为

行为未定义

如果 lo 的值大于 hi

参数

v

要限制的值。

lo
hi

要限制的元素范围。

comp

应用于投影元素的比较操作。

proj

应用于 vlohi 的投影操作。

返回值

如果 v 的投影值小于 lo 的投影值,则返回 lo 的引用;如果 hi 的投影值小于 v 的投影值,则返回 hi 的引用;否则返回 v 的引用。

复杂度

最多进行两次比较和三次投影应用。

异常

(无)

可能的实现

clamp(1) 和 clamp(2)
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;

备注

未定义行为

如果其中一个参数是临时值且该参数被返回,则通过引用捕获 std::ranges::clamp 的结果会产生悬空引用。

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

如果 v 与任一边界进行等价比较,则返回 v 的引用,而不是边界的引用。

示例

Main.cpp
#include <algorithm>
#include <cstdint>
#include <iomanip>
#include <iostream>
#include <string>

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

int main()
{
for (std::cout << " raw clamped to int8_t clamped to uint8_t\n";
int const v: {-129, -128, -1, 0, 42, 127, 128, 255, 256})
std::cout << std::setw(04) << v
<< std::setw(20) << ranges::clamp(v, INT8_MIN, INT8_MAX)
<< std::setw(21) << 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) << ranges::clamp(v, "-128"s, "127"s, {}, stoi)
<< std::setw(21) << ranges::clamp(v, "0"s, "255"s, {}, stoi)
<< '\n';
}
输出

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
本文源自 此 CppReference 页面。它可能经过修改以进行改进或适应编辑者偏好。点击“编辑此页面”查看本文档的所有更改。
悬停查看原始许可证。