最終更新日時: 2026年07月22日 16時08分23秒 (JST)
rotarymars が更新

履歴 編集

function
<atomic>

# std::atomic::store_sub(C++26)

    void
      store_sub(difference_type operand,
                memory_order order = memory_order_seq_cst
                ) volatile noexcept;                      // (1) C++26

    constexpr void
      store_sub(difference_type operand,
                memory_order order = memory_order_seq_cst
                ) noexcept;                               // (2) C++26

## 概要

値を読み込まずに減算を行う。

この関数は、`fetch_sub()`と異なり、現在の (古い) 値を読み込むことなく現在の値に演算を行うため、高速に動作する。ただし変更前の古い値は戻り値として取得できない。

## テンプレートパラメータ制約

- (1) : `atomic<T>::is_always_lock_free`が`true`であること

## 事前条件

- `order`は、以下のいずれかであること
  - `memory_order_relaxed`
  - `memory_order_release`
  - `memory_order_seq_cst`

## 効果

`order`で指定されたメモリオーダーにしたがって、現在の値に`operand`を減算した値でアトミックに置き換える

## 戻り値

なし

## 例外

投げない

## 備考

- この関数は、`atomic`クラスの整数型、浮動小数点数型、ポインタに対する特殊化で定義される
- 整数型
  - 符号付き整数型に対しては、符号なし整数型に変換されたかのようにしたあと演算が行われ、結果は符号付き整数型になる。未定義動作はない
- 浮動小数点数型
  - 演算結果が、その型で表現できない値であった場合、結果は未規定値になる。ただしその操作によって未定義動作は起こらない
  - 浮動小数点数型に対する操作は`std::numeric_limits<floating-point>`トレイトに準拠する
  - 浮動小数点数型に対するアトミック操作の浮動小数点環境は、呼び出しスレッドの浮動小数点環境とは異なる可能性がある
- ポインタ型
  - 結果として未定義アドレスになる場合があるが、それ以外の未定義動作はない

## 例

### 基本的な使い方

    #include <print>
    #include <atomic>

    int main()
    {
      std::atomic<int> x(3);

      x.store_sub(2);

      std::println("{}", x.load());
    }

#### 出力

    1

### 並列に減算する例

    #include <print>
    #include <atomic>
    #include <algorithm>
    #include <execution>
    #include <vector>

    int main()
    {
      std::atomic<int> x{100};
      std::vector<int> v = {1, 2, 3, 4, 5};

      std::for_each(std::execution::par_unseq, v.begin(), v.end(), [&](int n){
        x.store_sub(n);
      });

      std::println("{}", x.load());
    }

#### 出力

    85

## バージョン

### 言語

- C++26

### 処理系

- Clang: 21 ❌
- GCC: 15 ❌
- Visual C++: 2022 Update 13 ❌

## 参照

- P3111R8 Atomic Reduction Operations