Namespaces
Variants

std::clamp

ja.cppreference.net から
 
 
アルゴリズムライブラリ
制約付きアルゴリズムと範囲に対するアルゴリズム (C++20)
制約付きアルゴリズム (例: ranges::copy、ranges::sort、...)
ソートと関連操作
分割操作
(C++11)    

ソート操作
二分探索操作
(分割範囲に対して)
集合操作 (ソート済み範囲に対して)
マージ操作 (ソート済み範囲に対して)
ヒープ操作
最小値/最大値操作
(C++11)
(C++17)
辞書比較操作
順列操作


 
ヘッダ <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, hi] の範囲内にある場合、v を返します。そうでなければ最も近い境界値を返します。

1) 値の比較には operator<(C++20 まで)std::less{}(C++20 以上) を使用します。
T が LessThanComparable ではない場合、動作は未定義です。[1]
2) 値の比較には比較関数 comp を使用します。

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

  1. ↑ NaN を避けると、T は浮動小数点型にできます。

引数

v - クランプする値
lo, hi - v をクランプする範囲
comp - 比較関数オブジェクト (つまり Compare の要件を満たすオブジェクト)。第一引数が第二引数よりtrue小さい場合に を返します。

比較関数のシグネチャは以下と等価である必要があります:

bool cmp(const Type1& a, const Type2& b);

シグネチャに const& が含まれている必要はありませんが、関数は渡されたオブジェクトを変更してはならず、型 (const の可能性もある) Type1 および Type2 のすべての値を、値カテゴリに関係なく受け入れられなければなりません (したがって、Type1& は許可されません。また、 も、Type1 がムーブとコピーが等価である場合を除き許可されませんType1(C++11 以上))。
型 Type1 および Type2 は、型 T のオブジェクトが暗黙的に両方に変換可能である必要があります。

戻り値

lo が v より小さい場合は lo への参照、hi が hi より小さい場合は v への参照、それ以外の場合は v への参照を返します。

計算量

1) operator<(C++20 まで)std::less{}(C++20 以上) を使用した最大2回の比較。
2) 比較関数 comp の最大2回の適用。

実装例

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;
}

注記

std::clamp の結果を参照で捕捉すると、パラメータのいずれかが一時オブジェクトであり、そのパラメータが返された場合に、ぶら下がり参照が発生します:

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

v がいずれかの境界と同値と比較される場合、境界ではなく v への参照を返します。

機能テスト マクロ 値 標準 機能
__cpp_lib_clamp 201603L (C++17) std::clamp

例

#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';
}

出力:

[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

関連項目

指定された値のうち小さい方を返す
(関数テンプレート & アルゴリズム関数オブジェクト)
指定された値のうち大きい方を返す
(関数テンプレート & アルゴリズム関数オブジェクト)
(C++20)
整数値が指定された整数型の範囲内にあるか確認する
(関数テンプレート)
値を一対の境界値の間にクランプする
(アルゴリズム関数オブジェクト)