diff --git a/source/threads.tex b/source/threads.tex index 721e02a387..9f2e6d3da4 100644 --- a/source/threads.tex +++ b/source/threads.tex @@ -3126,7 +3126,7 @@ T* ptr; // \expos public: - using value_type = T; + using value_type = remove_cv_t; static constexpr size_t required_alignment = @\impdefx{required alignment for \tcode{atomic_ref} type's operations}@; static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic_ref} type's operations are always lock free}@; @@ -3136,22 +3136,22 @@ atomic_ref(const atomic_ref&) noexcept; atomic_ref& operator=(const atomic_ref&) = delete; - void store(T, memory_order = memory_order::seq_cst) const noexcept; - T operator=(T) const noexcept; - T load(memory_order = memory_order::seq_cst) const noexcept; - operator T() const noexcept; + void store(value_type, memory_order = memory_order::seq_cst) const noexcept; + value_type operator=(value_type) const noexcept; + value_type load(memory_order = memory_order::seq_cst) const noexcept; + operator value_type() const noexcept; - T exchange(T, memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_weak(T&, T, + value_type exchange(value_type, memory_order = memory_order::seq_cst) const noexcept; + bool compare_exchange_weak(value_type&, value_type, memory_order, memory_order) const noexcept; - bool compare_exchange_strong(T&, T, + bool compare_exchange_strong(value_type&, value_type, memory_order, memory_order) const noexcept; - bool compare_exchange_weak(T&, T, + bool compare_exchange_weak(value_type&, value_type, memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_strong(T&, T, + bool compare_exchange_strong(value_type&, value_type, memory_order = memory_order::seq_cst) const noexcept; - void wait(T, memory_order = memory_order::seq_cst) const noexcept; + void wait(value_type, memory_order = memory_order::seq_cst) const noexcept; void notify_one() const noexcept; void notify_all() const noexcept; constexpr T* address() const noexcept; @@ -3189,6 +3189,11 @@ to enable atomic operations to be applied to the referenced object. \end{note} +\pnum +The program is ill-formed +if \tcode{is_always_lock_free} is \tcode{false} and +\tcode{is_volatile_v} is \tcode{true}. + \rSec3[atomics.ref.ops]{Operations} \indexlibrarymember{required_alignment}{atomic_ref}% @@ -3289,10 +3294,14 @@ \indexlibrarymember{store}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{store}{atomic_ref<\placeholder{floating-point-type}>}% \begin{itemdecl} -void store(T desired, memory_order order = memory_order::seq_cst) const noexcept; +void store(value_type desired, memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v} is \tcode{false}. + \pnum \expects \tcode{order} is @@ -3312,10 +3321,14 @@ \indexlibrarymember{operator=}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{operator=}{atomic_ref<\placeholder{floating-point-type}>}% \begin{itemdecl} -T operator=(T desired) const noexcept; +value_type operator=(value_type desired) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v} is \tcode{false}. + \pnum \effects Equivalent to: @@ -3330,7 +3343,7 @@ \indexlibrarymember{load}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{load}{atomic_ref<\placeholder{floating-point-type}>}% \begin{itemdecl} -T load(memory_order order = memory_order::seq_cst) const noexcept; +value_type load(memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -3356,7 +3369,7 @@ \indexlibrarymember{operator \placeholder{integral-type}}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{operator \placeholder{floating-point-type}}{atomic_ref<\placeholder{floating-point-type}>}% \begin{itemdecl} -operator T() const noexcept; +operator value_type() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -3370,10 +3383,14 @@ \indexlibrarymember{exchange}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{exchange}{atomic_ref<\placeholder{floating-point-type}>}% \begin{itemdecl} -T exchange(T desired, memory_order order = memory_order::seq_cst) const noexcept; +value_type exchange(value_type desired, memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v} is \tcode{false}. + \pnum \effects Atomically replaces the value referenced by \tcode{*ptr} @@ -3396,20 +3413,24 @@ \indexlibrarymember{compare_exchange_strong}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{compare_exchange_strong}{atomic_ref<\placeholder{floating-point-type}>}% \begin{itemdecl} -bool compare_exchange_weak(T& expected, T desired, +bool compare_exchange_weak(value_type& expected, value_type desired, memory_order success, memory_order failure) const noexcept; -bool compare_exchange_strong(T& expected, T desired, +bool compare_exchange_strong(value_type& expected, value_type desired, memory_order success, memory_order failure) const noexcept; -bool compare_exchange_weak(T& expected, T desired, +bool compare_exchange_weak(value_type& expected, value_type desired, memory_order order = memory_order::seq_cst) const noexcept; -bool compare_exchange_strong(T& expected, T desired, +bool compare_exchange_strong(value_type& expected, value_type desired, memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v} is \tcode{false}. + \pnum \expects \tcode{failure} is @@ -3473,7 +3494,7 @@ \indexlibrarymember{wait}{atomic_ref}% \begin{itemdecl} -void wait(T old, memory_order order = memory_order::seq_cst) const noexcept; +void wait(value_type old, memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} @@ -3511,6 +3532,10 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v} is \tcode{false}. + \pnum \effects Unblocks the execution of at least one atomic waiting operation on \tcode{*ptr} @@ -3529,6 +3554,10 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v} is \tcode{false}. + \pnum \effects Unblocks the execution of all atomic waiting operations on \tcode{*ptr} @@ -3536,8 +3565,8 @@ \pnum \remarks - This function is an atomic notifying operation\iref{atomics.wait} - on atomic object \tcode{*ptr}. +This function is an atomic notifying operation\iref{atomics.wait} +on atomic object \tcode{*ptr}. \end{itemdescr} \indexlibrarymember{address}{atomic_ref}% @@ -3556,23 +3585,7 @@ \pnum \indexlibrary{\idxcode{atomic_ref<\placeholder{integral-type}>}}% There are specializations of the \tcode{atomic_ref} class template -for the integral types -\tcode{char}, -\tcode{signed char}, -\tcode{unsigned char}, -\tcode{short}, -\tcode{unsigned short}, -\tcode{int}, -\tcode{unsigned int}, -\tcode{long}, -\tcode{unsigned long}, -\tcode{long long}, -\tcode{unsigned long long}, -\keyword{char8_t}, -\keyword{char16_t}, -\keyword{char32_t}, -\keyword{wchar_t}, -and any other types needed by the typedefs in the header \libheaderref{cstdint}. +for all integral types except \cv{} \tcode{bool}. For each such type \tcode{\placeholder{integral-type}}, the specialization \tcode{atomic_ref<\placeholder{integral-type}>} provides additional atomic operations appropriate to integral types. @@ -3581,6 +3594,11 @@ uses the primary template\iref{atomics.ref.generic}. \end{note} +\pnum +The program is ill-formed +if \tcode{is_always_lock_free} is \tcode{false} and +\tcode{is_volatile_v} is true. + \begin{codeblock} namespace std { template<> struct atomic_ref<@\placeholder{integral-type}@> { @@ -3588,7 +3606,7 @@ @\placeholder{integral-type}@* ptr; // \expos public: - using value_type = @\placeholder{integral-type}@; + using value_type = remove_cv_t<@\placeholder{integral-type}@>; using difference_type = value_type; static constexpr size_t required_alignment = @\impdefx{required alignment for \tcode{atomic_ref} type's operations}@; @@ -3599,48 +3617,41 @@ atomic_ref(const atomic_ref&) noexcept; atomic_ref& operator=(const atomic_ref&) = delete; - void store(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral-type}@ operator=(@\placeholder{integral-type}@) const noexcept; - @\placeholdernc{integral-type}@ load(memory_order = memory_order::seq_cst) const noexcept; - operator @\placeholdernc{integral-type}@() const noexcept; + void store(value_type, memory_order = memory_order::seq_cst) const noexcept; + value_type operator=(value_type) const noexcept; + value_type load(memory_order = memory_order::seq_cst) const noexcept; + operator value_type() const noexcept; - @\placeholdernc{integral-type}@ exchange(@\placeholdernc{integral-type}@, + value_type exchange(value_type, memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_weak(@\placeholder{integral-type}@&, @\placeholder{integral-type}@, + bool compare_exchange_weak(value_type&, value_type, memory_order, memory_order) const noexcept; - bool compare_exchange_strong(@\placeholder{integral-type}@&, @\placeholder{integral-type}@, + bool compare_exchange_strong(value_type&, value_type, memory_order, memory_order) const noexcept; - bool compare_exchange_weak(@\placeholder{integral-type}@&, @\placeholder{integral-type}@, + bool compare_exchange_weak(value_type&, value_type, memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_strong(@\placeholder{integral-type}@&, @\placeholder{integral-type}@, + bool compare_exchange_strong(value_type&, value_type, memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral-type}@ fetch_add(@\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral-type}@ fetch_sub(@\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral-type}@ fetch_and(@\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral-type}@ fetch_or(@\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral-type}@ fetch_xor(@\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral-type}@ fetch_max(@\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) const noexcept; - @\placeholdernc{integral-type}@ fetch_min(@\placeholdernc{integral-type}@, - memory_order = memory_order::seq_cst) const noexcept; - - @\placeholdernc{integral-type}@ operator++(int) const noexcept; - @\placeholdernc{integral-type}@ operator--(int) const noexcept; - @\placeholdernc{integral-type}@ operator++() const noexcept; - @\placeholdernc{integral-type}@ operator--() const noexcept; - @\placeholdernc{integral-type}@ operator+=(@\placeholdernc{integral-type}@) const noexcept; - @\placeholdernc{integral-type}@ operator-=(@\placeholdernc{integral-type}@) const noexcept; - @\placeholdernc{integral-type}@ operator&=(@\placeholdernc{integral-type}@) const noexcept; - @\placeholdernc{integral-type}@ operator|=(@\placeholdernc{integral-type}@) const noexcept; - @\placeholdernc{integral-type}@ operator^=(@\placeholdernc{integral-type}@) const noexcept; - - void wait(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) const noexcept; + value_type fetch_add(value_type, memory_order = memory_order::seq_cst) const noexcept; + value_type fetch_sub(value_type, memory_order = memory_order::seq_cst) const noexcept; + value_type fetch_and(value_type, memory_order = memory_order::seq_cst) const noexcept; + value_type fetch_or(value_type, memory_order = memory_order::seq_cst) const noexcept; + value_type fetch_xor(value_type, memory_order = memory_order::seq_cst) const noexcept; + value_type fetch_max(value_type, memory_order = memory_order::seq_cst) const noexcept; + value_type fetch_min(value_type, memory_order = memory_order::seq_cst) const noexcept; + + value_type operator++(int) const noexcept; + value_type operator--(int) const noexcept; + value_type operator++() const noexcept; + value_type operator--() const noexcept; + value_type operator+=(value_type) const noexcept; + value_type operator-=(value_type) const noexcept; + value_type operator&=(value_type) const noexcept; + value_type operator|=(value_type) const noexcept; + value_type operator^=(value_type) const noexcept; + + void wait(value_type, memory_order = memory_order::seq_cst) const noexcept; void notify_one() const noexcept; void notify_all() const noexcept; constexpr @\placeholder{integral-type}@* address() const noexcept; @@ -3665,11 +3676,15 @@ \indexlibrarymember{fetch_sub}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{fetch_xor}{atomic_ref<\placeholder{integral-type}>}% \begin{itemdecl} -@\placeholdernc{integral-type}@ fetch_@\placeholdernc{key}@(@\placeholdernc{integral-type}@ operand, +value_type fetch_@\placeholdernc{key}@(value_type operand, memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{integral-type}>} is \tcode{false}. + \pnum \effects Atomically replaces the value referenced by \tcode{*ptr} with @@ -3708,10 +3723,14 @@ \indexlibrarymember{operator"|=}{atomic_ref<\placeholder{integral-type}>}% \indexlibrarymember{operator\caret=}{atomic_ref<\placeholder{integral-type}>}% \begin{itemdecl} -@\placeholdernc{integral-type}@ operator @\placeholder{op}@=(@\placeholdernc{integral-type}@ operand) const noexcept; +value_type operator @\placeholder{op}@=(value_type operand) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{integral-type}>} is \tcode{false}. + \pnum \effects Equivalent to: @@ -3723,11 +3742,16 @@ \pnum \indexlibrary{\idxcode{atomic_ref<\placeholder{floating-point-type}>}}% There are specializations of the \tcode{atomic_ref} class template -for all cv-unqualified floating-point types. +for all floating-point types. For each such type \tcode{\placeholder{floating-point-type}}, the specialization \tcode{atomic_ref<\placeholder{floating-\-point}>} provides additional atomic operations appropriate to floating-point types. +\pnum +The program is ill-formed +\tcode{if is_always_lock_free} is \tcode{false} and +\tcode{is_volatile_v} is \tcode{true}. + \begin{codeblock} namespace std { template<> struct atomic_ref<@\placeholder{floating-point-type}@> { @@ -3735,7 +3759,7 @@ @\placeholder{floating-point-type}@* ptr; // \expos public: - using value_type = @\placeholder{floating-point-type}@; + using value_type = remove_cv_t<@\placeholder{floating-point-type}@>; using difference_type = value_type; static constexpr size_t required_alignment = @\impdefx{required alignment for \tcode{atomic_ref} type's operations}@; @@ -3747,28 +3771,28 @@ atomic_ref& operator=(const atomic_ref&) = delete; void store(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) const noexcept; - @\placeholder{floating-point-type}@ operator=(@\placeholder{floating-point-type}@) const noexcept; - @\placeholder{floating-point-type}@ load(memory_order = memory_order::seq_cst) const noexcept; + value_type operator=(value_type) const noexcept; + value_type load(memory_order = memory_order::seq_cst) const noexcept; operator @\placeholdernc{floating-point-type}@() const noexcept; - @\placeholder{floating-point-type}@ exchange(@\placeholdernc{floating-point-type}@, + value_type exchange(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_weak(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, + bool compare_exchange_weak(value_type&, @\placeholdernc{floating-point-type}@, memory_order, memory_order) const noexcept; - bool compare_exchange_strong(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, + bool compare_exchange_strong(value_type&, @\placeholdernc{floating-point-type}@, memory_order, memory_order) const noexcept; - bool compare_exchange_weak(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, + bool compare_exchange_weak(value_type&, @\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_strong(@\placeholder{floating-point-type}@&, @\placeholdernc{floating-point-type}@, + bool compare_exchange_strong(value_type&, @\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) const noexcept; - @\placeholder{floating-point-type}@ fetch_add(@\placeholdernc{floating-point-type}@, + value_type fetch_add(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) const noexcept; - @\placeholder{floating-point-type}@ fetch_sub(@\placeholdernc{floating-point-type}@, + value_type fetch_sub(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) const noexcept; - @\placeholder{floating-point-type}@ operator+=(@\placeholder{floating-point-type}@) const noexcept; - @\placeholder{floating-point-type}@ operator-=(@\placeholder{floating-point-type}@) const noexcept; + value_type operator+=(value_type) const noexcept; + value_type operator-=(value_type) const noexcept; void wait(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) const noexcept; void notify_one() const noexcept; @@ -3790,11 +3814,15 @@ \indexlibrarymember{fetch_add}{atomic_ref<\placeholder{floating-point-type}>}% \indexlibrarymember{fetch_sub}{atomic_ref<\placeholder{floating-point-type}>}% \begin{itemdecl} -@\placeholder{floating-point-type}@ fetch_@\placeholdernc{key}@(@\placeholder{floating-point-type}@ operand, +value_type fetch_@\placeholdernc{key}@(value_type operand, memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\exposid{floating-point-type}>} is \tcode{false}. + \pnum \effects Atomically replaces the value referenced by \tcode{*ptr} with @@ -3814,20 +3842,24 @@ the result is unspecified, but the operations otherwise have no undefined behavior. Atomic arithmetic operations on \tcode{\placeholder{floating-point-type}} should conform to -the \tcode{std::numeric_limits<\placeholder{floating-point-type}>} traits +the \tcode{std::numeric_limits} traits associated with the floating-point type\iref{limits.syn}. The floating-point environment\iref{cfenv} -for atomic arithmetic operations on \tcode{\placeholder{floating-point-type}} +for atomic arithmetic operations on \tcode{\placeholder{floating-\newline point-type}} may be different than the calling thread's floating-point environment. \end{itemdescr} \indexlibrarymember{operator+=}{atomic_ref<\placeholder{floating-point-type}>}% \indexlibrarymember{operator-=}{atomic_ref<\placeholder{floating-point-type}>}% \begin{itemdecl} -@\placeholder{floating-point-type}@ operator @\placeholder{op}@=(@\placeholder{floating-point-type}@ operand) const noexcept; +value_type operator @\placeholder{op}@=(value_type operand) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\exposid{floating-point-type}>} is \tcode{false}. + \pnum \effects Equivalent to: @@ -3837,52 +3869,64 @@ \rSec3[atomics.ref.pointer]{Partial specialization for pointers} \indexlibraryglobal{atomic_ref}% +\pnum +There are specializations of the \tcode{atomic_ref} class template +for all pointer-to-object types. +For each such type \placeholder{pointer-type}, +the specialization \tcode{atomic_ref<\placeholder{pointer-type}>} provides +additional atomic operations appropriate to pointer types. + +\pnum +The program is ill-formed +if \tcode{is_always_lock_free} is \tcode{false} and +\tcode{is_volatile_v} is \tcode{true}. + \begin{codeblock} namespace std { - template struct atomic_ref { + template struct atomic_ref<@\placeholder{pointer-type}@> { private: - T** ptr; // \expos + @\placeholder{pointer-type}@* ptr; // \expos public: - using value_type = T*; + using value_type = remove_cv_t<@\placeholder{pointer-type}@>; using difference_type = ptrdiff_t; static constexpr size_t required_alignment = @\impdefx{required alignment for \tcode{atomic_ref} type's operations}@; static constexpr bool is_always_lock_free = @\impdefx{whether a given \tcode{atomic_ref} type's operations are always lock free}@; bool is_lock_free() const noexcept; - explicit atomic_ref(T*&); + explicit atomic_ref(@\placeholder{pointer-type}@&); atomic_ref(const atomic_ref&) noexcept; atomic_ref& operator=(const atomic_ref&) = delete; - void store(T*, memory_order = memory_order::seq_cst) const noexcept; - T* operator=(T*) const noexcept; - T* load(memory_order = memory_order::seq_cst) const noexcept; - operator T*() const noexcept; + void store(value_type, memory_order = memory_order::seq_cst) const noexcept; + value_type operator=(value_type) const noexcept; + value_type load(memory_order = memory_order::seq_cst) const noexcept; + operator value_type() const noexcept; - T* exchange(T*, memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_weak(T*&, T*, + value_type exchange(value_type, memory_order = memory_order::seq_cst) const noexcept; + bool compare_exchange_weak(value_type&, value_type, memory_order, memory_order) const noexcept; - bool compare_exchange_strong(T*&, T*, + bool compare_exchange_strong(value_type&, value_type, memory_order, memory_order) const noexcept; - bool compare_exchange_weak(T*&, T*, + bool compare_exchange_weak(value_type&, value_type, memory_order = memory_order::seq_cst) const noexcept; - bool compare_exchange_strong(T*&, T*, + bool compare_exchange_strong(value_type&, value_type, memory_order = memory_order::seq_cst) const noexcept; - T* fetch_add(difference_type, memory_order = memory_order::seq_cst) const noexcept; - T* fetch_sub(difference_type, memory_order = memory_order::seq_cst) const noexcept; - T* fetch_max(T*, memory_order = memory_order::seq_cst) const noexcept; - T* fetch_min(T*, memory_order = memory_order::seq_cst) const noexcept; + value_type fetch_add(difference_type, memory_order = memory_order::seq_cst) const noexcept; + value_type fetch_sub(difference_type, memory_order = memory_order::seq_cst) const noexcept; + value_type fetch_max(value_type, memory_order = memory_order::seq_cst) const noexcept; + value_type fetch_min(value_type, memory_order = memory_order::seq_cst) const noexcept; - T* operator++(int) const noexcept; - T* operator--(int) const noexcept; - T* operator++() const noexcept; - T* operator--() const noexcept; - T* operator+=(difference_type) const noexcept; - T* operator-=(difference_type) const noexcept; + value_type operator++(int) const noexcept; + value_type operator--(int) const noexcept; + value_type operator++() const noexcept; + value_type operator--() const noexcept; + value_type operator+=(difference_type) const noexcept; + value_type operator-=(difference_type) const noexcept; - void wait(T*, memory_order = memory_order::seq_cst) const noexcept; + void wait(value_type, memory_order = memory_order::seq_cst) const noexcept; void notify_one() const noexcept; void notify_all() const noexcept; constexpr @\placeholder{pointer-type}@* address() const noexcept; @@ -3904,13 +3948,18 @@ \indexlibrarymember{fetch_max}{atomic_ref}% \indexlibrarymember{fetch_min}{atomic_ref}% \begin{itemdecl} -T* fetch_@\placeholdernc{key}@(difference_type operand, memory_order order = memory_order::seq_cst) const noexcept; +value_type fetch_@\placeholdernc{key}@(difference_type operand, + memory_order order = memory_order::seq_cst) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{pointer-type}>} is \tcode{false}. + \pnum \mandates -\tcode{T} is a complete object type. +\tcode{remove_pointer_t<\placeholder{pointer-type}>} is a complete object type. \pnum \effects @@ -3943,15 +3992,17 @@ \end{note} \end{itemdescr} - - \indexlibrarymember{operator+=}{atomic_ref}% \indexlibrarymember{operator-=}{atomic_ref}% \begin{itemdecl} -T* operator @\placeholder{op}@=(difference_type operand) const noexcept; +value_type operator @\placeholder{op}@=(difference_type operand) const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{pointer-type}>} is \tcode{false}. + \pnum \effects Equivalent to: @@ -3961,6 +4012,14 @@ \rSec3[atomics.ref.memop]{Member operators common to integers and pointers to objects} +\pnum +Let \placeholder{referred-type} +be \placeholder{pointer-type} +for the specializations in \ref{atomics.ref.pointer} and +be \placeholder{integral-type} +for the specializations in \ref{atomics.ref.int}. + + \indexlibrarymember{operator++}{atomic_ref}% \indexlibrarymember{operator++}{atomic_ref<\placeholder{integral-type}>}% \begin{itemdecl} @@ -3968,6 +4027,10 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{referred-type}>} is \tcode{false}. + \pnum \effects Equivalent to: \tcode{return fetch_add(1);} @@ -3980,6 +4043,10 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{referred-type}>} is \tcode{false}. + \pnum \effects Equivalent to: \tcode{return fetch_sub(1);} @@ -3992,6 +4059,10 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{referred-type}>} is \tcode{false}. + \pnum \effects Equivalent to: \tcode{return fetch_add(1) + 1;} @@ -4004,6 +4075,10 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{referred-type}>} is \tcode{false}. + \pnum \effects Equivalent to: \tcode{return fetch_sub(1) - 1;} @@ -4070,8 +4145,9 @@ \item \tcode{is_trivially_copyable_v}, \item \tcode{is_copy_constructible_v}, \item \tcode{is_move_constructible_v}, -\item \tcode{is_copy_assignable_v}, or -\item \tcode{is_move_assignable_v} +\item \tcode{is_copy_assignable_v}, +\item \tcode{is_move_assignable_v}, or +\item \tcode{same_as>}, \end{itemize} is \tcode{false}. \begin{note}