名前空間
変種
操作

std::ranges::clamp

From cppreference.com
< cpp‎ | algorithm‎ | ranges
 
 
アルゴリズムライブラリ
制約付きアルゴリズムとRangeアルゴリズム (C++20)
制約付きアルゴリズム、例: ranges::copy, ranges::sort, ...
実行ポリシー (C++17)
シーケンスを変更しない操作
一括操作
(C++17)
検索操作
(C++11)                (C++11)(C++11)

シーケンスを変更する操作
コピー操作
(C++11)
(C++11)
スワップ操作
変換操作
生成操作
削除操作
順序変更操作
(C++17まで)(C++11)
(C++20)(C++20)
サンプリング操作
(C++17)

ソートおよび関連操作
パーティション操作
ソート操作
二分探索操作
(パーティション化された範囲)
集合操作 (ソート済み範囲)
マージ操作 (ソート済み範囲)
ヒープ操作
最小/最大操作
(C++11)
(C++17)
辞書順比較操作
順列操作
Cライブラリ
数値演算
未初期化メモリに対する操作
 
制約付きアルゴリズム
このメニューのすべての名前は名前空間 `std::ranges` に属します
シーケンスを変更しない操作
シーケンスを変更する操作
パーティション操作
ソート操作
二分探索操作 (ソート済み範囲)
       
       
集合操作 (ソート済み範囲)
ヒープ操作
最小/最大操作
       
       
clamp

順列操作
畳み込み操作
数値演算
(C++23)            
未初期化ストレージに対する操作
戻り値の型
 
ヘッダー <algorithm> で定義
呼び出しシグネチャ
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 を返します。それ以外の場合は、最も近い境界値を返します。

lohi より大きい場合、動作は未定義です。

このページで説明されている関数のようなエンティティは、アルゴリズム関数オブジェクト(非公式にはニーブロイドとして知られている)です。つまり、

目次

[編集] パラメータ

v - クランプする値
lo, hi - v をクランプする境界
comp - 投影された要素に適用する比較
proj - vlo、および hi に適用する投影

[編集] 戻り値

投影された v の値が投影された lo の値より小さい場合は lo への参照、投影された hi の値が投影された v の値より小さい場合は hi への参照、それ以外の場合は v への参照。

[編集] 計算量

最大2回の比較と3回の投影の適用。

[編集] 実装例

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 によって包含される)により、動作は未定義です。

標準では、投影結果の値カテゴリが保持されることが要求されており、projv に対して一度しか呼び出せないため、投影結果が prvalue の場合、コンパイラは2回キャッシュしてムーブする必要があり、コンパイラへの2回の呼び出しが発生します。

  • libstdc++ はこれに準拠しておらず、常に投影結果を lvalue として渡します。
  • libc++ は以前、投影を2回実行していましたが、Clang 18 で修正されました。
  • MSVC STL は以前、投影を2回実行していましたが、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)
値を一対の境界値の間に制限する
(関数テンプレート) [編集]
English 日本語 中文(简体) 中文(繁體)