名前空間
変種
操作

std::clamp

提供: cppreference.com
< cpp‎ | algorithm
 
 
アルゴリズムライブラリ
実行ポリシー (C++17)
非変更シーケンス操作
(C++11)(C++11)(C++11)
(C++17)
変更シーケンス操作
未初期化記憶域の操作
分割操作
ソート操作
(C++11)
二分探索操作
集合操作 (ソート済み範囲用)
ヒープ操作
(C++11)
最小/最大演算
(C++11)
clamp
(C++17)
順列
数値演算
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以上)
1) vlo より小さい場合は lo を返し、そうでなく hiv より小さい場合は hi を返し、そうでなければ v を返します。 値を比較するために operator< を使用します。
2) (1) と同じですが、値を比較するために comp を使用します。

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

目次

[編集] 引数

v - クランプする値
lo,hi - v をクランプする境界
comp - 第1引数が第2引数より小さい場合に true を返す、比較関数オブジェクト (Compare の要件を満たすオブジェクト)。

比較関数のシグネチャは以下と同等であるべきです。

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

シグネチャが const & を持つ必要はありませんが、関数は渡されたオブジェクトを変更してはならず、値カテゴリに関わらず Type1 および Type2 型 (およびそれらの const 修飾された型) のすべての値を受理できなければなりません (そのため Type1 & は許されません。 また Type1 に対してムーブがコピーと同等でなければ Type1 も許されません (C++11以上))。
Type1 および Type2 は、どちらも T 型のオブジェクトから暗黙に変換可能なものでなければなりません。 ​

型の要件
-
オーバロード (1) を使用するためには TLessThanComparable の要件を満たさなければなりません。

[編集] 戻り値

vlo より小さい場合は lo を指す参照、 hiv より小さい場合は hi を指す参照、そうでなければ v を指す参照。

[編集] 計算量

多くとも2回の比較。

[編集] 実装例

1つめのバージョン
template<class T>
constexpr const T& clamp( const T& v, const T& lo, const T& hi )
{
    return clamp( v, lo, hi, std::less<>() );
}
2つめのバージョン
template<class T, class Compare>
constexpr const T& clamp( const T& v, const T& lo, const T& hi, Compare comp )
{
    return assert( !comp(hi, lo) ),
        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 を指す参照が返されます。

浮動小数点の T に対しては、 NaN が避けられる場合にのみ動作します。

[編集]

#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


[編集] 関連項目

指定された値の小さい方を返します
(関数テンプレート) [edit]
指定された値の大きい方を返します
(関数テンプレート) [edit]