[atomics.ref.generic]

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

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

### 32.5.7 Class template atomic_ref [atomics.ref.generic]

#### [32.5.7.1](#general) General [[atomics.ref.generic.general]](atomics.ref.generic.general)

[ð](#lib:atomic_ref)

namespace std {template<class T> struct atomic_ref {private: T* ptr; // *exposition only*public:using value_type = remove_cv_t<T>; 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(T&); 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 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 T* address() const noexcept; };}

[1](#general-1)

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

An atomic_ref object applies atomic operations ([[atomics.general]](atomics.general "32.5.1 General")) to
the object referenced by *ptr such that,
for the lifetime ([[basic.life]](basic.life "6.8.4 Lifetime")) of the atomic_ref object,
the object referenced by *ptr is an atomic object ([[intro.races]](intro.races "6.10.2.2 Data races"))[.](#general-1.sentence-1)

[2](#general-2)

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

The program is ill-formed if is_trivially_copyable_v<T> is false[.](#general-2.sentence-1)

[3](#general-3)

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

The lifetime ([[basic.life]](basic.life "6.8.4 Lifetime")) of an object referenced by *ptr shall exceed the lifetime of all atomic_refs that reference the object[.](#general-3.sentence-1)

While any atomic_ref instances exist
that reference the *ptr object,
all accesses to that object shall exclusively occur
through those atomic_ref instances[.](#general-3.sentence-2)

No subobject of the object referenced by atomic_ref shall be concurrently referenced by any other atomic_ref object[.](#general-3.sentence-3)

[4](#general-4)

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

Atomic operations applied to an object
through a referencing atomic_ref are atomic with respect to
atomic operations applied through any other atomic_ref referencing the same object[.](#general-4.sentence-1)

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

Atomic operations or the atomic_ref constructor can acquire
a shared resource, such as a lock associated with the referenced object,
to enable atomic operations to be applied to the referenced object[.](#general-4.sentence-2)

â *end note*]

[5](#general-5)

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

The program is ill-formed
if is_always_lock_free is false andis_volatile_v<T> is true[.](#general-5.sentence-1)

#### [32.5.7.2](#atomics.ref.ops) Operations [[atomics.ref.ops]](atomics.ref.ops)

[ð](#lib:required_alignment,atomic_ref)

`static constexpr size_t required_alignment;
`

[1](#atomics.ref.ops-1)

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

The alignment required for an object to be referenced by an atomic reference,
which is at least alignof(T)[.](#atomics.ref.ops-1.sentence-1)

[2](#atomics.ref.ops-2)

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

[*Note [1](#atomics.ref.ops-note-1)*:

Hardware could require an object
referenced by an atomic_ref to have stricter alignment ([[basic.align]](basic.align "6.8.3 Alignment"))
than other objects of type T[.](#atomics.ref.ops-2.sentence-1)

Further, whether operations on an atomic_ref are lock-free could depend on the alignment of the referenced object[.](#atomics.ref.ops-2.sentence-2)

For example, lock-free operations on std​::​complex<double> could be supported only if aligned to 2*alignof(double)[.](#atomics.ref.ops-2.sentence-3)

â *end note*]

[ð](#lib:is_always_lock_free,atomic_ref)

`static constexpr bool is_always_lock_free;
`

[3](#atomics.ref.ops-3)

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

The static data member is_always_lock_free is true if the atomic_ref type's operations are always lock-free,
and false otherwise[.](#atomics.ref.ops-3.sentence-1)

[ð](#lib:is_lock_free,atomic_ref)

`bool is_lock_free() const noexcept;
`

[4](#atomics.ref.ops-4)

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

*Returns*: true if operations on all objects of the type atomic_ref<T> are lock-free,false otherwise[.](#atomics.ref.ops-4.sentence-1)

[ð](#lib:atomic_ref,constructor)

`constexpr atomic_ref(T& obj);
`

[5](#atomics.ref.ops-5)

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

*Preconditions*: The referenced object is aligned to required_alignment[.](#atomics.ref.ops-5.sentence-1)

[6](#atomics.ref.ops-6)

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

*Postconditions*: *this references obj[.](#atomics.ref.ops-6.sentence-1)

[7](#atomics.ref.ops-7)

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

*Throws*: Nothing[.](#atomics.ref.ops-7.sentence-1)

[ð](#lib:atomic_ref,constructor_)

`constexpr atomic_ref(const atomic_ref& ref) noexcept;
`

[8](#atomics.ref.ops-8)

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

*Postconditions*: *this references the object referenced by ref[.](#atomics.ref.ops-8.sentence-1)

[ð](#lib:store,atomic_ref)

`constexpr void store(value_type desired,
                     memory_order order = memory_order::seq_cst) const noexcept;
`

[9](#atomics.ref.ops-9)

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

*Constraints*: is_const_v<T> is false[.](#atomics.ref.ops-9.sentence-1)

[10](#atomics.ref.ops-10)

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

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

[11](#atomics.ref.ops-11)

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

*Effects*: Atomically replaces the value referenced by *ptr with the value of desired[.](#atomics.ref.ops-11.sentence-1)

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

[ð](#lib:operator=,atomic_ref)

`constexpr value_type operator=(value_type desired) const noexcept;
`

[12](#atomics.ref.ops-12)

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

*Constraints*: is_const_v<T> is false[.](#atomics.ref.ops-12.sentence-1)

[13](#atomics.ref.ops-13)

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

*Effects*: Equivalent to:store(desired);return desired;

[ð](#lib:load,atomic_ref)

`constexpr value_type load(memory_order order = memory_order::seq_cst) const noexcept;
`

[14](#atomics.ref.ops-14)

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

*Preconditions*: order ismemory_order​::​relaxed,memory_order​::​acquire, ormemory_order​::​seq_cst[.](#atomics.ref.ops-14.sentence-1)

[15](#atomics.ref.ops-15)

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

*Effects*: Memory is affected according to the value of order[.](#atomics.ref.ops-15.sentence-1)

[16](#atomics.ref.ops-16)

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

*Returns*: Atomically returns the value referenced by *ptr[.](#atomics.ref.ops-16.sentence-1)

[ð](#lib:operator_type,atomic_ref)

`constexpr operator value_type() const noexcept;
`

[17](#atomics.ref.ops-17)

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

*Effects*: Equivalent to: return load();

[ð](#lib:exchange,atomic_ref)

`constexpr value_type exchange(value_type desired,
                              memory_order order = memory_order::seq_cst) const noexcept;
`

[18](#atomics.ref.ops-18)

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

*Constraints*: is_const_v<T> is false[.](#atomics.ref.ops-18.sentence-1)

[19](#atomics.ref.ops-19)

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

*Effects*: Atomically replaces the value referenced by *ptr with desired[.](#atomics.ref.ops-19.sentence-1)

Memory is affected according to the value of order[.](#atomics.ref.ops-19.sentence-2)

This operation is an atomic read-modify-write operation ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races"))[.](#atomics.ref.ops-19.sentence-3)

[20](#atomics.ref.ops-20)

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

*Returns*: Atomically returns the value referenced by *ptr immediately before the effects[.](#atomics.ref.ops-20.sentence-1)

[ð](#lib:compare_exchange_weak,atomic_ref)

`constexpr bool compare_exchange_weak(value_type& expected, value_type desired,
                           memory_order success, memory_order failure) const noexcept;

constexpr bool compare_exchange_strong(value_type& expected, value_type desired,
                             memory_order success, memory_order failure) const noexcept;

constexpr bool compare_exchange_weak(value_type& expected, value_type desired,
                           memory_order order = memory_order::seq_cst) const noexcept;

constexpr bool compare_exchange_strong(value_type& expected, value_type desired,
                             memory_order order = memory_order::seq_cst) const noexcept;
`

[21](#atomics.ref.ops-21)

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

*Constraints*: is_const_v<T> is false[.](#atomics.ref.ops-21.sentence-1)

[22](#atomics.ref.ops-22)

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

*Preconditions*: failure ismemory_order​::​relaxed,memory_order​::​acquire, ormemory_order​::​seq_cst[.](#atomics.ref.ops-22.sentence-1)

[23](#atomics.ref.ops-23)

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

*Effects*: Retrieves the value in expected[.](#atomics.ref.ops-23.sentence-1)

It then atomically compares the value representation of
the value referenced by *ptr for equality
with that previously retrieved from expected,
and if true, replaces the value referenced by *ptr with that in desired[.](#atomics.ref.ops-23.sentence-2)

If and only if the comparison is true,
memory is affected according to the value of success, and
if the comparison is false,
memory is affected according to the value of failure[.](#atomics.ref.ops-23.sentence-3)

When only one memory_order argument is supplied,
the value of success is order, and
the value of failure is order except that a value of memory_order​::​acq_rel shall be replaced by
the value memory_order​::​acquire and
a value of memory_order​::​release shall be replaced by
the value memory_order​::​relaxed[.](#atomics.ref.ops-23.sentence-4)

If and only if the comparison is false then,
after the atomic operation,
the value in expected is replaced by
the value read from the value referenced by *ptr during the atomic comparison[.](#atomics.ref.ops-23.sentence-5)

If the operation returns true,
these operations are atomic read-modify-write operations ([[intro.races]](intro.races "6.10.2.2 Data races"))
on the value referenced by *ptr[.](#atomics.ref.ops-23.sentence-6)

Otherwise, these operations are atomic load operations on that memory[.](#atomics.ref.ops-23.sentence-7)

[24](#atomics.ref.ops-24)

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

*Returns*: The result of the comparison[.](#atomics.ref.ops-24.sentence-1)

[25](#atomics.ref.ops-25)

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

*Remarks*: A weak compare-and-exchange operation may fail spuriously[.](#atomics.ref.ops-25.sentence-1)

That is, even when the contents of memory referred to
by expected and ptr are equal,
it may return false and
store back to expected the same memory contents
that were originally there[.](#atomics.ref.ops-25.sentence-2)

[*Note [2](#atomics.ref.ops-note-2)*:

This spurious failure enables implementation of compare-and-exchange
on a broader class of machines, e.g., load-locked store-conditional machines[.](#atomics.ref.ops-25.sentence-3)

A consequence of spurious failure is
that nearly all uses of weak compare-and-exchange will be in a loop[.](#atomics.ref.ops-25.sentence-4)

When a compare-and-exchange is in a loop,
the weak version will yield better performance on some platforms[.](#atomics.ref.ops-25.sentence-5)

When a weak compare-and-exchange would require a loop and
a strong one would not, the strong one is preferable[.](#atomics.ref.ops-25.sentence-6)

â *end note*]

[ð](#lib:wait,atomic_ref%3cT%3e)

`constexpr void wait(value_type old, memory_order order = memory_order::seq_cst) const noexcept;
`

[26](#atomics.ref.ops-26)

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

*Preconditions*: order ismemory_order​::​relaxed,memory_order​::​acquire, ormemory_order​::​seq_cst[.](#atomics.ref.ops-26.sentence-1)

[27](#atomics.ref.ops-27)

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

*Effects*: Repeatedly performs the following steps, in order:

- [(27.1)](#atomics.ref.ops-27.1)

  Evaluates load(order) and
 compares its value representation for equality against that of old[.](#atomics.ref.ops-27.1.sentence-1)

- [(27.2)](#atomics.ref.ops-27.2)

  If they compare unequal, returns[.](#atomics.ref.ops-27.2.sentence-1)

- [(27.3)](#atomics.ref.ops-27.3)

  Blocks until it
 is unblocked by an atomic notifying operation or is unblocked spuriously[.](#atomics.ref.ops-27.3.sentence-1)

[28](#atomics.ref.ops-28)

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

*Remarks*: This function is an atomic waiting operation ([[atomics.wait]](atomics.wait "32.5.6 Waiting and notifying"))
on atomic object *ptr[.](#atomics.ref.ops-28.sentence-1)

[ð](#lib:notify_one,atomic_ref%3cT%3e)

`constexpr void notify_one() const noexcept;
`

[29](#atomics.ref.ops-29)

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

*Constraints*: is_const_v<T> is false[.](#atomics.ref.ops-29.sentence-1)

[30](#atomics.ref.ops-30)

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

*Effects*: Unblocks the execution of at least one atomic waiting operation on *ptr that is eligible to be unblocked ([[atomics.wait]](atomics.wait "32.5.6 Waiting and notifying")) by this call,
if any such atomic waiting operations exist[.](#atomics.ref.ops-30.sentence-1)

[31](#atomics.ref.ops-31)

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

*Remarks*: This function is an atomic notifying operation ([[atomics.wait]](atomics.wait "32.5.6 Waiting and notifying"))
on atomic object *ptr[.](#atomics.ref.ops-31.sentence-1)

[ð](#lib:notify_all,atomic_ref%3cT%3e)

`constexpr void notify_all() const noexcept;
`

[32](#atomics.ref.ops-32)

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

*Constraints*: is_const_v<T> is false[.](#atomics.ref.ops-32.sentence-1)

[33](#atomics.ref.ops-33)

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

*Effects*: Unblocks the execution of all atomic waiting operations on *ptr that are eligible to be unblocked ([[atomics.wait]](atomics.wait "32.5.6 Waiting and notifying")) by this call[.](#atomics.ref.ops-33.sentence-1)

[34](#atomics.ref.ops-34)

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

*Remarks*: This function is an atomic notifying operation ([[atomics.wait]](atomics.wait "32.5.6 Waiting and notifying"))
on atomic object *ptr[.](#atomics.ref.ops-34.sentence-1)

[ð](#lib:address,atomic_ref%3cT%3e)

`constexpr T* address() const noexcept;
`

[35](#atomics.ref.ops-35)

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

*Returns*: ptr[.](#atomics.ref.ops-35.sentence-1)

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

[1](#atomics.ref.int-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[.](#atomics.ref.int-1.sentence-1)

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

[*Note [1](#atomics.ref.int-note-1)*:

The specialization atomic_ref<bool> uses the primary template ([atomics.ref.generic])[.](#atomics.ref.int-1.sentence-3)

â *end note*]

[2](#atomics.ref.int-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[.](#atomics.ref.int-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](#atomics.ref.int-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[.](#atomics.ref.int-3.sentence-1)

[4](#atomics.ref.int-4)

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

The following operations perform arithmetic computations[.](#atomics.ref.int-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")[.](#atomics.ref.int-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](#atomics.ref.int-5)

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

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

[6](#atomics.ref.int-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[.](#atomics.ref.int-6.sentence-1)

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

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

[7](#atomics.ref.int-7)

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

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

[8](#atomics.ref.int-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[.](#atomics.ref.int-8.sentence-1)

[*Note [2](#atomics.ref.int-note-2)*:

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

â *end note*]

[9](#atomics.ref.int-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[.](#atomics.ref.int-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](#atomics.ref.int-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[.](#atomics.ref.int-10.sentence-1)

[11](#atomics.ref.int-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[.](#atomics.ref.int-11.sentence-1)

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

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

[12](#atomics.ref.int-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[.](#atomics.ref.int-12.sentence-1)

[*Note [3](#atomics.ref.int-note-3)*:

There are no undefined results arising from the computation[.](#atomics.ref.int-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[.](#atomics.ref.int-12.sentence-3)

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

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

[13](#atomics.ref.int-13)

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

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

[14](#atomics.ref.int-14)

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

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

#### [32.5.7.4](#atomics.ref.float) Specializations for floating-point types [[atomics.ref.float]](atomics.ref.float)

[1](#atomics.ref.float-1)

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

There are specializations of the atomic_ref class template
for all floating-point types[.](#atomics.ref.float-1.sentence-1)

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

[2](#atomics.ref.float-2)

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

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

namespace std {template<> struct atomic_ref<*floating-point-type*> {private:*floating-point-type** ptr; // *exposition only*public:using value_type = remove_cv_t<*floating-point-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(*floating-point-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_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 value_type fetch_fmaximum(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_fminimum(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_fmaximum_num(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_fminimum_num(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_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 void store_fmaximum(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr void store_fminimum(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr void store_fmaximum_num(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr void store_fminimum_num(value_type,
 memory_order = memory_order::seq_cst) 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 *floating-point-type** address() const noexcept; };}

[3](#atomics.ref.float-3)

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

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

[4](#atomics.ref.float-4)

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

The following operations perform arithmetic computations[.](#atomics.ref.float-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"),
except for the keysmax,min,fmaximum,fminimum,fmaximum_num, andfminimum_num,
which are specified below[.](#atomics.ref.float-4.sentence-2)

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

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

[5](#atomics.ref.float-5)

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

*Constraints*: is_const_v<*floating-point-type*> is false[.](#atomics.ref.float-5.sentence-1)

[6](#atomics.ref.float-6)

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

*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[.](#atomics.ref.float-6.sentence-1)

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

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

[7](#atomics.ref.float-7)

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

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

[8](#atomics.ref.float-8)

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

*Remarks*: If the result is not a representable value for its type ([[expr.pre]](expr.pre "7.1 Preamble")),
the result is unspecified,
but the operations otherwise have no undefined behavior[.](#atomics.ref.float-8.sentence-1)

Atomic arithmetic operations on *floating-point-type* should conform to
the std​::​numeric_limits<value_type> traits
associated with the floating-point type ([[limits.syn]](limits.syn "17.3.3 Header <limits> synopsis"))[.](#atomics.ref.float-8.sentence-2)

The floating-point environment ([[cfenv]](cfenv "29.3 The floating-point environment"))
for atomic arithmetic operations on *floating-​point-type* may be different than the calling thread's floating-point environment[.](#atomics.ref.float-8.sentence-3)

[9](#atomics.ref.float-9)

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

- [(9.1)](#atomics.ref.float-9.1)

  For fetch_fmaximum and fetch_fminimum,
the maximum and minimum computation is performed
as if by fmaximum and fminimum, respectively,
with *ptr and the first parameter as the arguments[.](#atomics.ref.float-9.1.sentence-1)

- [(9.2)](#atomics.ref.float-9.2)

  For fetch_fmaximum_num and fetch_fminimum_num,
the maximum and minimum computation is performed
as if by fmaximum_num and fminimum_num, respectively,
with *ptr and the first parameter as the arguments[.](#atomics.ref.float-9.2.sentence-1)

- [(9.3)](#atomics.ref.float-9.3)

  For fetch_max and fetch_min,
the maximum and minimum computation is performed
as if by fmaximum_num and fminimum_num, respectively,
with *ptr and the first parameter as the arguments, except that:
  * [(9.3.1)](#atomics.ref.float-9.3.1)

      If both arguments are NaN, an unspecified NaN value is stored at *ptr[.](#atomics.ref.float-9.3.1.sentence-1)

  * [(9.3.2)](#atomics.ref.float-9.3.2)

      If exactly one argument is a NaN,
either the other argument or an unspecified NaN value is stored at *ptr;
it is unspecified which[.](#atomics.ref.float-9.3.2.sentence-1)

  * [(9.3.3)](#atomics.ref.float-9.3.3)

      If the arguments are differently signed zeros,
which of these values is stored at *ptr is unspecified[.](#atomics.ref.float-9.3.3.sentence-1)

[10](#atomics.ref.float-10)

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

*Recommended practice*: The implementation of fetch_max and fetch_min should treat negative zero as smaller than positive zero[.](#atomics.ref.float-10.sentence-1)

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

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

[11](#atomics.ref.float-11)

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

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

[12](#atomics.ref.float-12)

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

*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[.](#atomics.ref.float-12.sentence-1)

Memory is affected according to the value of order[.](#atomics.ref.float-12.sentence-2)

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

[13](#atomics.ref.float-13)

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

*Remarks*: If the result is not a representable value for its type ([[expr.pre]](expr.pre "7.1 Preamble")),
the result is unspecified,
but the operations otherwise have no undefined behavior[.](#atomics.ref.float-13.sentence-1)

Atomic arithmetic operations on *floating-point-type* should conform to the numeric_limits<*floating-point-type*> traits associated with the floating-point type ([[limits.syn]](limits.syn "17.3.3 Header <limits> synopsis"))[.](#atomics.ref.float-13.sentence-2)

The floating-point environment ([[cfenv]](cfenv "29.3 The floating-point environment"))
for atomic arithmetic operations on *floating-point-type* may be different than the calling thread's floating-point environment[.](#atomics.ref.float-13.sentence-3)

The arithmetic rules of floating-point atomic modify-write operations
may be different from operations on floating-point types or
atomic floating-point types[.](#atomics.ref.float-13.sentence-4)

[*Note [1](#atomics.ref.float-note-1)*:

Tree reductions are permitted for atomic modify-write operations[.](#atomics.ref.float-13.sentence-5)

â *end note*]

[14](#atomics.ref.float-14)

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

- [(14.1)](#atomics.ref.float-14.1)

  For store_fmaximum and store_fminimum,
the maximum and minimum computation is performed
as if by fmaximum and fminimum, respectively,
with *ptr and the first parameter as the arguments[.](#atomics.ref.float-14.1.sentence-1)

- [(14.2)](#atomics.ref.float-14.2)

  For store_fmaximum_num and store_fminimum_num,
the maximum and minimum computation is performed
as if by fmaximum_num and fminimum_num, respectively,
with *ptr and the first parameter as the arguments[.](#atomics.ref.float-14.2.sentence-1)

- [(14.3)](#atomics.ref.float-14.3)

  For store_max and store_min,
the maximum and minimum computation is performed
as if by fmaximum_num and fminimum_num, respectively,
with *ptr and the first parameter as the arguments, except that:
  * [(14.3.1)](#atomics.ref.float-14.3.1)

      If both arguments are NaN, an unspecified NaN value is stored at *ptr[.](#atomics.ref.float-14.3.1.sentence-1)

  * [(14.3.2)](#atomics.ref.float-14.3.2)

      If exactly one argument is a NaN,
either the other argument or an unspecified NaN value is stored at *ptr,
it is unspecified which[.](#atomics.ref.float-14.3.2.sentence-1)

  * [(14.3.3)](#atomics.ref.float-14.3.3)

      If the arguments are differently signed zeros,
which of these values is stored at *ptr is unspecified[.](#atomics.ref.float-14.3.3.sentence-1)

[15](#atomics.ref.float-15)

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

*Recommended practice*: The implementation of store_max and store_min should treat negative zero as smaller than positive zero[.](#atomics.ref.float-15.sentence-1)

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

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

[16](#atomics.ref.float-16)

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

*Constraints*: is_const_v<*floating-point-type*> is false[.](#atomics.ref.float-16.sentence-1)

[17](#atomics.ref.float-17)

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

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

#### [32.5.7.5](#atomics.ref.pointer) Specialization for pointers [[atomics.ref.pointer]](atomics.ref.pointer)

[1](#atomics.ref.pointer-1)

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

There are specializations of the atomic_ref class template
for all pointer-to-object types[.](#atomics.ref.pointer-1.sentence-1)

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

[2](#atomics.ref.pointer-2)

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

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

namespace std {template<> struct atomic_ref<*pointer-type*> {private:*pointer-type** ptr; // *exposition only*public:using value_type = remove_cv_t<*pointer-type*>; using difference_type = ptrdiff_t; 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(*pointer-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(difference_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_sub(difference_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(difference_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr void store_sub(difference_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+=(difference_type) const noexcept; constexpr value_type operator-=(difference_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 *pointer-type** address() const noexcept; };}

[3](#atomics.ref.pointer-3)

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

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

[4](#atomics.ref.pointer-4)

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

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

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

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

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

[5](#atomics.ref.pointer-5)

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

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

[6](#atomics.ref.pointer-6)

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

*Mandates*: remove_pointer_t<*pointer-type*> is a complete object type[.](#atomics.ref.pointer-6.sentence-1)

[7](#atomics.ref.pointer-7)

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

*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[.](#atomics.ref.pointer-7.sentence-1)

Memory is affected according to the value of order[.](#atomics.ref.pointer-7.sentence-2)

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

[8](#atomics.ref.pointer-8)

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

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

[9](#atomics.ref.pointer-9)

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

*Remarks*: The result may be an undefined address,
but the operations otherwise have no undefined behavior[.](#atomics.ref.pointer-9.sentence-1)

[10](#atomics.ref.pointer-10)

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

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[.](#atomics.ref.pointer-10.sentence-1)

[*Note [1](#atomics.ref.pointer-note-1)*:

If the pointers point to different complete objects (or subobjects thereof),
the < operator does not establish a strict weak ordering
(Table [29](utility.arg.requirements#tab:cpp17.lessthancomparable "Table 29: Cpp17LessThanComparable requirements"), [[expr.rel]](expr.rel "7.6.9 Relational operators"))[.](#atomics.ref.pointer-10.sentence-2)

â *end note*]

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

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

[11](#atomics.ref.pointer-11)

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

*Mandates*: T is a complete object type[.](#atomics.ref.pointer-11.sentence-1)

[12](#atomics.ref.pointer-12)

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

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

[13](#atomics.ref.pointer-13)

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

*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[.](#atomics.ref.pointer-13.sentence-1)

Memory is affected according to the value of order[.](#atomics.ref.pointer-13.sentence-2)

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

[14](#atomics.ref.pointer-14)

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

*Remarks*: The result may be an undefined address,
but the operations otherwise have no undefined behavior[.](#atomics.ref.pointer-14.sentence-1)

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[.](#atomics.ref.pointer-14.sentence-2)

[*Note [2](#atomics.ref.pointer-note-2)*:

If the pointers point to different complete objects (or subobjects thereof),
the < operator does not establish
a strict weak ordering (Table [29](utility.arg.requirements#tab:cpp17.lessthancomparable "Table 29: Cpp17LessThanComparable requirements"), [[expr.rel]](expr.rel "7.6.9 Relational operators"))[.](#atomics.ref.pointer-14.sentence-3)

â *end note*]

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

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

[15](#atomics.ref.pointer-15)

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

*Constraints*: is_const_v<*pointer-type*> is false[.](#atomics.ref.pointer-15.sentence-1)

[16](#atomics.ref.pointer-16)

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

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

#### [32.5.7.6](#atomics.ref.memop) Member operators
 common to integers and pointers to objects [[atomics.ref.memop]](atomics.ref.memop)

[1](#atomics.ref.memop-1)

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

Let *referred-type* be *pointer-type* for the specializations in [[atomics.ref.pointer]](#atomics.ref.pointer "32.5.7.5 Specialization for pointers") and
be *integral-type* for the specializations in [[atomics.ref.int]](#atomics.ref.int "32.5.7.3 Specializations for integral types")[.](#atomics.ref.memop-1.sentence-1)

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

`constexpr value_type operator++(int) const noexcept;
`

[2](#atomics.ref.memop-2)

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

*Constraints*: is_const_v<*referred-type*> is false[.](#atomics.ref.memop-2.sentence-1)

[3](#atomics.ref.memop-3)

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

*Effects*: Equivalent to: return fetch_add(1);

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

`constexpr value_type operator--(int) const noexcept;
`

[4](#atomics.ref.memop-4)

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

*Constraints*: is_const_v<*referred-type*> is false[.](#atomics.ref.memop-4.sentence-1)

[5](#atomics.ref.memop-5)

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

*Effects*: Equivalent to: return fetch_sub(1);

[ð](#lib:operator++,atomic_ref%3cpointer-type%3e_)

`constexpr value_type operator++() const noexcept;
`

[6](#atomics.ref.memop-6)

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

*Constraints*: is_const_v<*referred-type*> is false[.](#atomics.ref.memop-6.sentence-1)

[7](#atomics.ref.memop-7)

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

*Effects*: Equivalent to: return fetch_add(1) + 1;

[ð](#lib:operator--,atomic_ref%3cpointer-type%3e_)

`constexpr value_type operator--() const noexcept;
`

[8](#atomics.ref.memop-8)

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

*Constraints*: is_const_v<*referred-type*> is false[.](#atomics.ref.memop-8.sentence-1)

[9](#atomics.ref.memop-9)

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

*Effects*: Equivalent to: return fetch_sub(1) - 1;
