[atomics.ref.int]

# 32 Concurrency support library [[thread]](./#thread)

## 32.5 Atomic operations [[atomics]](atomics#ref.int)

### 32.5.7 Class template atomic_ref [[atomics.ref.generic]](atomics.ref.generic#atomics.ref.int)

#### 32.5.7.3 Specializations for integral types [atomics.ref.int]

[1](#1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3662)

There are specializations of the atomic_ref class template
for all integral types except cv bool[.](#1.sentence-1)

For each such type *integral-type*,
the specialization atomic_ref<*integral-type*> provides
additional atomic operations appropriate to integral types[.](#1.sentence-2)

[*Note [1](#note-1)*:

The specialization atomic_ref<bool> uses the primary template ([[atomics.ref.generic]](atomics.ref.generic "32.5.7 Class template atomic_­ref"))[.](#1.sentence-3)

â *end note*]

[2](#2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3674)

The program is ill-formed
if is_always_lock_free is false andis_volatile_v<*integral-type*> is true[.](#2.sentence-1)

namespace std {template<> struct atomic_ref<*integral-type*> {private:*integral-type** ptr; // *exposition only*public:using value_type = remove_cv_t<*integral-type*>; using difference_type = value_type; static constexpr size_t required_alignment = *implementation-defined*; static constexpr bool is_always_lock_free = *implementation-defined*; bool is_lock_free() const noexcept; constexpr explicit atomic_ref(*integral-type*&); constexpr atomic_ref(const atomic_ref&) noexcept;
 atomic_ref& operator=(const atomic_ref&) = delete; constexpr void store(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type operator=(value_type) const noexcept; constexpr value_type load(memory_order = memory_order::seq_cst) const noexcept; constexpr operator value_type() const noexcept; constexpr value_type exchange(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr bool compare_exchange_weak(value_type&, value_type,
 memory_order, memory_order) const noexcept; constexpr bool compare_exchange_strong(value_type&, value_type,
 memory_order, memory_order) const noexcept; constexpr bool compare_exchange_weak(value_type&, value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr bool compare_exchange_strong(value_type&, value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_add(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_sub(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_and(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_or(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_xor(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_max(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_min(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr void store_add(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr void store_sub(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr void store_and(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr void store_or(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr void store_xor(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr void store_max(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr void store_min(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr value_type operator++(int) const noexcept; constexpr value_type operator--(int) const noexcept; constexpr value_type operator++() const noexcept; constexpr value_type operator--() const noexcept; constexpr value_type operator+=(value_type) const noexcept; constexpr value_type operator-=(value_type) const noexcept; constexpr value_type operator&=(value_type) const noexcept; constexpr value_type operator|=(value_type) const noexcept; constexpr value_type operator^=(value_type) const noexcept; constexpr void wait(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void notify_one() const noexcept; constexpr void notify_all() const noexcept; constexpr *integral-type** address() const noexcept; };}

[3](#3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3761)

Descriptions are provided below only for members
that differ from the primary template[.](#3.sentence-1)

[4](#4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3765)

The following operations perform arithmetic computations[.](#4.sentence-1)

The correspondence among key, operator, and computation is specified
in Table [155](atomics.types.int#tab:atomic.types.int.comp "Table 155: Atomic arithmetic computations")[.](#4.sentence-2)

[ð](#lib:fetch_add,atomic_ref%3cintegral-type%3e)

`constexpr value_type fetch_key(value_type operand,
  memory_order order = memory_order::seq_cst) const noexcept;
`

[5](#5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3783)

*Constraints*: is_const_v<*integral-type*> is false[.](#5.sentence-1)

[6](#6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3787)

*Effects*: Atomically replaces the value referenced by *ptr with
the result of the computation applied to the value referenced by *ptr and the given operand[.](#6.sentence-1)

Memory is affected according to the value of order[.](#6.sentence-2)

These operations are atomic read-modify-write operations ([[intro.races]](intro.races "6.10.2.2 Data races"))[.](#6.sentence-3)

[7](#7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3795)

*Returns*: Atomically, the value referenced by *ptr immediately before the effects[.](#7.sentence-1)

[8](#8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3800)

*Remarks*: Except for fetch_max and fetch_min, for signed integer types
the result is as if the object value and parameters
were converted to their corresponding unsigned types,
the computation performed on those types, and
the result converted back to the signed type[.](#8.sentence-1)

[*Note [2](#note-2)*:

There are no undefined results arising from the computation[.](#8.sentence-2)

â *end note*]

[9](#9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3812)

For fetch_max and fetch_min, the maximum and minimum
computation is performed as if by max and min algorithms ([[alg.min.max]](alg.min.max "26.8.9 Minimum and maximum")), respectively,
with the object value and the first parameter as the arguments[.](#9.sentence-1)

[ð](#lib:store_add,atomic_ref%3cintegral-type%3e)

`constexpr void store_key(value_type operand,
                         memory_order order = memory_order::seq_cst) const noexcept;
`

[10](#10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3831)

*Preconditions*: order is memory_order​::​relaxed,memory_order​::​release, ormemory_order​::​seq_cst[.](#10.sentence-1)

[11](#11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3837)

*Effects*: Atomically replaces the value referenced by *ptr with the result of the computation applied to
the value referenced by *ptr and the given operand[.](#11.sentence-1)

Memory is affected according to the value of order[.](#11.sentence-2)

These operations are atomic modify-write operations ([[atomics.order]](atomics.order "32.5.4 Order and consistency"))[.](#11.sentence-3)

[12](#12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3845)

*Remarks*: Except for store_max and store_min,
for signed integer types,
the result is as if *ptr and parameters
were converted to their corresponding unsigned types,
the computation performed on those types, and
the result converted back to the signed type[.](#12.sentence-1)

[*Note [3](#note-3)*:

There are no undefined results arising from the computation[.](#12.sentence-2)

â *end note*]

For store_max and store_min,
the maximum and minimum computation is performed
as if by max and min algorithms ([[alg.min.max]](alg.min.max "26.8.9 Minimum and maximum")), respectively,
with *ptr and the first parameter as the arguments[.](#12.sentence-3)

[ð](#lib:operator+=,atomic_ref%3cintegral-type%3e)

`constexpr value_type operator op=(value_type operand) const noexcept;
`

[13](#13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3872)

*Constraints*: is_const_v<*integral-type*> is false[.](#13.sentence-1)

[14](#14)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3876)

*Effects*: Equivalent to:return fetch_*key*(operand) *op* operand;
