名稱空間
變體
操作

std::ranges::clamp

來自 cppreference.com
< cpp‎ | 演算法‎ | 範圍
 
 
演算法庫
有約束演算法與針對範圍的演算法 (C++20)
有約束的演算法,例如 ranges::copyranges::sort 等……
執行策略 (C++17)
排序及相關操作
劃分操作
排序操作
二分搜尋操作
(於已劃分範圍上)
集合操作(於已排序範圍上)
歸併操作(於已排序範圍上)
堆操作
最小/最大值操作
(C++11)
(C++17)
字典序比較操作
排列操作
C 庫
數值操作
未初始化記憶體上的操作
 
受約束演算法
此選單中的所有名稱均屬於名稱空間 std::ranges
非修改序列操作
修改序列操作
劃分操作
排序操作
二分查詢操作(在已排序的範圍內)
       
       
集合操作(於已排序範圍上)
堆操作
最小/最大值操作
       
       
clamp

排列操作
摺疊操作
數值操作
(C++23)            
對未初始化儲存的操作
返回型別
 
定義於標頭檔案 <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 = {} );
(C++20 起)

如果 v 的值在 [lohi] 範圍內,則返回 v;否則返回最近的邊界。

如果 lo 大於 hi,則行為未定義。

本頁描述的類函式實體是 演算法函式物件(非正式地稱為 niebloids),即

目錄

[編輯] 引數

v - 要限制的值
lo, hi - 限制 v 的邊界
comp - 應用於投影元素的比較器
proj - 應用於 vlohi 的投影

[編輯] 返回值

如果 v 的投影值小於 lo 的投影值,則返回 lo 的引用;如果 hi 的投影值小於 v 的投影值,則返回 hi 的引用;否則返回 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 subsume),行為未定義。

標準要求保留投影結果的值類別,並且 proj 只能在 v 上呼叫一次,這意味著 prvalue 的投影結果必須被快取併為比較器的兩次呼叫移動兩次。

  • libstdc++ 不符合此要求,並且總是將投影結果作為左值傳遞。
  • 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)
將值限制在邊界值對之間
(函式模板) [編輯]