Namespaces
Variants

std::saturating_add

ja.cppreference.net より
 
 
 
 
ヘッダで定義 <numeric>
template< class T >
constexpr T saturating_add( T x, T y ) noexcept;
(C++26 以降)

飽和加算を計算しますx + y。この演算は(組み込みの 整数に対する算術演算)とは異なり、無限範囲の数学的演算であるかのように振る舞います。q をqそのような演算の結果とします。 戻り値:

  • q、もし q が型 T の値として表現可能ならば。そうでなければ、
  • 型 T の最大値または最小値のうち、qに近い方。

このオーバーロードは、T が 整数型である場合にのみオーバーロード解決に参加します。つまり、signed char, short, int, long, long long, 拡張符号付き整数型、またはそのような型の符号なしバージョンです。特に、T は (おそらく cv 修飾された) bool, char, wchar_t, char8_t, char16_t, および char32_t であってはなりません。これらの型は算術を意図していないためです。

パラメータ

x, y - 整数値

戻り値

飽和された x + y.

ノート

組み込みの整数算術演算子とは異なり、整数昇格は x および y 引数には適用されません。

異なる型の2つの引数が渡された場合、呼び出しはコンパイルに失敗します。つまり、テンプレート実引数推定に関する動作は、std::min や std::max と同じです。

最近のほとんどのハードウェアアーキテクチャは、SIMD ベクトル上での飽和演算を効率的にサポートしており、SSE2(x86向け)や NEON(ARM向け)などがあります。

機能テスト マクロ 値 標準 機能
__cpp_lib_saturation_arithmetic 202311L (C++26) 飽和演算
202603L (C++26) 飽和演算関数の改名

実装例

参照: libstdc++ (GCC), libc++ (Clang).

例

次の場所でプレビューできます: Compiler Explorer.

#include <climits>
#include <limits>
#include <numeric>

static_assert(CHAR_BIT == 8);
static_assert(UCHAR_MAX == 255);

int main()
{
    constexpr int a = std::saturating_add(3, 4); // no saturation occurs, T = int
    static_assert(a == 7);

    constexpr unsigned char b = std::saturating_add<unsigned char>(UCHAR_MAX, 4); // saturated
    static_assert(b == UCHAR_MAX);

    constexpr unsigned char c = std::saturating_add(UCHAR_MAX, 4); // not saturated, T = int
        // saturating_add(int, int) returns int tmp == 259,
        // then assignment truncates 259 % 256 == 3 (might yield int -> unsigned char warning)
    static_assert(c == 3);

//  unsigned char d = std::saturating_add(252, c); // Error: inconsistent deductions for T

    constexpr unsigned char e = std::saturating_add<unsigned char>(251, a); // saturated
    static_assert(e == UCHAR_MAX);
        // 251 is of type T = unsigned char, `a` is converted to unsigned char value;
        // might yield an int -> unsigned char conversion warning for `a`

    constexpr signed char f = std::saturating_add<signed char>(-123, -3); // not saturated
    static_assert(f == -126);

    constexpr signed char g = std::saturating_add<signed char>(-123, -13); // saturated
    static_assert(g == std::numeric_limits<signed char>::min()); // g == -128
}

関連項目

2つの整数に対する飽和減算演算
(関数テンプレート)
2つの整数に対する飽和乗算演算
(関数テンプレート)
2つの整数に対する飽和除算演算
(関数テンプレート)
整数値を別の整数型の範囲にクランプして返す
(関数テンプレート)
(C++17)
値を一対の境界値の間にクランプする
(関数テンプレート & アルゴリズム関数オブジェクト)
(C++20)
整数値が指定された整数型の範囲内にあるかどうかを調べる
(関数テンプレート)
[static]
指定された非浮動小数点型の最小有限値、または指定された浮動小数点型の最小正の正規化された値を返す
(std::numeric_limits<T> のパブリック静的メンバ関数)
[static]
指定された型の最大有限値を返す
(std::numeric_limits<T> のパブリック静的メンバ関数)

外部リンク

1.  飽和演算の分岐なし実装 — Locklessinc.com, 2012