This commit is contained in:
2025-10-25 03:02:53 +03:00
commit 043225d523
3416 changed files with 681196 additions and 0 deletions

1919
cppdraft/util/sharedptr.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,675 @@
[util.smartptr.atomic]
# 32 Concurrency support library [[thread]](./#thread)
## 32.5 Atomic operations [[atomics]](atomics#util.smartptr.atomic)
### 32.5.8 Class template atomic [[atomics.types.generic]](atomics.types.generic#util.smartptr.atomic)
#### 32.5.8.7 Partial specializations for smart pointers [util.smartptr.atomic]
#### [32.5.8.7.1](#general) General [[util.smartptr.atomic.general]](util.smartptr.atomic.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6072)
The library provides partial specializations of the atomic template
for shared-ownership smart pointers ([[util.sharedptr]](util.sharedptr "20.3.2Shared-ownership pointers"))[.](#general-1.sentence-1)
[*Note [1](#general-note-1)*:
The partial specializations are declared in header [<memory>](memory.syn#header:%3cmemory%3e "20.2.2Header <memory> synopsis[memory.syn]")[.](#general-1.sentence-2)
— *end note*]
The behavior of all operations is as specified in [[atomics.types.generic]](atomics.types.generic "32.5.8Class template atomic"),
unless specified otherwise[.](#general-1.sentence-3)
The template parameter T of these partial specializations
may be an incomplete type[.](#general-1.sentence-4)
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6083)
All changes to an atomic smart pointer in [util.smartptr.atomic], and
all associated use_count increments,
are guaranteed to be performed atomically[.](#general-2.sentence-1)
Associated use_count decrements
are sequenced after the atomic operation,
but are not required to be part of it[.](#general-2.sentence-2)
Any associated deletion and deallocation
are sequenced after the atomic update step and
are not part of the atomic operation[.](#general-2.sentence-3)
[*Note [2](#general-note-2)*:
If the atomic operation uses locks,
locks acquired by the implementation
will be held when any use_count adjustments are performed, and
will not be held when any destruction or deallocation
resulting from this is performed[.](#general-2.sentence-4)
— *end note*]
[3](#general-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6101)
[*Example [1](#general-example-1)*: template<typename T> class atomic_list {struct node { T t;
shared_ptr<node> next; };
atomic<shared_ptr<node>> head;
public: shared_ptr<node> find(T t) const {auto p = head.load(); while (p && p->t != t) p = p->next; return p; }void push_front(T t) {auto p = make_shared<node>();
p->t = t;
p->next = head; while (!head.compare_exchange_weak(p->next, p)) {}}}; — *end example*]
#### [32.5.8.7.2](#shared) Partial specialization for shared_ptr [[util.smartptr.atomic.shared]](util.smartptr.atomic.shared)
[🔗](#lib:atomic%3cshared_ptr%3cT%3e%3e)
namespace std {template<class T> struct atomic<shared_ptr<T>> {using value_type = shared_ptr<T>; static constexpr bool is_always_lock_free = *implementation-defined*; bool is_lock_free() const noexcept; constexpr atomic() noexcept; constexpr atomic(nullptr_t) noexcept : atomic() { }constexpr atomic(shared_ptr<T> desired) noexcept;
atomic(const atomic&) = delete; void operator=(const atomic&) = delete; constexpr shared_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept; constexpr operator shared_ptr<T>() const noexcept; constexpr void store(shared_ptr<T> desired,
memory_order order = memory_order::seq_cst) noexcept; constexpr void operator=(shared_ptr<T> desired) noexcept; constexpr void operator=(nullptr_t) noexcept; constexpr shared_ptr<T> exchange(shared_ptr<T> desired,
memory_order order = memory_order::seq_cst) noexcept; constexpr bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
memory_order success, memory_order failure) noexcept; constexpr bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
memory_order success, memory_order failure) noexcept; constexpr bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
memory_order order = memory_order::seq_cst) noexcept; constexpr bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
memory_order order = memory_order::seq_cst) noexcept; constexpr void wait(shared_ptr<T> old,
memory_order order = memory_order::seq_cst) const noexcept; constexpr void notify_one() noexcept; constexpr void notify_all() noexcept; private: shared_ptr<T> p; // *exposition only*};}
[🔗](#lib:atomic%3cshared_ptr%3cT%3e%3e,constructor)
`constexpr atomic() noexcept;
`
[1](#shared-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6181)
*Effects*: Value-initializes p[.](#shared-1.sentence-1)
[🔗](#lib:atomic%3cshared_ptr%3cT%3e%3e,constructor_)
`constexpr atomic(shared_ptr<T> desired) noexcept;
`
[2](#shared-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6192)
*Effects*: Initializes the object with the value desired[.](#shared-2.sentence-1)
Initialization is not an atomic operation ([[intro.multithread]](intro.multithread "6.10.2Multi-threaded executions and data races"))[.](#shared-2.sentence-2)
[*Note [1](#shared-note-1)*:
It is possible to have an access to
an atomic object A race with its construction,
for example,
by communicating the address of the just-constructed object A to another thread via memory_order::relaxed operations
on a suitable atomic pointer variable, and
then immediately accessing A in the receiving thread[.](#shared-2.sentence-3)
This results in undefined behavior[.](#shared-2.sentence-4)
— *end note*]
[🔗](#lib:store,atomic%3cshared_ptr%3cT%3e%3e)
`constexpr void store(shared_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
`
[3](#shared-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6214)
*Preconditions*: order ismemory_order::relaxed,memory_order::release, ormemory_order::seq_cst[.](#shared-3.sentence-1)
[4](#shared-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6221)
*Effects*: Atomically replaces the value pointed to by this with
the value of desired as if by p.swap(desired)[.](#shared-4.sentence-1)
Memory is affected according to the value of order[.](#shared-4.sentence-2)
[🔗](#lib:operator=,atomic%3cshared_ptr%3cT%3e%3e)
`constexpr void operator=(shared_ptr<T> desired) noexcept;
`
[5](#shared-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6234)
*Effects*: Equivalent to store(desired)[.](#shared-5.sentence-1)
[🔗](#lib:operator=,atomic%3cshared_ptr%3cT%3e%3e_)
`constexpr void operator=(nullptr_t) noexcept;
`
[6](#shared-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6245)
*Effects*: Equivalent to store(nullptr)[.](#shared-6.sentence-1)
[🔗](#lib:load,atomic%3cshared_ptr%3cT%3e%3e)
`constexpr shared_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
`
[7](#shared-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6256)
*Preconditions*: order ismemory_order::relaxed,memory_order::acquire, ormemory_order::seq_cst[.](#shared-7.sentence-1)
[8](#shared-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6263)
*Effects*: Memory is affected according to the value of order[.](#shared-8.sentence-1)
[9](#shared-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6267)
*Returns*: Atomically returns p[.](#shared-9.sentence-1)
[🔗](#lib:operator_shared_ptr%3cT%3e,atomic%3cshared_ptr%3cT%3e%3e)
`constexpr operator shared_ptr<T>() const noexcept;
`
[10](#shared-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6278)
*Effects*: Equivalent to: return load();
[🔗](#lib:exchange,atomic%3cshared_ptr%3cT%3e%3e)
`constexpr shared_ptr<T> exchange(shared_ptr<T> desired,
memory_order order = memory_order::seq_cst) noexcept;
`
[11](#shared-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6290)
*Effects*: Atomically replaces p with desired as if by p.swap(desired)[.](#shared-11.sentence-1)
Memory is affected according to the value of order[.](#shared-11.sentence-2)
This is an atomic read-modify-write operation ([[intro.races]](intro.races "6.10.2.2Data races"))[.](#shared-11.sentence-3)
[12](#shared-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6297)
*Returns*: Atomically returns the value of p immediately before the effects[.](#shared-12.sentence-1)
[🔗](#lib:compare_exchange_weak,atomic%3cshared_ptr%3cT%3e%3e)
`constexpr bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
memory_order success, memory_order failure) noexcept;
constexpr bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
memory_order success, memory_order failure) noexcept;
`
[13](#shared-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6312)
*Preconditions*: failure ismemory_order::relaxed,memory_order::acquire, ormemory_order::seq_cst[.](#shared-13.sentence-1)
[14](#shared-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6319)
*Effects*: If p is equivalent to expected,
assigns desired to p and
has synchronization semantics corresponding to the value of success,
otherwise assigns p to expected and
has synchronization semantics corresponding to the value of failure[.](#shared-14.sentence-1)
[15](#shared-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6327)
*Returns*: true if p was equivalent to expected,false otherwise[.](#shared-15.sentence-1)
[16](#shared-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6332)
*Remarks*: Two shared_ptr objects are equivalent if
they store the same pointer value and
either share ownership or are both empty[.](#shared-16.sentence-1)
The weak form may fail spuriously[.](#shared-16.sentence-2)
See [[atomics.types.operations]](atomics.types.operations "32.5.8.2Operations on atomic types")[.](#shared-16.sentence-3)
[17](#shared-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6339)
If the operation returns true,expected is not accessed after the atomic update and
the operation is an atomic read-modify-write operation ([[intro.multithread]](intro.multithread "6.10.2Multi-threaded executions and data races"))
on the memory pointed to by this[.](#shared-17.sentence-1)
Otherwise, the operation is an atomic load operation on that memory, andexpected is updated with the existing value
read from the atomic object in the attempted atomic update[.](#shared-17.sentence-2)
The use_count update corresponding to the write to expected is part of the atomic operation[.](#shared-17.sentence-3)
The write to expected itself
is not required to be part of the atomic operation[.](#shared-17.sentence-4)
[🔗](#lib:compare_exchange_weak,atomic%3cshared_ptr%3cT%3e%3e_)
`constexpr bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
memory_order order = memory_order::seq_cst) noexcept;
`
[18](#shared-18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6360)
*Effects*: Equivalent to:return compare_exchange_weak(expected, desired, order, fail_order); where fail_order is the same as 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[.](#shared-18.sentence-1)
[🔗](#lib:compare_exchange_strong,atomic%3cshared_ptr%3cT%3e%3e_)
`constexpr bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
memory_order order = memory_order::seq_cst) noexcept;
`
[19](#shared-19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6380)
*Effects*: Equivalent to:return compare_exchange_strong(expected, desired, order, fail_order); where fail_order is the same as 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[.](#shared-19.sentence-1)
[🔗](#lib:wait,atomic%3cshared_ptr%3cT%3e%3e)
`constexpr void wait(shared_ptr<T> old, memory_order order = memory_order::seq_cst) const noexcept;
`
[20](#shared-20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6399)
*Preconditions*: order ismemory_order::relaxed,memory_order::acquire, ormemory_order::seq_cst[.](#shared-20.sentence-1)
[21](#shared-21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6406)
*Effects*: Repeatedly performs the following steps, in order:
- [(21.1)](#shared-21.1)
Evaluates load(order) and compares it to old[.](#shared-21.1.sentence-1)
- [(21.2)](#shared-21.2)
If the two are not equivalent, returns[.](#shared-21.2.sentence-1)
- [(21.3)](#shared-21.3)
Blocks until it
is unblocked by an atomic notifying operation or is unblocked spuriously[.](#shared-21.3.sentence-1)
[22](#shared-22)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6419)
*Remarks*: Two shared_ptr objects are equivalent
if they store the same pointer and either share ownership or are both empty[.](#shared-22.sentence-1)
This function is an atomic waiting operation ([[atomics.wait]](atomics.wait "32.5.6Waiting and notifying"))[.](#shared-22.sentence-2)
[🔗](#lib:notify_one,atomic%3cshared_ptr%3cT%3e%3e)
`constexpr void notify_one() noexcept;
`
[23](#shared-23)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6432)
*Effects*: Unblocks the execution of at least one atomic waiting operation
that is eligible to be unblocked ([[atomics.wait]](atomics.wait "32.5.6Waiting and notifying")) by this call,
if any such atomic waiting operations exist[.](#shared-23.sentence-1)
[24](#shared-24)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6438)
*Remarks*: This function is an atomic notifying operation ([[atomics.wait]](atomics.wait "32.5.6Waiting and notifying"))[.](#shared-24.sentence-1)
[🔗](#lib:notify_all,atomic%3cshared_ptr%3cT%3e%3e)
`constexpr void notify_all() noexcept;
`
[25](#shared-25)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6449)
*Effects*: Unblocks the execution of all atomic waiting operations
that are eligible to be unblocked ([[atomics.wait]](atomics.wait "32.5.6Waiting and notifying")) by this call[.](#shared-25.sentence-1)
[26](#shared-26)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6454)
*Remarks*: This function is an atomic notifying operation ([[atomics.wait]](atomics.wait "32.5.6Waiting and notifying"))[.](#shared-26.sentence-1)
#### [32.5.8.7.3](#weak) Partial specialization for weak_ptr [[util.smartptr.atomic.weak]](util.smartptr.atomic.weak)
[🔗](#lib:atomic%3cweak_ptr%3cT%3e%3e)
namespace std {template<class T> struct atomic<weak_ptr<T>> {using value_type = weak_ptr<T>; static constexpr bool is_always_lock_free = *implementation-defined*; bool is_lock_free() const noexcept; constexpr atomic() noexcept; constexpr atomic(weak_ptr<T> desired) noexcept;
atomic(const atomic&) = delete; void operator=(const atomic&) = delete; constexpr weak_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept; constexpr operator weak_ptr<T>() const noexcept; constexpr void store(weak_ptr<T> desired,
memory_order order = memory_order::seq_cst) noexcept; constexpr void operator=(weak_ptr<T> desired) noexcept; constexpr weak_ptr<T> exchange(weak_ptr<T> desired,
memory_order order = memory_order::seq_cst) noexcept; constexpr bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
memory_order success, memory_order failure) noexcept; constexpr bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
memory_order success, memory_order failure) noexcept; constexpr bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
memory_order order = memory_order::seq_cst) noexcept; constexpr bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
memory_order order = memory_order::seq_cst) noexcept; constexpr void wait(weak_ptr<T> old,
memory_order order = memory_order::seq_cst) const noexcept; constexpr void notify_one() noexcept; constexpr void notify_all() noexcept; private: weak_ptr<T> p; // *exposition only*};}
[🔗](#lib:atomic%3cweak_ptr%3cT%3e%3e,constructor)
`constexpr atomic() noexcept;
`
[1](#weak-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6509)
*Effects*: Value-initializes p[.](#weak-1.sentence-1)
[🔗](#lib:atomic%3cweak_ptr%3cT%3e%3e,constructor_)
`constexpr atomic(weak_ptr<T> desired) noexcept;
`
[2](#weak-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6520)
*Effects*: Initializes the object with the value desired[.](#weak-2.sentence-1)
Initialization is not an atomic operation ([[intro.multithread]](intro.multithread "6.10.2Multi-threaded executions and data races"))[.](#weak-2.sentence-2)
[*Note [1](#weak-note-1)*:
It is possible to have an access to
an atomic object A race with its construction,
for example,
by communicating the address of the just-constructed object A to another thread via memory_order::relaxed operations
on a suitable atomic pointer variable, and
then immediately accessing A in the receiving thread[.](#weak-2.sentence-3)
This results in undefined behavior[.](#weak-2.sentence-4)
— *end note*]
[🔗](#lib:store,atomic%3cweak_ptr%3cT%3e%3e)
`constexpr void store(weak_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
`
[3](#weak-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6542)
*Preconditions*: order ismemory_order::relaxed,memory_order::release, ormemory_order::seq_cst[.](#weak-3.sentence-1)
[4](#weak-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6549)
*Effects*: Atomically replaces the value pointed to by this with
the value of desired as if by p.swap(desired)[.](#weak-4.sentence-1)
Memory is affected according to the value of order[.](#weak-4.sentence-2)
[🔗](#lib:operator=,atomic%3cweak_ptr%3cT%3e%3e)
`constexpr void operator=(weak_ptr<T> desired) noexcept;
`
[5](#weak-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6562)
*Effects*: Equivalent to store(desired)[.](#weak-5.sentence-1)
[🔗](#lib:load,atomic%3cweak_ptr%3cT%3e%3e)
`constexpr weak_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
`
[6](#weak-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6573)
*Preconditions*: order ismemory_order::relaxed,memory_order::acquire, ormemory_order::seq_cst[.](#weak-6.sentence-1)
[7](#weak-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6580)
*Effects*: Memory is affected according to the value of order[.](#weak-7.sentence-1)
[8](#weak-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6584)
*Returns*: Atomically returns p[.](#weak-8.sentence-1)
[🔗](#lib:operator_weak_ptr%3cT%3e,atomic%3cweak_ptr%3cT%3e%3e)
`constexpr operator weak_ptr<T>() const noexcept;
`
[9](#weak-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6595)
*Effects*: Equivalent to: return load();
[🔗](#lib:exchange,atomic%3cweak_ptr%3cT%3e%3e)
`constexpr weak_ptr<T> exchange(weak_ptr<T> desired,
memory_order order = memory_order::seq_cst) noexcept;
`
[10](#weak-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6607)
*Effects*: Atomically replaces p with desired as if by p.swap(desired)[.](#weak-10.sentence-1)
Memory is affected according to the value of order[.](#weak-10.sentence-2)
This is an atomic read-modify-write operation ([[intro.races]](intro.races "6.10.2.2Data races"))[.](#weak-10.sentence-3)
[11](#weak-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6614)
*Returns*: Atomically returns the value of p immediately before the effects[.](#weak-11.sentence-1)
[🔗](#lib:compare_exchange_weak,atomic%3cweak_ptr%3cT%3e%3e)
`constexpr bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
memory_order success, memory_order failure) noexcept;
constexpr bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
memory_order success, memory_order failure) noexcept;
`
[12](#weak-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6628)
*Preconditions*: failure ismemory_order::relaxed,memory_order::acquire, ormemory_order::seq_cst[.](#weak-12.sentence-1)
[13](#weak-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6635)
*Effects*: If p is equivalent to expected,
assigns desired to p and
has synchronization semantics corresponding to the value of success,
otherwise assigns p to expected and
has synchronization semantics corresponding to the value of failure[.](#weak-13.sentence-1)
[14](#weak-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6643)
*Returns*: true if p was equivalent to expected,false otherwise[.](#weak-14.sentence-1)
[15](#weak-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6648)
*Remarks*: Two weak_ptr objects are equivalent if
they store the same pointer value and
either share ownership or are both empty[.](#weak-15.sentence-1)
The weak form may fail spuriously[.](#weak-15.sentence-2)
See [[atomics.types.operations]](atomics.types.operations "32.5.8.2Operations on atomic types")[.](#weak-15.sentence-3)
[16](#weak-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6655)
If the operation returns true,expected is not accessed after the atomic update and
the operation is an atomic read-modify-write operation ([[intro.multithread]](intro.multithread "6.10.2Multi-threaded executions and data races"))
on the memory pointed to by this[.](#weak-16.sentence-1)
Otherwise, the operation is an atomic load operation on that memory, andexpected is updated with the existing value
read from the atomic object in the attempted atomic update[.](#weak-16.sentence-2)
The use_count update corresponding to the write to expected is part of the atomic operation[.](#weak-16.sentence-3)
The write to expected itself
is not required to be part of the atomic operation[.](#weak-16.sentence-4)
[🔗](#lib:compare_exchange_weak,atomic%3cweak_ptr%3cT%3e%3e_)
`constexpr bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
memory_order order = memory_order::seq_cst) noexcept;
`
[17](#weak-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6676)
*Effects*: Equivalent to:return compare_exchange_weak(expected, desired, order, fail_order); where fail_order is the same as 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[.](#weak-17.sentence-1)
[🔗](#lib:compare_exchange_strong,atomic%3cweak_ptr%3cT%3e%3e)
`constexpr bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
memory_order order = memory_order::seq_cst) noexcept;
`
[18](#weak-18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6696)
*Effects*: Equivalent to:return compare_exchange_strong(expected, desired, order, fail_order); where fail_order is the same as 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[.](#weak-18.sentence-1)
[🔗](#lib:wait,atomic%3cweak_ptr%3cT%3e%3e)
`constexpr void wait(weak_ptr<T> old, memory_order order = memory_order::seq_cst) const noexcept;
`
[19](#weak-19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6715)
*Preconditions*: order ismemory_order::relaxed,memory_order::acquire, ormemory_order::seq_cst[.](#weak-19.sentence-1)
[20](#weak-20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6722)
*Effects*: Repeatedly performs the following steps, in order:
- [(20.1)](#weak-20.1)
Evaluates load(order) and compares it to old[.](#weak-20.1.sentence-1)
- [(20.2)](#weak-20.2)
If the two are not equivalent, returns[.](#weak-20.2.sentence-1)
- [(20.3)](#weak-20.3)
Blocks until it
is unblocked by an atomic notifying operation or is unblocked spuriously[.](#weak-20.3.sentence-1)
[21](#weak-21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6735)
*Remarks*: Two weak_ptr objects are equivalent
if they store the same pointer and either share ownership or are both empty[.](#weak-21.sentence-1)
This function is an atomic waiting operation ([[atomics.wait]](atomics.wait "32.5.6Waiting and notifying"))[.](#weak-21.sentence-2)
[🔗](#lib:notify_one,atomic%3cweak_ptr%3cT%3e%3e)
`constexpr void notify_one() noexcept;
`
[22](#weak-22)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6749)
*Effects*: Unblocks the execution of at least one atomic waiting operation
that is eligible to be unblocked ([[atomics.wait]](atomics.wait "32.5.6Waiting and notifying")) by this call,
if any such atomic waiting operations exist[.](#weak-22.sentence-1)
[23](#weak-23)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6755)
*Remarks*: This function is an atomic notifying operation ([[atomics.wait]](atomics.wait "32.5.6Waiting and notifying"))[.](#weak-23.sentence-1)
[🔗](#lib:notify_all,atomic%3cweak_ptr%3cT%3e%3e)
`constexpr void notify_all() noexcept;
`
[24](#weak-24)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6766)
*Effects*: Unblocks the execution of all atomic waiting operations
that are eligible to be unblocked ([[atomics.wait]](atomics.wait "32.5.6Waiting and notifying")) by this call[.](#weak-24.sentence-1)
[25](#weak-25)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6771)
*Remarks*: This function is an atomic notifying operation ([[atomics.wait]](atomics.wait "32.5.6Waiting and notifying"))[.](#weak-25.sentence-1)

View File

@@ -0,0 +1,68 @@
[util.smartptr.atomic.general]
# 32 Concurrency support library [[thread]](./#thread)
## 32.5 Atomic operations [[atomics]](atomics#util.smartptr.atomic.general)
### 32.5.8 Class template atomic [[atomics.types.generic]](atomics.types.generic#util.smartptr.atomic.general)
#### 32.5.8.7 Partial specializations for smart pointers [[util.smartptr.atomic]](util.smartptr.atomic#general)
#### 32.5.8.7.1 General [util.smartptr.atomic.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6072)
The library provides partial specializations of the atomic template
for shared-ownership smart pointers ([[util.sharedptr]](util.sharedptr "20.3.2Shared-ownership pointers"))[.](#1.sentence-1)
[*Note [1](#note-1)*:
The partial specializations are declared in header [<memory>](memory.syn#header:%3cmemory%3e "20.2.2Header <memory> synopsis[memory.syn]")[.](#1.sentence-2)
— *end note*]
The behavior of all operations is as specified in [[atomics.types.generic]](atomics.types.generic "32.5.8Class template atomic"),
unless specified otherwise[.](#1.sentence-3)
The template parameter T of these partial specializations
may be an incomplete type[.](#1.sentence-4)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6083)
All changes to an atomic smart pointer in [[util.smartptr.atomic]](util.smartptr.atomic "32.5.8.7Partial specializations for smart pointers"), and
all associated use_count increments,
are guaranteed to be performed atomically[.](#2.sentence-1)
Associated use_count decrements
are sequenced after the atomic operation,
but are not required to be part of it[.](#2.sentence-2)
Any associated deletion and deallocation
are sequenced after the atomic update step and
are not part of the atomic operation[.](#2.sentence-3)
[*Note [2](#note-2)*:
If the atomic operation uses locks,
locks acquired by the implementation
will be held when any use_count adjustments are performed, and
will not be held when any destruction or deallocation
resulting from this is performed[.](#2.sentence-4)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6101)
[*Example [1](#example-1)*: template<typename T> class atomic_list {struct node { T t;
shared_ptr<node> next; };
atomic<shared_ptr<node>> head;
public: shared_ptr<node> find(T t) const {auto p = head.load(); while (p && p->t != t) p = p->next; return p; }void push_front(T t) {auto p = make_shared<node>();
p->t = t;
p->next = head; while (!head.compare_exchange_weak(p->next, p)) {}}}; — *end example*]

View File

@@ -0,0 +1,318 @@
[util.smartptr.atomic.shared]
# 32 Concurrency support library [[thread]](./#thread)
## 32.5 Atomic operations [[atomics]](atomics#util.smartptr.atomic.shared)
### 32.5.8 Class template atomic [[atomics.types.generic]](atomics.types.generic#util.smartptr.atomic.shared)
#### 32.5.8.7 Partial specializations for smart pointers [[util.smartptr.atomic]](util.smartptr.atomic#shared)
#### 32.5.8.7.2 Partial specialization for shared_ptr [util.smartptr.atomic.shared]
[🔗](#lib:atomic%3cshared_ptr%3cT%3e%3e)
namespace std {template<class T> struct atomic<shared_ptr<T>> {using value_type = shared_ptr<T>; static constexpr bool is_always_lock_free = *implementation-defined*; bool is_lock_free() const noexcept; constexpr atomic() noexcept; constexpr atomic(nullptr_t) noexcept : atomic() { }constexpr atomic(shared_ptr<T> desired) noexcept;
atomic(const atomic&) = delete; void operator=(const atomic&) = delete; constexpr shared_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept; constexpr operator shared_ptr<T>() const noexcept; constexpr void store(shared_ptr<T> desired,
memory_order order = memory_order::seq_cst) noexcept; constexpr void operator=(shared_ptr<T> desired) noexcept; constexpr void operator=(nullptr_t) noexcept; constexpr shared_ptr<T> exchange(shared_ptr<T> desired,
memory_order order = memory_order::seq_cst) noexcept; constexpr bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
memory_order success, memory_order failure) noexcept; constexpr bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
memory_order success, memory_order failure) noexcept; constexpr bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
memory_order order = memory_order::seq_cst) noexcept; constexpr bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
memory_order order = memory_order::seq_cst) noexcept; constexpr void wait(shared_ptr<T> old,
memory_order order = memory_order::seq_cst) const noexcept; constexpr void notify_one() noexcept; constexpr void notify_all() noexcept; private: shared_ptr<T> p; // *exposition only*};}
[🔗](#lib:atomic%3cshared_ptr%3cT%3e%3e,constructor)
`constexpr atomic() noexcept;
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6181)
*Effects*: Value-initializes p[.](#1.sentence-1)
[🔗](#lib:atomic%3cshared_ptr%3cT%3e%3e,constructor_)
`constexpr atomic(shared_ptr<T> desired) noexcept;
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6192)
*Effects*: Initializes the object with the value desired[.](#2.sentence-1)
Initialization is not an atomic operation ([[intro.multithread]](intro.multithread "6.10.2Multi-threaded executions and data races"))[.](#2.sentence-2)
[*Note [1](#note-1)*:
It is possible to have an access to
an atomic object A race with its construction,
for example,
by communicating the address of the just-constructed object A to another thread via memory_order::relaxed operations
on a suitable atomic pointer variable, and
then immediately accessing A in the receiving thread[.](#2.sentence-3)
This results in undefined behavior[.](#2.sentence-4)
— *end note*]
[🔗](#lib:store,atomic%3cshared_ptr%3cT%3e%3e)
`constexpr void store(shared_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
`
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6214)
*Preconditions*: order ismemory_order::relaxed,memory_order::release, ormemory_order::seq_cst[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6221)
*Effects*: Atomically replaces the value pointed to by this with
the value of desired as if by p.swap(desired)[.](#4.sentence-1)
Memory is affected according to the value of order[.](#4.sentence-2)
[🔗](#lib:operator=,atomic%3cshared_ptr%3cT%3e%3e)
`constexpr void operator=(shared_ptr<T> desired) noexcept;
`
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6234)
*Effects*: Equivalent to store(desired)[.](#5.sentence-1)
[🔗](#lib:operator=,atomic%3cshared_ptr%3cT%3e%3e_)
`constexpr void operator=(nullptr_t) noexcept;
`
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6245)
*Effects*: Equivalent to store(nullptr)[.](#6.sentence-1)
[🔗](#lib:load,atomic%3cshared_ptr%3cT%3e%3e)
`constexpr shared_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
`
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6256)
*Preconditions*: order ismemory_order::relaxed,memory_order::acquire, ormemory_order::seq_cst[.](#7.sentence-1)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6263)
*Effects*: Memory is affected according to the value of order[.](#8.sentence-1)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6267)
*Returns*: Atomically returns p[.](#9.sentence-1)
[🔗](#lib:operator_shared_ptr%3cT%3e,atomic%3cshared_ptr%3cT%3e%3e)
`constexpr operator shared_ptr<T>() const noexcept;
`
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6278)
*Effects*: Equivalent to: return load();
[🔗](#lib:exchange,atomic%3cshared_ptr%3cT%3e%3e)
`constexpr shared_ptr<T> exchange(shared_ptr<T> desired,
memory_order order = memory_order::seq_cst) noexcept;
`
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6290)
*Effects*: Atomically replaces p with desired as if by p.swap(desired)[.](#11.sentence-1)
Memory is affected according to the value of order[.](#11.sentence-2)
This is an atomic read-modify-write operation ([[intro.races]](intro.races "6.10.2.2Data races"))[.](#11.sentence-3)
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6297)
*Returns*: Atomically returns the value of p immediately before the effects[.](#12.sentence-1)
[🔗](#lib:compare_exchange_weak,atomic%3cshared_ptr%3cT%3e%3e)
`constexpr bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
memory_order success, memory_order failure) noexcept;
constexpr bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
memory_order success, memory_order failure) noexcept;
`
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6312)
*Preconditions*: failure ismemory_order::relaxed,memory_order::acquire, ormemory_order::seq_cst[.](#13.sentence-1)
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6319)
*Effects*: If p is equivalent to expected,
assigns desired to p and
has synchronization semantics corresponding to the value of success,
otherwise assigns p to expected and
has synchronization semantics corresponding to the value of failure[.](#14.sentence-1)
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6327)
*Returns*: true if p was equivalent to expected,false otherwise[.](#15.sentence-1)
[16](#16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6332)
*Remarks*: Two shared_ptr objects are equivalent if
they store the same pointer value and
either share ownership or are both empty[.](#16.sentence-1)
The weak form may fail spuriously[.](#16.sentence-2)
See [[atomics.types.operations]](atomics.types.operations "32.5.8.2Operations on atomic types")[.](#16.sentence-3)
[17](#17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6339)
If the operation returns true,expected is not accessed after the atomic update and
the operation is an atomic read-modify-write operation ([[intro.multithread]](intro.multithread "6.10.2Multi-threaded executions and data races"))
on the memory pointed to by this[.](#17.sentence-1)
Otherwise, the operation is an atomic load operation on that memory, andexpected is updated with the existing value
read from the atomic object in the attempted atomic update[.](#17.sentence-2)
The use_count update corresponding to the write to expected is part of the atomic operation[.](#17.sentence-3)
The write to expected itself
is not required to be part of the atomic operation[.](#17.sentence-4)
[🔗](#lib:compare_exchange_weak,atomic%3cshared_ptr%3cT%3e%3e_)
`constexpr bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
memory_order order = memory_order::seq_cst) noexcept;
`
[18](#18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6360)
*Effects*: Equivalent to:return compare_exchange_weak(expected, desired, order, fail_order); where fail_order is the same as 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[.](#18.sentence-1)
[🔗](#lib:compare_exchange_strong,atomic%3cshared_ptr%3cT%3e%3e_)
`constexpr bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
memory_order order = memory_order::seq_cst) noexcept;
`
[19](#19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6380)
*Effects*: Equivalent to:return compare_exchange_strong(expected, desired, order, fail_order); where fail_order is the same as 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[.](#19.sentence-1)
[🔗](#lib:wait,atomic%3cshared_ptr%3cT%3e%3e)
`constexpr void wait(shared_ptr<T> old, memory_order order = memory_order::seq_cst) const noexcept;
`
[20](#20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6399)
*Preconditions*: order ismemory_order::relaxed,memory_order::acquire, ormemory_order::seq_cst[.](#20.sentence-1)
[21](#21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6406)
*Effects*: Repeatedly performs the following steps, in order:
- [(21.1)](#21.1)
Evaluates load(order) and compares it to old[.](#21.1.sentence-1)
- [(21.2)](#21.2)
If the two are not equivalent, returns[.](#21.2.sentence-1)
- [(21.3)](#21.3)
Blocks until it
is unblocked by an atomic notifying operation or is unblocked spuriously[.](#21.3.sentence-1)
[22](#22)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6419)
*Remarks*: Two shared_ptr objects are equivalent
if they store the same pointer and either share ownership or are both empty[.](#22.sentence-1)
This function is an atomic waiting operation ([[atomics.wait]](atomics.wait "32.5.6Waiting and notifying"))[.](#22.sentence-2)
[🔗](#lib:notify_one,atomic%3cshared_ptr%3cT%3e%3e)
`constexpr void notify_one() noexcept;
`
[23](#23)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6432)
*Effects*: Unblocks the execution of at least one atomic waiting operation
that is eligible to be unblocked ([[atomics.wait]](atomics.wait "32.5.6Waiting and notifying")) by this call,
if any such atomic waiting operations exist[.](#23.sentence-1)
[24](#24)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6438)
*Remarks*: This function is an atomic notifying operation ([[atomics.wait]](atomics.wait "32.5.6Waiting and notifying"))[.](#24.sentence-1)
[🔗](#lib:notify_all,atomic%3cshared_ptr%3cT%3e%3e)
`constexpr void notify_all() noexcept;
`
[25](#25)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6449)
*Effects*: Unblocks the execution of all atomic waiting operations
that are eligible to be unblocked ([[atomics.wait]](atomics.wait "32.5.6Waiting and notifying")) by this call[.](#25.sentence-1)
[26](#26)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6454)
*Remarks*: This function is an atomic notifying operation ([[atomics.wait]](atomics.wait "32.5.6Waiting and notifying"))[.](#26.sentence-1)

View File

@@ -0,0 +1,307 @@
[util.smartptr.atomic.weak]
# 32 Concurrency support library [[thread]](./#thread)
## 32.5 Atomic operations [[atomics]](atomics#util.smartptr.atomic.weak)
### 32.5.8 Class template atomic [[atomics.types.generic]](atomics.types.generic#util.smartptr.atomic.weak)
#### 32.5.8.7 Partial specializations for smart pointers [[util.smartptr.atomic]](util.smartptr.atomic#weak)
#### 32.5.8.7.3 Partial specialization for weak_ptr [util.smartptr.atomic.weak]
[🔗](#lib:atomic%3cweak_ptr%3cT%3e%3e)
namespace std {template<class T> struct atomic<weak_ptr<T>> {using value_type = weak_ptr<T>; static constexpr bool is_always_lock_free = *implementation-defined*; bool is_lock_free() const noexcept; constexpr atomic() noexcept; constexpr atomic(weak_ptr<T> desired) noexcept;
atomic(const atomic&) = delete; void operator=(const atomic&) = delete; constexpr weak_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept; constexpr operator weak_ptr<T>() const noexcept; constexpr void store(weak_ptr<T> desired,
memory_order order = memory_order::seq_cst) noexcept; constexpr void operator=(weak_ptr<T> desired) noexcept; constexpr weak_ptr<T> exchange(weak_ptr<T> desired,
memory_order order = memory_order::seq_cst) noexcept; constexpr bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
memory_order success, memory_order failure) noexcept; constexpr bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
memory_order success, memory_order failure) noexcept; constexpr bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
memory_order order = memory_order::seq_cst) noexcept; constexpr bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
memory_order order = memory_order::seq_cst) noexcept; constexpr void wait(weak_ptr<T> old,
memory_order order = memory_order::seq_cst) const noexcept; constexpr void notify_one() noexcept; constexpr void notify_all() noexcept; private: weak_ptr<T> p; // *exposition only*};}
[🔗](#lib:atomic%3cweak_ptr%3cT%3e%3e,constructor)
`constexpr atomic() noexcept;
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6509)
*Effects*: Value-initializes p[.](#1.sentence-1)
[🔗](#lib:atomic%3cweak_ptr%3cT%3e%3e,constructor_)
`constexpr atomic(weak_ptr<T> desired) noexcept;
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6520)
*Effects*: Initializes the object with the value desired[.](#2.sentence-1)
Initialization is not an atomic operation ([[intro.multithread]](intro.multithread "6.10.2Multi-threaded executions and data races"))[.](#2.sentence-2)
[*Note [1](#note-1)*:
It is possible to have an access to
an atomic object A race with its construction,
for example,
by communicating the address of the just-constructed object A to another thread via memory_order::relaxed operations
on a suitable atomic pointer variable, and
then immediately accessing A in the receiving thread[.](#2.sentence-3)
This results in undefined behavior[.](#2.sentence-4)
— *end note*]
[🔗](#lib:store,atomic%3cweak_ptr%3cT%3e%3e)
`constexpr void store(weak_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
`
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6542)
*Preconditions*: order ismemory_order::relaxed,memory_order::release, ormemory_order::seq_cst[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6549)
*Effects*: Atomically replaces the value pointed to by this with
the value of desired as if by p.swap(desired)[.](#4.sentence-1)
Memory is affected according to the value of order[.](#4.sentence-2)
[🔗](#lib:operator=,atomic%3cweak_ptr%3cT%3e%3e)
`constexpr void operator=(weak_ptr<T> desired) noexcept;
`
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6562)
*Effects*: Equivalent to store(desired)[.](#5.sentence-1)
[🔗](#lib:load,atomic%3cweak_ptr%3cT%3e%3e)
`constexpr weak_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
`
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6573)
*Preconditions*: order ismemory_order::relaxed,memory_order::acquire, ormemory_order::seq_cst[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6580)
*Effects*: Memory is affected according to the value of order[.](#7.sentence-1)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6584)
*Returns*: Atomically returns p[.](#8.sentence-1)
[🔗](#lib:operator_weak_ptr%3cT%3e,atomic%3cweak_ptr%3cT%3e%3e)
`constexpr operator weak_ptr<T>() const noexcept;
`
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6595)
*Effects*: Equivalent to: return load();
[🔗](#lib:exchange,atomic%3cweak_ptr%3cT%3e%3e)
`constexpr weak_ptr<T> exchange(weak_ptr<T> desired,
memory_order order = memory_order::seq_cst) noexcept;
`
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6607)
*Effects*: Atomically replaces p with desired as if by p.swap(desired)[.](#10.sentence-1)
Memory is affected according to the value of order[.](#10.sentence-2)
This is an atomic read-modify-write operation ([[intro.races]](intro.races "6.10.2.2Data races"))[.](#10.sentence-3)
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6614)
*Returns*: Atomically returns the value of p immediately before the effects[.](#11.sentence-1)
[🔗](#lib:compare_exchange_weak,atomic%3cweak_ptr%3cT%3e%3e)
`constexpr bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
memory_order success, memory_order failure) noexcept;
constexpr bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
memory_order success, memory_order failure) noexcept;
`
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6628)
*Preconditions*: failure ismemory_order::relaxed,memory_order::acquire, ormemory_order::seq_cst[.](#12.sentence-1)
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6635)
*Effects*: If p is equivalent to expected,
assigns desired to p and
has synchronization semantics corresponding to the value of success,
otherwise assigns p to expected and
has synchronization semantics corresponding to the value of failure[.](#13.sentence-1)
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6643)
*Returns*: true if p was equivalent to expected,false otherwise[.](#14.sentence-1)
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6648)
*Remarks*: Two weak_ptr objects are equivalent if
they store the same pointer value and
either share ownership or are both empty[.](#15.sentence-1)
The weak form may fail spuriously[.](#15.sentence-2)
See [[atomics.types.operations]](atomics.types.operations "32.5.8.2Operations on atomic types")[.](#15.sentence-3)
[16](#16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6655)
If the operation returns true,expected is not accessed after the atomic update and
the operation is an atomic read-modify-write operation ([[intro.multithread]](intro.multithread "6.10.2Multi-threaded executions and data races"))
on the memory pointed to by this[.](#16.sentence-1)
Otherwise, the operation is an atomic load operation on that memory, andexpected is updated with the existing value
read from the atomic object in the attempted atomic update[.](#16.sentence-2)
The use_count update corresponding to the write to expected is part of the atomic operation[.](#16.sentence-3)
The write to expected itself
is not required to be part of the atomic operation[.](#16.sentence-4)
[🔗](#lib:compare_exchange_weak,atomic%3cweak_ptr%3cT%3e%3e_)
`constexpr bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
memory_order order = memory_order::seq_cst) noexcept;
`
[17](#17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6676)
*Effects*: Equivalent to:return compare_exchange_weak(expected, desired, order, fail_order); where fail_order is the same as 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[.](#17.sentence-1)
[🔗](#lib:compare_exchange_strong,atomic%3cweak_ptr%3cT%3e%3e)
`constexpr bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
memory_order order = memory_order::seq_cst) noexcept;
`
[18](#18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6696)
*Effects*: Equivalent to:return compare_exchange_strong(expected, desired, order, fail_order); where fail_order is the same as 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[.](#18.sentence-1)
[🔗](#lib:wait,atomic%3cweak_ptr%3cT%3e%3e)
`constexpr void wait(weak_ptr<T> old, memory_order order = memory_order::seq_cst) const noexcept;
`
[19](#19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6715)
*Preconditions*: order ismemory_order::relaxed,memory_order::acquire, ormemory_order::seq_cst[.](#19.sentence-1)
[20](#20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6722)
*Effects*: Repeatedly performs the following steps, in order:
- [(20.1)](#20.1)
Evaluates load(order) and compares it to old[.](#20.1.sentence-1)
- [(20.2)](#20.2)
If the two are not equivalent, returns[.](#20.2.sentence-1)
- [(20.3)](#20.3)
Blocks until it
is unblocked by an atomic notifying operation or is unblocked spuriously[.](#20.3.sentence-1)
[21](#21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6735)
*Remarks*: Two weak_ptr objects are equivalent
if they store the same pointer and either share ownership or are both empty[.](#21.sentence-1)
This function is an atomic waiting operation ([[atomics.wait]](atomics.wait "32.5.6Waiting and notifying"))[.](#21.sentence-2)
[🔗](#lib:notify_one,atomic%3cweak_ptr%3cT%3e%3e)
`constexpr void notify_one() noexcept;
`
[22](#22)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6749)
*Effects*: Unblocks the execution of at least one atomic waiting operation
that is eligible to be unblocked ([[atomics.wait]](atomics.wait "32.5.6Waiting and notifying")) by this call,
if any such atomic waiting operations exist[.](#22.sentence-1)
[23](#23)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6755)
*Remarks*: This function is an atomic notifying operation ([[atomics.wait]](atomics.wait "32.5.6Waiting and notifying"))[.](#23.sentence-1)
[🔗](#lib:notify_all,atomic%3cweak_ptr%3cT%3e%3e)
`constexpr void notify_all() noexcept;
`
[24](#24)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6766)
*Effects*: Unblocks the execution of all atomic waiting operations
that are eligible to be unblocked ([[atomics.wait]](atomics.wait "32.5.6Waiting and notifying")) by this call[.](#24.sentence-1)
[25](#25)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L6771)
*Remarks*: This function is an atomic notifying operation ([[atomics.wait]](atomics.wait "32.5.6Waiting and notifying"))[.](#25.sentence-1)

View File

@@ -0,0 +1,92 @@
[util.smartptr.enab]
# 20 Memory management library [[mem]](./#mem)
## 20.3 Smart pointers [[smartptr]](smartptr#util.smartptr.enab)
### 20.3.2 Shared-ownership pointers [[util.sharedptr]](util.sharedptr#util.smartptr.enab)
#### 20.3.2.7 Class template enable_shared_from_this [util.smartptr.enab]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5289)
A class T can inherit from enable_shared_from_this<T> to inherit the shared_from_this member functions that obtain
a shared_ptr instance pointing to *this[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5295)
[*Example [1](#example-1)*: struct X: public enable_shared_from_this<X> { };
int main() { shared_ptr<X> p(new X);
shared_ptr<X> q = p->shared_from_this();
assert(p == q);
assert(p.owner_equal(q)); // p and q share ownership} — *end example*]
namespace std {template<class T> class enable_shared_from_this {protected:constexpr enable_shared_from_this() noexcept; constexpr enable_shared_from_this(const enable_shared_from_this&) noexcept; constexpr enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept; constexpr ~enable_shared_from_this(); public:constexpr shared_ptr<T> shared_from_this(); constexpr shared_ptr<T const> shared_from_this() const; constexpr weak_ptr<T> weak_from_this() noexcept; constexpr weak_ptr<T const> weak_from_this() const noexcept; private:mutable weak_ptr<T> *weak-this*; // *exposition only*};}
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5330)
The template parameter T of enable_shared_from_this may be an incomplete type[.](#3.sentence-1)
[🔗](#lib:enable_shared_from_this,constructor)
`constexpr enable_shared_from_this() noexcept;
constexpr enable_shared_from_this(const enable_shared_from_this<T>&) noexcept;
`
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5341)
*Effects*: Value-initializes *weak-this*[.](#4.sentence-1)
[🔗](#lib:operator=,enable_shared_from_this)
`constexpr enable_shared_from_this<T>& operator=(const enable_shared_from_this<T>&) noexcept;
`
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5352)
*Returns*: *this[.](#5.sentence-1)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5356)
[*Note [1](#note-1)*:
*weak-this* is not changed[.](#6.sentence-1)
— *end note*]
[🔗](#lib:shared_ptr)
`constexpr shared_ptr<T> shared_from_this();
constexpr shared_ptr<T const> shared_from_this() const;
`
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5370)
*Returns*: shared_ptr<T>(*weak-this*)[.](#7.sentence-1)
[🔗](#lib:weak_ptr)
`constexpr weak_ptr<T> weak_from_this() noexcept;
constexpr weak_ptr<T const> weak_from_this() const noexcept;
`
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5383)
*Returns*: *weak-this*[.](#8.sentence-1)

View File

@@ -0,0 +1,37 @@
[util.smartptr.getdeleter]
# 20 Memory management library [[mem]](./#mem)
## 20.3 Smart pointers [[smartptr]](smartptr#util.smartptr.getdeleter)
### 20.3.2 Shared-ownership pointers [[util.sharedptr]](util.sharedptr#util.smartptr.getdeleter)
#### 20.3.2.2 Class template shared_ptr [[util.smartptr.shared]](util.smartptr.shared#util.smartptr.getdeleter)
#### 20.3.2.2.11 get_deleter [util.smartptr.getdeleter]
[🔗](#lib:get_deleter,shared_ptr)
`template<class D, class T>
constexpr D* get_deleter(const shared_ptr<T>& p) noexcept;
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4802)
*Returns*: If p owns a deleter d of type cv-unqualifiedD, returns addressof(d); otherwise returns nullptr[.](#1.sentence-1)
The returned
pointer remains valid as long as there exists a shared_ptr instance
that owns d[.](#1.sentence-2)
[*Note [1](#note-1)*:
It is unspecified whether the pointer
remains valid longer than that[.](#1.sentence-3)
This can happen if the implementation doesn't destroy
the deleter until all weak_ptr instances that share ownership withp have been destroyed[.](#1.sentence-4)
— *end note*]

View File

@@ -0,0 +1,37 @@
[util.smartptr.hash]
# 20 Memory management library [[mem]](./#mem)
## 20.3 Smart pointers [[smartptr]](smartptr#util.smartptr.hash)
### 20.3.3 Smart pointer hash support [util.smartptr.hash]
[🔗](#lib:hash,unique_ptr)
`template<class T, class D> struct hash<unique_ptr<T, D>>;
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5396)
Letting UP be unique_ptr<T, D>,
the specialization hash<UP> is enabled ([[unord.hash]](unord.hash "22.10.19Class template hash"))
if and only if hash<typename UP::pointer> is enabled[.](#1.sentence-1)
When enabled, for an object p of type UP,hash<UP>()(p) evaluates to
the same value as hash<typename UP::pointer>()(p.get())[.](#1.sentence-2)
The member functions are not guaranteed to be noexcept[.](#1.sentence-3)
[🔗](#lib:hash,shared_ptr)
`template<class T> struct hash<shared_ptr<T>>;
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5412)
For an object p of type shared_ptr<T>,hash<shared_ptr<T>>()(p) evaluates to
the same value as hash<typename shared_ptr<T>::element_type*>()(p.get())[.](#2.sentence-1)

View File

@@ -0,0 +1,48 @@
[util.smartptr.owner.equal]
# 20 Memory management library [[mem]](./#mem)
## 20.3 Smart pointers [[smartptr]](smartptr#util.smartptr.owner.equal)
### 20.3.2 Shared-ownership pointers [[util.sharedptr]](util.sharedptr#util.smartptr.owner.equal)
#### 20.3.2.6 Struct owner_equal [util.smartptr.owner.equal]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5241)
The class owner_equal provides
ownership-based mixed equality comparisons of shared and weak pointers[.](#1.sentence-1)
[🔗](#lib:owner_equal)
namespace std {struct owner_equal {template<class T, class U>constexpr bool operator()(const shared_ptr<T>&, const shared_ptr<U>&) const noexcept; template<class T, class U>constexpr bool operator()(const shared_ptr<T>&, const weak_ptr<U>&) const noexcept; template<class T, class U>constexpr bool operator()(const weak_ptr<T>&, const shared_ptr<U>&) const noexcept; template<class T, class U>constexpr bool operator()(const weak_ptr<T>&, const weak_ptr<U>&) const noexcept; using is_transparent = *unspecified*; };}
[🔗](#lib:operator(),owner_equal)
`template<class T, class U>
constexpr bool operator()(const shared_ptr<T>& x, const shared_ptr<U>& y) const noexcept;
template<class T, class U>
constexpr bool operator()(const shared_ptr<T>& x, const weak_ptr<U>& y) const noexcept;
template<class T, class U>
constexpr bool operator()(const weak_ptr<T>& x, const shared_ptr<U>& y) const noexcept;
template<class T, class U>
constexpr bool operator()(const weak_ptr<T>& x, const weak_ptr<U>& y) const noexcept;
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5276)
*Returns*: x.owner_equal(y)[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5280)
[*Note [1](#note-1)*:
x.owner_equal(y) is true if and only if x and y share ownership or are both empty[.](#3.sentence-1)
— *end note*]

View File

@@ -0,0 +1,43 @@
[util.smartptr.owner.hash]
# 20 Memory management library [[mem]](./#mem)
## 20.3 Smart pointers [[smartptr]](smartptr#util.smartptr.owner.hash)
### 20.3.2 Shared-ownership pointers [[util.sharedptr]](util.sharedptr#util.smartptr.owner.hash)
#### 20.3.2.5 Struct owner_hash [util.smartptr.owner.hash]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5201)
The class owner_hash provides ownership-based hashing[.](#1.sentence-1)
[🔗](#lib:owner_hash)
namespace std {struct owner_hash {template<class T> size_t operator()(const shared_ptr<T>&) const noexcept; template<class T> size_t operator()(const weak_ptr<T>&) const noexcept; using is_transparent = *unspecified*; };}
[🔗](#lib:operator(),owner_hash)
`template<class T>
size_t operator()(const shared_ptr<T>& x) const noexcept;
template<class T>
size_t operator()(const weak_ptr<T>& x) const noexcept;
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5228)
*Returns*: x.owner_hash()[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5232)
[*Note [1](#note-1)*:
For any object y where x.owner_equal(y) is true,x.owner_hash() == y.owner_hash() is true[.](#3.sentence-1)
— *end note*]

View File

@@ -0,0 +1,40 @@
[util.smartptr.ownerless]
# 20 Memory management library [[mem]](./#mem)
## 20.3 Smart pointers [[smartptr]](smartptr#util.smartptr.ownerless)
### 20.3.2 Shared-ownership pointers [[util.sharedptr]](util.sharedptr#util.smartptr.ownerless)
#### 20.3.2.4 Class template owner_less [util.smartptr.ownerless]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5149)
The class template owner_less allows ownership-based mixed comparisons of shared
and weak pointers[.](#1.sentence-1)
[🔗](#lib:owner_less)
namespace std {template<class T = void> struct owner_less; template<class T> struct owner_less<shared_ptr<T>> {constexpr bool operator()(const shared_ptr<T>&, const shared_ptr<T>&) const noexcept; constexpr bool operator()(const shared_ptr<T>&, const weak_ptr<T>&) const noexcept; constexpr bool operator()(const weak_ptr<T>&, const shared_ptr<T>&) const noexcept; }; template<class T> struct owner_less<weak_ptr<T>> {constexpr bool operator()(const weak_ptr<T>&, const weak_ptr<T>&) const noexcept; constexpr bool operator()(const shared_ptr<T>&, const weak_ptr<T>&) const noexcept; constexpr bool operator()(const weak_ptr<T>&, const shared_ptr<T>&) const noexcept; }; template<> struct owner_less<void> {template<class T, class U>constexpr bool operator()(const shared_ptr<T>&, const shared_ptr<U>&) const noexcept; template<class T, class U>constexpr bool operator()(const shared_ptr<T>&, const weak_ptr<U>&) const noexcept; template<class T, class U>constexpr bool operator()(const weak_ptr<T>&, const shared_ptr<U>&) const noexcept; template<class T, class U>constexpr bool operator()(const weak_ptr<T>&, const weak_ptr<U>&) const noexcept; using is_transparent = *unspecified*; };}
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5186)
operator()(x, y) returns x.owner_before(y)[.](#2.sentence-1)
[*Note [1](#note-1)*:
Note that
- [(2.1)](#2.1)
operator() defines a strict weak ordering as defined in [[alg.sorting]](alg.sorting "26.8Sorting and related operations");
- [(2.2)](#2.2)
!operator()(a, b) && !operator()(b, a) is true if and only if a.owner_equal(b) is true[.](#2.sentence-2)
— *end note*]

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,83 @@
[util.smartptr.shared.assign]
# 20 Memory management library [[mem]](./#mem)
## 20.3 Smart pointers [[smartptr]](smartptr#util.smartptr.shared.assign)
### 20.3.2 Shared-ownership pointers [[util.sharedptr]](util.sharedptr#util.smartptr.shared.assign)
#### 20.3.2.2 Class template shared_ptr [[util.smartptr.shared]](util.smartptr.shared#assign)
#### 20.3.2.2.4 Assignment [util.smartptr.shared.assign]
[🔗](#lib:operator=,shared_ptr)
`constexpr shared_ptr& operator=(const shared_ptr& r) noexcept;
template<class Y> constexpr shared_ptr& operator=(const shared_ptr<Y>& r) noexcept;
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3914)
*Effects*: Equivalent to shared_ptr(r).swap(*this)[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3918)
*Returns*: *this[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3922)
[*Note [1](#note-1)*:
The use count updates caused by the temporary object
construction and destruction are not observable side
effects, so the implementation can meet the effects (and the
implied guarantees) via different means, without creating a
temporary[.](#3.sentence-1)
In particular, in the example:shared_ptr<int> p(new int);
shared_ptr<void> q(p);
p = p;
q = p; both assignments can be no-ops[.](#3.sentence-2)
— *end note*]
[🔗](#lib:operator=,shared_ptr_)
`constexpr shared_ptr& operator=(shared_ptr&& r) noexcept;
template<class Y> constexpr shared_ptr& operator=(shared_ptr<Y>&& r) noexcept;
`
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3946)
*Effects*: Equivalent to shared_ptr(std::move(r)).swap(*this)[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3950)
*Returns*: *this[.](#5.sentence-1)
[🔗](#lib:operator=,shared_ptr__)
`template<class Y, class D> constexpr shared_ptr& operator=(unique_ptr<Y, D>&& r);
`
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3961)
*Effects*: Equivalent to shared_ptr(std::move(r)).swap(*this)[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3965)
*Returns*: *this[.](#7.sentence-1)

View File

@@ -0,0 +1,152 @@
[util.smartptr.shared.cast]
# 20 Memory management library [[mem]](./#mem)
## 20.3 Smart pointers [[smartptr]](smartptr#util.smartptr.shared.cast)
### 20.3.2 Shared-ownership pointers [[util.sharedptr]](util.sharedptr#util.smartptr.shared.cast)
#### 20.3.2.2 Class template shared_ptr [[util.smartptr.shared]](util.smartptr.shared#cast)
#### 20.3.2.2.10 Casts [util.smartptr.shared.cast]
[🔗](#lib:static_pointer_cast,shared_ptr)
`template<class T, class U>
constexpr shared_ptr<T> static_pointer_cast(const shared_ptr<U>& r) noexcept;
template<class T, class U>
constexpr shared_ptr<T> static_pointer_cast(shared_ptr<U>&& r) noexcept;
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4677)
*Mandates*: The expression static_cast<T*>((U*)nullptr) is well-formed[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4681)
*Returns*: shared_ptr<T>(*R*, static_cast<typename shared_ptr<T>::element_type*>(r.get())) where *R* is r for the first overload, andstd::move(r) for the second[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4689)
[*Note [1](#note-1)*:
The seemingly equivalent expressionshared_ptr<T>(static_cast<T*>(r.get())) can result in undefined behavior, attempting to delete the
same object twice[.](#3.sentence-1)
— *end note*]
[🔗](#lib:dynamic_pointer_cast,shared_ptr)
`template<class T, class U>
constexpr shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& r) noexcept;
template<class T, class U>
constexpr shared_ptr<T> dynamic_pointer_cast(shared_ptr<U>&& r) noexcept;
`
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4707)
*Mandates*: The expression dynamic_cast<T*>((U*)nullptr) is well-formed[.](#4.sentence-1)
The expression dynamic_cast<typename shared_ptr<T>::element_type*>(r.get()) is well-formed[.](#4.sentence-2)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4712)
*Preconditions*: The expression dynamic_cast<typename shared_ptr<T>::element_type*>(r.get()) has well-defined behavior[.](#5.sentence-1)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4716)
*Returns*:
- [(6.1)](#6.1)
When dynamic_cast<typename shared_ptr<T>::element_type*>(r.get()) returns a non-null value p, shared_ptr<T>(*R*, p),
where *R* is r for the first overload, and std::move(r) for the second[.](#6.1.sentence-1)
- [(6.2)](#6.2)
Otherwise, shared_ptr<T>()[.](#6.2.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4727)
[*Note [2](#note-2)*:
The seemingly equivalent expressionshared_ptr<T>(dynamic_cast<T*>(r.get())) can result in
undefined behavior, attempting to delete the same object twice[.](#7.sentence-1)
— *end note*]
[🔗](#lib:const_pointer_cast,shared_ptr)
`template<class T, class U>
constexpr shared_ptr<T> const_pointer_cast(const shared_ptr<U>& r) noexcept;
template<class T, class U>
constexpr shared_ptr<T> const_pointer_cast(shared_ptr<U>&& r) noexcept;
`
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4744)
*Mandates*: The expression const_cast<T*>((U*)nullptr) is well-formed[.](#8.sentence-1)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4748)
*Returns*: shared_ptr<T>(*R*, const_cast<typename shared_ptr<T>::element_type*>(r.get())) where *R* is r for the first overload, andstd::move(r) for the second[.](#9.sentence-1)
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4756)
[*Note [3](#note-3)*:
The seemingly equivalent expressionshared_ptr<T>(const_cast<T*>(r.get())) can result in
undefined behavior, attempting to delete the same object twice[.](#10.sentence-1)
— *end note*]
[🔗](#lib:reinterpret_pointer_cast,shared_ptr)
`template<class T, class U>
shared_ptr<T> reinterpret_pointer_cast(const shared_ptr<U>& r) noexcept;
template<class T, class U>
shared_ptr<T> reinterpret_pointer_cast(shared_ptr<U>&& r) noexcept;
`
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4773)
*Mandates*: The expression reinterpret_cast<T*>((U*)nullptr) is well-formed[.](#11.sentence-1)
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4777)
*Returns*: shared_ptr<T>(*R*, reinterpret_cast<typename shared_ptr<T>::element_type*>(r.get())) where *R* is r for the first overload, andstd::move(r) for the second[.](#12.sentence-1)
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4785)
[*Note [4](#note-4)*:
The seemingly equivalent expressionshared_ptr<T>(reinterpret_cast<T*>(r.get())) can result in
undefined behavior, attempting to delete the same object twice[.](#13.sentence-1)
— *end note*]

View File

@@ -0,0 +1,70 @@
[util.smartptr.shared.cmp]
# 20 Memory management library [[mem]](./#mem)
## 20.3 Smart pointers [[smartptr]](smartptr#util.smartptr.shared.cmp)
### 20.3.2 Shared-ownership pointers [[util.sharedptr]](util.sharedptr#util.smartptr.shared.cmp)
#### 20.3.2.2 Class template shared_ptr [[util.smartptr.shared]](util.smartptr.shared#cmp)
#### 20.3.2.2.8 Comparison [util.smartptr.shared.cmp]
[🔗](#lib:operator==,shared_ptr)
`template<class T, class U>
constexpr bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4603)
*Returns*: a.get() == b.get()[.](#1.sentence-1)
[🔗](#lib:operator==,shared_ptr_)
`template<class T>
constexpr bool operator==(const shared_ptr<T>& a, nullptr_t) noexcept;
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4615)
*Returns*: !a[.](#2.sentence-1)
[🔗](#lib:operator%3c=%3e,shared_ptr)
`template<class T, class U>
constexpr strong_ordering operator<=>(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
`
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4627)
*Returns*: compare_three_way()(a.get(), b.get())[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4631)
[*Note [1](#note-1)*:
Defining a comparison operator function allows shared_ptr objects
to be used as keys in associative containers[.](#4.sentence-1)
— *end note*]
[🔗](#lib:operator%3c=%3e,shared_ptr_)
`template<class T>
constexpr strong_ordering operator<=>(const shared_ptr<T>& a, nullptr_t) noexcept;
`
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4645)
*Returns*: compare_three_way()(a.get(), static_cast<typename shared_ptr<T>::element_type*>(nullptr))

View File

@@ -0,0 +1,309 @@
[util.smartptr.shared.const]
# 20 Memory management library [[mem]](./#mem)
## 20.3 Smart pointers [[smartptr]](smartptr#util.smartptr.shared.const)
### 20.3.2 Shared-ownership pointers [[util.sharedptr]](util.sharedptr#util.smartptr.shared.const)
#### 20.3.2.2 Class template shared_ptr [[util.smartptr.shared]](util.smartptr.shared#const)
#### 20.3.2.2.2 Constructors [util.smartptr.shared.const]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3617)
In the constructor definitions below,
enables shared_from_this with p,
for a pointer p of type Y*,
means that if Y has an unambiguous and accessible base class
that is a specialization of enable_shared_from_this ([[util.smartptr.enab]](util.smartptr.enab "20.3.2.7Class template enable_­shared_­from_­this")),
then remove_cv_t<Y>* shall be implicitly convertible to T* and
the constructor evaluates the statement:if (p != nullptr && p->*weak-this*.expired()) p->*weak-this* = shared_ptr<remove_cv_t<Y>>(*this, const_cast<remove_cv_t<Y>*>(p));
The assignment to the *weak-this* member is not atomic and
conflicts with any potentially concurrent access to the same object ([[intro.multithread]](intro.multithread "6.10.2Multi-threaded executions and data races"))[.](#1.sentence-2)
[🔗](#lib:shared_ptr,constructor)
`constexpr shared_ptr() noexcept;
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3638)
*Postconditions*: use_count() == 0 && get() == nullptr[.](#2.sentence-1)
[🔗](#lib:shared_ptr,constructor_)
`template<class Y> constexpr explicit shared_ptr(Y* p);
`
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3649)
*Constraints*: When T is an array type,
the expression delete[] p is well-formed and eitherT is U[N] and Y(*)[N] is convertible to T*, orT is U[] and Y(*)[] is convertible to T*[.](#3.sentence-1)
When T is not an array type,
the expression delete p is well-formed andY* is convertible to T*[.](#3.sentence-2)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3659)
*Mandates*: Y is a complete type[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3663)
*Preconditions*: The expressiondelete[] p, when T is an array type, ordelete p, when T is not an array type,
has well-defined behavior, and
does not throw exceptions[.](#5.sentence-1)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3671)
*Effects*: When T is not an array type,
constructs a shared_ptr object
that owns the pointer p[.](#6.sentence-1)
Otherwise, constructs a shared_ptr that owns p and a deleter of an
unspecified type that calls delete[] p[.](#6.sentence-2)
When T is not an array type,
enables shared_from_this with p[.](#6.sentence-3)
If an exception is thrown, delete p is called
when T is not an array type, delete[] p otherwise[.](#6.sentence-4)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3684)
*Postconditions*: use_count() == 1 && get() == p[.](#7.sentence-1)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3688)
*Throws*: bad_alloc, or an implementation-defined exception when a resource other than memory cannot be obtained[.](#8.sentence-1)
[🔗](#lib:shared_ptr,constructor__)
`template<class Y, class D> constexpr shared_ptr(Y* p, D d);
template<class Y, class D, class A> constexpr shared_ptr(Y* p, D d, A a);
template<class D> constexpr shared_ptr(nullptr_t p, D d);
template<class D, class A> constexpr shared_ptr(nullptr_t p, D d, A a);
`
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3703)
*Constraints*: is_move_constructible_v<D> is true, andd(p) is a well-formed expression[.](#9.sentence-1)
For the first two overloads:
- [(9.1)](#9.1)
If T is an array type, then eitherT is U[N] and Y(*)[N] is convertible to T*, orT is U[] and Y(*)[] is convertible to T*[.](#9.1.sentence-1)
- [(9.2)](#9.2)
If T is not an array type, then Y* is convertible to T*[.](#9.2.sentence-1)
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3718)
*Preconditions*: Construction of d and a deleter of type D initialized with std::move(d) do not throw exceptions[.](#10.sentence-1)
The expression d(p) has well-defined behavior and does not throw exceptions[.](#10.sentence-2)
A meets
the [*Cpp17Allocator*](allocator.requirements.general#:Cpp17Allocator "16.4.4.6.1General[allocator.requirements.general]") requirements ([[allocator.requirements.general]](allocator.requirements.general "16.4.4.6.1General"))[.](#10.sentence-3)
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3727)
*Effects*: Constructs a shared_ptr object that owns the
object p and the deleter d[.](#11.sentence-1)
When T is not an array type,
the first and second constructors enable shared_from_this with p[.](#11.sentence-2)
The second and fourth constructors shall use a copy of a to
allocate memory for internal use[.](#11.sentence-3)
If an exception is thrown, d(p) is called[.](#11.sentence-4)
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3737)
*Postconditions*: use_count() == 1 && get() == p[.](#12.sentence-1)
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3741)
*Throws*: bad_alloc, or an implementation-defined exception
when a resource other than memory cannot be obtained[.](#13.sentence-1)
[🔗](#lib:shared_ptr,constructor___)
`template<class Y> constexpr shared_ptr(const shared_ptr<Y>& r, element_type* p) noexcept;
template<class Y> constexpr shared_ptr(shared_ptr<Y>&& r, element_type* p) noexcept;
`
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3755)
*Effects*: Constructs a shared_ptr instance that
stores p and shares ownership with
the initial value of r[.](#14.sentence-1)
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3761)
*Postconditions*: get() == p[.](#15.sentence-1)
For the second overload,r is empty and r.get() == nullptr[.](#15.sentence-2)
[16](#16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3767)
[*Note [1](#note-1)*:
Use of this constructor leads to a dangling pointer
unless p remains valid
at least until the ownership group of r is destroyed[.](#16.sentence-1)
— *end note*]
[17](#17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3774)
[*Note [2](#note-2)*:
This constructor allows creation of an emptyshared_ptr instance with a non-null stored pointer[.](#17.sentence-1)
— *end note*]
[🔗](#lib:shared_ptr,constructor____)
`constexpr shared_ptr(const shared_ptr& r) noexcept;
template<class Y> constexpr shared_ptr(const shared_ptr<Y>& r) noexcept;
`
[18](#18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3788)
*Constraints*: For the second constructor, Y* is compatible with T*[.](#18.sentence-1)
[19](#19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3792)
*Effects*: If r is empty, constructs
an empty shared_ptr object; otherwise, constructs
a shared_ptr object that shares ownership with r[.](#19.sentence-1)
[20](#20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3798)
*Postconditions*: get() == r.get() && use_count() == r.use_count()[.](#20.sentence-1)
[🔗](#lib:shared_ptr,constructor_____)
`constexpr shared_ptr(shared_ptr&& r) noexcept;
template<class Y> constexpr shared_ptr(shared_ptr<Y>&& r) noexcept;
`
[21](#21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3810)
*Constraints*: For the second constructor, Y* is compatible with T*[.](#21.sentence-1)
[22](#22)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3814)
*Effects*: Move constructs a shared_ptr instance from r[.](#22.sentence-1)
[23](#23)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3818)
*Postconditions*: *this contains the old value ofr[.](#23.sentence-1)
r is empty, and r.get() == nullptr[.](#23.sentence-2)
[🔗](#lib:shared_ptr,constructor______)
`template<class Y> constexpr explicit shared_ptr(const weak_ptr<Y>& r);
`
[24](#24)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3831)
*Constraints*: Y* is compatible with T*[.](#24.sentence-1)
[25](#25)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3835)
*Effects*: Constructs a shared_ptr object that shares ownership withr and stores a copy of the pointer stored in r[.](#25.sentence-1)
If an exception is thrown, the constructor has no effect[.](#25.sentence-2)
[26](#26)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3841)
*Postconditions*: use_count() == r.use_count()[.](#26.sentence-1)
[27](#27)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3845)
*Throws*: bad_weak_ptr when r.expired()[.](#27.sentence-1)
[🔗](#lib:shared_ptr,constructor_______)
`template<class Y, class D> constexpr shared_ptr(unique_ptr<Y, D>&& r);
`
[28](#28)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3857)
*Constraints*: Y* is compatible with T* andunique_ptr<Y, D>::pointer is convertible to element_type*[.](#28.sentence-1)
[29](#29)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3862)
*Effects*: If r.get() == nullptr, equivalent to shared_ptr()[.](#29.sentence-1)
Otherwise, if D is not a reference type,
equivalent to shared_ptr(r.release(), std::move(r.get_deleter()))[.](#29.sentence-2)
Otherwise, equivalent to shared_ptr(r.release(), ref(r.get_deleter()))[.](#29.sentence-3)
If an exception is thrown, the constructor has no effect[.](#29.sentence-4)

View File

@@ -0,0 +1,379 @@
[util.smartptr.shared.create]
# 20 Memory management library [[mem]](./#mem)
## 20.3 Smart pointers [[smartptr]](smartptr#util.smartptr.shared.create)
### 20.3.2 Shared-ownership pointers [[util.sharedptr]](util.sharedptr#util.smartptr.shared.create)
#### 20.3.2.2 Class template shared_ptr [[util.smartptr.shared]](util.smartptr.shared#create)
#### 20.3.2.2.7 Creation [util.smartptr.shared.create]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4220)
The common requirements that apply to allmake_shared,allocate_shared,make_shared_for_overwrite, andallocate_shared_for_overwrite overloads,
unless specified otherwise, are described below[.](#1.sentence-1)
[🔗](#lib:make_shared)
`template<class T, ...>
constexpr shared_ptr<T> make_shared(args);
template<class T, class A, ...>
constexpr shared_ptr<T> allocate_shared(const A& a, args);
template<class T, ...>
constexpr shared_ptr<T> make_shared_for_overwrite(args);
template<class T, class A, ...>
constexpr shared_ptr<T> allocate_shared_for_overwrite(const A& a, args);
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4242)
*Preconditions*: A meets
the [*Cpp17Allocator*](allocator.requirements.general#:Cpp17Allocator "16.4.4.6.1General[allocator.requirements.general]") requirements ([[allocator.requirements.general]](allocator.requirements.general "16.4.4.6.1General"))[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4247)
*Effects*: Allocates memory for an object of type T (or U[N] when T is U[],
where N is determined from *args* as specified by the concrete overload)[.](#3.sentence-1)
The object is initialized from *args* as specified by the concrete overload[.](#3.sentence-2)
The allocate_shared and allocate_shared_for_overwrite templates
use a copy of a (rebound for an unspecified value_type) to allocate memory[.](#3.sentence-3)
If an exception is thrown, the functions have no effect[.](#3.sentence-4)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4258)
*Postconditions*: r.get() != nullptr && r.use_count() == 1,
where r is the return value[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4263)
*Returns*: A shared_ptr instance that stores and owns the address of
the newly constructed object[.](#5.sentence-1)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4268)
*Throws*: bad_alloc, or
an exception thrown from allocate or from the initialization of the object[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4273)
*Remarks*:
- [(7.1)](#7.1)
Implementations should perform no more than one memory allocation[.](#7.1.sentence-1)
[*Note [1](#note-1)*:
This provides efficiency equivalent to an intrusive smart pointer[.](#7.1.sentence-2)
— *end note*]
- [(7.2)](#7.2)
When an object of an array type U is specified to have
an initial value of u (of the same type),
this shall be interpreted to mean that
each array element of the object has as its initial value
the corresponding element from u[.](#7.2.sentence-1)
- [(7.3)](#7.3)
When an object of an array type is specified to have
a default initial value,
this shall be interpreted to mean that each array element of the object
has a default initial value[.](#7.3.sentence-1)
- [(7.4)](#7.4)
When a (sub)object of a non-array type U is specified to have
an initial value of v, or U(l...),
where l... is a list of constructor arguments, make_shared shall initialize this (sub)object
via the expression ::new(pv) U(v) or ::new(pv) U(l...) respectively,
where pv has type void* and points to storage
suitable to hold an object of type U[.](#7.4.sentence-1)
- [(7.5)](#7.5)
When a (sub)object of a non-array type U is specified to have
an initial value of v, or U(l...),
where l... is a list of constructor arguments, allocate_shared shall initialize this (sub)object
via the expression
* [(7.5.1)](#7.5.1)
allocator_traits<A2>::construct(a2, pu, v) or
* [(7.5.2)](#7.5.2)
allocator_traits<A2>::construct(a2, pu, l...)
respectively,
where pu is a pointer of type remove_cv_t<U>* pointing to storage
suitable to hold an object of type remove_cv_t<U> and a2 of type A2 is a potentially rebound copy of
the allocator a passed to allocate_shared[.](#7.5.sentence-1)
- [(7.6)](#7.6)
When a (sub)object of non-array type U is specified to have
a default initial value, make_shared shall initialize this (sub)object
via the expression ::new(pv) U(),
where pv has type void* and points to storage
suitable to hold an object of type U[.](#7.6.sentence-1)
- [(7.7)](#7.7)
When a (sub)object of non-array type U is specified to have
a default initial value, allocate_shared initializes this (sub)object
via the expression allocator_traits<A2>::construct(a2, pu),
where pu is a pointer of type remove_cv_t<U>* pointing to storage
suitable to hold an object of type remove_cv_t<U> and a2 of type A2 is a potentially rebound copy of
the allocator a passed to allocate_shared[.](#7.7.sentence-1)
- [(7.8)](#7.8)
When a (sub)object of non-array type U is initialized by make_shared_for_overwrite or allocate_shared_for_overwrite,
it is initialized via the expression ::new(pv) U,
where pv has type void* and
points to storage suitable to hold an object of type U[.](#7.8.sentence-1)
- [(7.9)](#7.9)
Array elements are initialized in ascending order of their addresses[.](#7.9.sentence-1)
- [(7.10)](#7.10)
When the lifetime of the object managed by the return value ends, or
when the initialization of an array element throws an exception,
the initialized elements are destroyed in the reverse order
of their original construction[.](#7.10.sentence-1)
- [(7.11)](#7.11)
When a (sub)object of non-array type U that was initialized by make_shared, make_shared_for_overwrite, or allocate_shared_for_overwrite is to be destroyed,
it is destroyed via the expression pu->~U() where pu points to that object of type U[.](#7.11.sentence-1)
- [(7.12)](#7.12)
When a (sub)object of non-array type U that was initialized by allocate_shared is to be destroyed,
it is destroyed via the expression allocator_traits<A2>::destroy(a2, pu) where pu is a pointer of type remove_cv_t<U>* pointing to that object of type remove_cv_t<U> and a2 of type A2 is a potentially rebound copy of
the allocator a passed to allocate_shared[.](#7.12.sentence-1)
[*Note [2](#note-2)*:
These functions will typically allocate more memory than sizeof(T) to
allow for internal bookkeeping structures such as reference counts[.](#7.sentence-2)
— *end note*]
[🔗](#lib:make_shared_)
`template<class T, class... Args>
constexpr shared_ptr<T> make_shared(Args&&... args); // T is not array
template<class T, class A, class... Args>
constexpr shared_ptr<T> allocate_shared(const A& a, Args&&... args); // T is not array
`
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4380)
*Constraints*: T is not an array type[.](#8.sentence-1)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4384)
*Returns*: A shared_ptr to an object of type T with an initial value T(std::forward<Args>(args)...)[.](#9.sentence-1)
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4389)
*Remarks*: The shared_ptr constructors called by these functions
enable shared_from_this with the address of the newly constructed object of type T[.](#10.sentence-1)
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4395)
[*Example [1](#example-1)*: shared_ptr<int> p = make_shared<int>(); // shared_ptr to int() shared_ptr<vector<int>> q = make_shared<vector<int>>(16, 1); // shared_ptr to vector of 16 elements with value 1 — *end example*]
[🔗](#lib:make_shared__)
`template<class T>
constexpr shared_ptr<T> make_shared(size_t N); // T is U[]
template<class T, class A>
constexpr shared_ptr<T> allocate_shared(const A& a, size_t N); // T is U[]
`
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4415)
*Constraints*: T is of the form U[][.](#12.sentence-1)
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4419)
*Returns*: A shared_ptr to an object of type U[N] with a default initial value,
where U is remove_extent_t<T>[.](#13.sentence-1)
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4425)
[*Example [2](#example-2)*: shared_ptr<double[]> p = make_shared<double[]>(1024); // shared_ptr to a value-initialized double[1024] shared_ptr<double[][2][2]> q = make_shared<double[][2][2]>(6); // shared_ptr to a value-initialized double[6][2][2] — *end example*]
[🔗](#lib:make_shared___)
`template<class T>
constexpr shared_ptr<T> make_shared(); // T is U[N]
template<class T, class A>
constexpr shared_ptr<T> allocate_shared(const A& a); // T is U[N]
`
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4446)
*Constraints*: T is of the form U[N][.](#15.sentence-1)
[16](#16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4450)
*Returns*: A shared_ptr to an object of type T with a default initial value[.](#16.sentence-1)
[17](#17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4455)
[*Example [3](#example-3)*: shared_ptr<double[1024]> p = make_shared<double[1024]>(); // shared_ptr to a value-initialized double[1024] shared_ptr<double[6][2][2]> q = make_shared<double[6][2][2]>(); // shared_ptr to a value-initialized double[6][2][2] — *end example*]
[🔗](#lib:make_shared____)
`template<class T>
constexpr shared_ptr<T> make_shared(size_t N,
const remove_extent_t<T>& u); // T is U[]
template<class T, class A>
constexpr shared_ptr<T> allocate_shared(const A& a, size_t N,
const remove_extent_t<T>& u); // T is U[]
`
[18](#18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4478)
*Constraints*: T is of the form U[][.](#18.sentence-1)
[19](#19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4482)
*Returns*: A shared_ptr to an object of type U[N],
where U is remove_extent_t<T> and
each array element has an initial value of u[.](#19.sentence-1)
[20](#20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4488)
[*Example [4](#example-4)*: shared_ptr<double[]> p = make_shared<double[]>(1024, 1.0); // shared_ptr to a double[1024], where each element is 1.0 shared_ptr<double[][2]> q = make_shared<double[][2]>(6, {1.0, 0.0}); // shared_ptr to a double[6][2], where each double[2] element is {1.0, 0.0} shared_ptr<vector<int>[]> r = make_shared<vector<int>[]>(4, {1, 2}); // shared_ptr to a vector<int>[4], where each vector has contents {1, 2} — *end example*]
[🔗](#lib:make_shared_____)
`template<class T>
constexpr shared_ptr<T> make_shared(const remove_extent_t<T>& u); // T is U[N]
template<class T, class A>
constexpr shared_ptr<T> allocate_shared(const A& a,
const remove_extent_t<T>& u); // T is U[N]
`
[21](#21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4512)
*Constraints*: T is of the form U[N][.](#21.sentence-1)
[22](#22)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4516)
*Returns*: A shared_ptr to an object of type T,
where each array element of type remove_extent_t<T> has an initial value of u[.](#22.sentence-1)
[23](#23)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4522)
[*Example [5](#example-5)*: shared_ptr<double[1024]> p = make_shared<double[1024]>(1.0); // shared_ptr to a double[1024], where each element is 1.0 shared_ptr<double[6][2]> q = make_shared<double[6][2]>({1.0, 0.0}); // shared_ptr to a double[6][2], where each double[2] element is {1.0, 0.0} shared_ptr<vector<int>[4]> r = make_shared<vector<int>[4]>({1, 2}); // shared_ptr to a vector<int>[4], where each vector has contents {1, 2} — *end example*]
[🔗](#lib:make_shared______)
`template<class T>
constexpr shared_ptr<T> make_shared_for_overwrite();
template<class T, class A>
constexpr shared_ptr<T> allocate_shared_for_overwrite(const A& a);
`
[24](#24)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4545)
*Constraints*: T is not an array of unknown bound[.](#24.sentence-1)
[25](#25)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4549)
*Returns*: A shared_ptr to an object of type T[.](#25.sentence-1)
[26](#26)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4553)
[*Example [6](#example-6)*: struct X { double data[1024]; };
shared_ptr<X> p = make_shared_for_overwrite<X>(); // shared_ptr to a default-initialized X, where each element in X::data has an indeterminate value shared_ptr<double[1024]> q = make_shared_for_overwrite<double[1024]>(); // shared_ptr to a default-initialized double[1024], where each element has an indeterminate value — *end example*]
[🔗](#lib:make_shared_______)
`template<class T>
constexpr shared_ptr<T> make_shared_for_overwrite(size_t N);
template<class T, class A>
constexpr shared_ptr<T> allocate_shared_for_overwrite(const A& a, size_t N);
`
[27](#27)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4576)
*Constraints*: T is an array of unknown bound[.](#27.sentence-1)
[28](#28)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4580)
*Returns*: A shared_ptr to an object of type U[N],
where U is remove_extent_t<T>[.](#28.sentence-1)
[29](#29)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4585)
[*Example [7](#example-7)*: shared_ptr<double[]> p = make_shared_for_overwrite<double[]>(1024); // shared_ptr to a default-initialized double[1024], where each element has an indeterminate value — *end example*]

View File

@@ -0,0 +1,48 @@
[util.smartptr.shared.dest]
# 20 Memory management library [[mem]](./#mem)
## 20.3 Smart pointers [[smartptr]](smartptr#util.smartptr.shared.dest)
### 20.3.2 Shared-ownership pointers [[util.sharedptr]](util.sharedptr#util.smartptr.shared.dest)
#### 20.3.2.2 Class template shared_ptr [[util.smartptr.shared]](util.smartptr.shared#dest)
#### 20.3.2.2.3 Destructor [util.smartptr.shared.dest]
[🔗](#lib:shared_ptr,destructor)
`constexpr ~shared_ptr();
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3879)
*Effects*:
- [(1.1)](#1.1)
If *this is empty or shares ownership with anothershared_ptr instance (use_count() > 1), there are no side effects[.](#1.1.sentence-1)
- [(1.2)](#1.2)
Otherwise, if *this owns an objectp and a deleter d, d(p) is called[.](#1.2.sentence-1)
- [(1.3)](#1.3)
Otherwise, *this owns a pointer p,
and delete p is called[.](#1.3.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3894)
[*Note [1](#note-1)*:
Since the destruction of *this decreases the number of instances that share ownership with *this by one,
after *this has been destroyed
all shared_ptr instances that shared ownership with*this will report a use_count() that is one less
than its previous value[.](#2.sentence-1)
— *end note*]

View File

@@ -0,0 +1,74 @@
[util.smartptr.shared.general]
# 20 Memory management library [[mem]](./#mem)
## 20.3 Smart pointers [[smartptr]](smartptr#util.smartptr.shared.general)
### 20.3.2 Shared-ownership pointers [[util.sharedptr]](util.sharedptr#util.smartptr.shared.general)
#### 20.3.2.2 Class template shared_ptr [[util.smartptr.shared]](util.smartptr.shared#general)
#### 20.3.2.2.1 General [util.smartptr.shared.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3487)
The shared_ptr class template stores a pointer, usually obtained
via new[.](#1.sentence-1)
shared_ptr implements semantics of shared ownership;
the last remaining owner of the pointer is responsible for destroying
the object, or otherwise releasing the resources associated with the stored pointer[.](#1.sentence-2)
Ashared_ptr is said to be empty if it does not own a pointer[.](#1.sentence-3)
namespace std {template<class T> class shared_ptr {public:using element_type = remove_extent_t<T>; using weak_type = weak_ptr<T>; // [[util.smartptr.shared.const]](util.smartptr.shared.const "20.3.2.2.2Constructors"), constructorsconstexpr shared_ptr() noexcept; constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { }template<class Y>constexpr explicit shared_ptr(Y* p); template<class Y, class D>constexpr shared_ptr(Y* p, D d); template<class Y, class D, class A>constexpr shared_ptr(Y* p, D d, A a); template<class D>constexpr shared_ptr(nullptr_t p, D d); template<class D, class A>constexpr shared_ptr(nullptr_t p, D d, A a); template<class Y>constexpr shared_ptr(const shared_ptr<Y>& r, element_type* p) noexcept; template<class Y>constexpr shared_ptr(shared_ptr<Y>&& r, element_type* p) noexcept; constexpr shared_ptr(const shared_ptr& r) noexcept; template<class Y>constexpr shared_ptr(const shared_ptr<Y>& r) noexcept; constexpr shared_ptr(shared_ptr&& r) noexcept; template<class Y>constexpr shared_ptr(shared_ptr<Y>&& r) noexcept; template<class Y>constexpr explicit shared_ptr(const weak_ptr<Y>& r); template<class Y, class D>constexpr shared_ptr(unique_ptr<Y, D>&& r); // [[util.smartptr.shared.dest]](util.smartptr.shared.dest "20.3.2.2.3Destructor"), destructorconstexpr ~shared_ptr(); // [[util.smartptr.shared.assign]](util.smartptr.shared.assign "20.3.2.2.4Assignment"), assignmentconstexpr shared_ptr& operator=(const shared_ptr& r) noexcept; template<class Y>constexpr shared_ptr& operator=(const shared_ptr<Y>& r) noexcept; constexpr shared_ptr& operator=(shared_ptr&& r) noexcept; template<class Y>constexpr shared_ptr& operator=(shared_ptr<Y>&& r) noexcept; template<class Y, class D>constexpr shared_ptr& operator=(unique_ptr<Y, D>&& r); // [[util.smartptr.shared.mod]](util.smartptr.shared.mod "20.3.2.2.5Modifiers"), modifiersconstexpr void swap(shared_ptr& r) noexcept; constexpr void reset() noexcept; template<class Y>constexpr void reset(Y* p); template<class Y, class D>constexpr void reset(Y* p, D d); template<class Y, class D, class A>constexpr void reset(Y* p, D d, A a); // [[util.smartptr.shared.obs]](util.smartptr.shared.obs "20.3.2.2.6Observers"), observersconstexpr element_type* get() const noexcept; constexpr T& operator*() const noexcept; constexpr T* operator->() const noexcept; constexpr element_type& operator[](ptrdiff_t i) const; constexpr long use_count() const noexcept; constexpr explicit operator bool() const noexcept; template<class U>constexpr bool owner_before(const shared_ptr<U>& b) const noexcept; template<class U>constexpr bool owner_before(const weak_ptr<U>& b) const noexcept;
size_t owner_hash() const noexcept; template<class U>constexpr bool owner_equal(const shared_ptr<U>& b) const noexcept; template<class U>constexpr bool owner_equal(const weak_ptr<U>& b) const noexcept; }; template<class T> shared_ptr(weak_ptr<T>) -> shared_ptr<T>; template<class T, class D> shared_ptr(unique_ptr<T, D>) -> shared_ptr<T>;}
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3578)
Specializations of shared_ptr shall be [*Cpp17CopyConstructible*](utility.arg.requirements#:Cpp17CopyConstructible "16.4.4.2Template argument requirements[utility.arg.requirements]"),[*Cpp17CopyAssignable*](utility.arg.requirements#:Cpp17CopyAssignable "16.4.4.2Template argument requirements[utility.arg.requirements]"), and [*Cpp17LessThanComparable*](utility.arg.requirements#:Cpp17LessThanComparable "16.4.4.2Template argument requirements[utility.arg.requirements]"), allowing their use in standard
containers[.](#2.sentence-1)
Specializations of shared_ptr shall be
contextually convertible to bool,
allowing their use in boolean expressions and declarations in conditions[.](#2.sentence-2)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3585)
The template parameter T of shared_ptr may be an incomplete type[.](#3.sentence-1)
[*Note [1](#note-1)*:
T can be a function type[.](#3.sentence-2)
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3592)
[*Example [1](#example-1)*: if (shared_ptr<X> px = dynamic_pointer_cast<X>(py)) {// do something with px} — *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3601)
For purposes of determining the presence of a data race, member functions shall
access and modify only the shared_ptr and weak_ptr objects
themselves and not objects they refer to[.](#5.sentence-1)
Changes in use_count() do not
reflect modifications that can introduce data races[.](#5.sentence-2)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3607)
For the purposes of [[smartptr]](smartptr "20.3Smart pointers"),
a pointer type Y* is said to be[*compatible with*](#def:compatible_with,shared_ptr "20.3.2.2.1General[util.smartptr.shared.general]") a pointer type T* when eitherY* is convertible to T* orY is U[N] and T is cv U[][.](#6.sentence-1)

View File

@@ -0,0 +1,29 @@
[util.smartptr.shared.io]
# 20 Memory management library [[mem]](./#mem)
## 20.3 Smart pointers [[smartptr]](smartptr#util.smartptr.shared.io)
### 20.3.2 Shared-ownership pointers [[util.sharedptr]](util.sharedptr#util.smartptr.shared.io)
#### 20.3.2.2 Class template shared_ptr [[util.smartptr.shared]](util.smartptr.shared#io)
#### 20.3.2.2.12 I/O [util.smartptr.shared.io]
[🔗](#lib:operator%3c%3c,shared_ptr)
`template<class E, class T, class Y>
basic_ostream<E, T>& operator<<(basic_ostream<E, T>& os, const shared_ptr<Y>& p);
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4826)
*Effects*: As if by: os << p.get();
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4830)
*Returns*: os[.](#2.sentence-1)

View File

@@ -0,0 +1,66 @@
[util.smartptr.shared.mod]
# 20 Memory management library [[mem]](./#mem)
## 20.3 Smart pointers [[smartptr]](smartptr#util.smartptr.shared.mod)
### 20.3.2 Shared-ownership pointers [[util.sharedptr]](util.sharedptr#util.smartptr.shared.mod)
#### 20.3.2.2 Class template shared_ptr [[util.smartptr.shared]](util.smartptr.shared#mod)
#### 20.3.2.2.5 Modifiers [util.smartptr.shared.mod]
[🔗](#lib:swap,shared_ptr)
`constexpr void swap(shared_ptr& r) noexcept;
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3979)
*Effects*: Exchanges the contents of *this and r[.](#1.sentence-1)
[🔗](#lib:reset,shared_ptr)
`constexpr void reset() noexcept;
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3990)
*Effects*: Equivalent to shared_ptr().swap(*this)[.](#2.sentence-1)
[🔗](#lib:reset,shared_ptr_)
`template<class Y> constexpr void reset(Y* p);
`
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4001)
*Effects*: Equivalent to shared_ptr(p).swap(*this)[.](#3.sentence-1)
[🔗](#lib:reset,shared_ptr__)
`template<class Y, class D> constexpr void reset(Y* p, D d);
`
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4012)
*Effects*: Equivalent to shared_ptr(p, d).swap(*this)[.](#4.sentence-1)
[🔗](#lib:reset,shared_ptr___)
`template<class Y, class D, class A> constexpr void reset(Y* p, D d, A a);
`
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4023)
*Effects*: Equivalent to shared_ptr(p, d, a).swap(*this)[.](#5.sentence-1)

View File

@@ -0,0 +1,240 @@
[util.smartptr.shared.obs]
# 20 Memory management library [[mem]](./#mem)
## 20.3 Smart pointers [[smartptr]](smartptr#util.smartptr.shared.obs)
### 20.3.2 Shared-ownership pointers [[util.sharedptr]](util.sharedptr#util.smartptr.shared.obs)
#### 20.3.2.2 Class template shared_ptr [[util.smartptr.shared]](util.smartptr.shared#obs)
#### 20.3.2.2.6 Observers [util.smartptr.shared.obs]
[🔗](#lib:get,shared_ptr)
`constexpr element_type* get() const noexcept;
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4035)
*Returns*: The stored pointer[.](#1.sentence-1)
[🔗](#lib:operator*,shared_ptr)
`constexpr T& operator*() const noexcept;
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4046)
*Preconditions*: get() != nullptr[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4050)
*Returns*: *get()[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4054)
*Remarks*: When T is an array type or cv void,
it is unspecified whether this
member function is declared[.](#4.sentence-1)
If it is declared, it is unspecified what its
return type is, except that the declaration (although not necessarily the
definition) of the function shall be well-formed[.](#4.sentence-2)
[🔗](#lib:operator-%3e,shared_ptr)
`constexpr T* operator->() const noexcept;
`
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4069)
*Preconditions*: get() != nullptr[.](#5.sentence-1)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4073)
*Returns*: get()[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4077)
*Remarks*: When T is an array type,
it is unspecified whether this member function is declared[.](#7.sentence-1)
If it is declared, it is unspecified what its return type is,
except that the declaration (although not necessarily the definition)
of the function shall be well-formed[.](#7.sentence-2)
[🔗](#lib:operator%5b%5d,shared_ptr)
`constexpr element_type& operator[](ptrdiff_t i) const;
`
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4092)
*Preconditions*: get() != nullptr is true[.](#8.sentence-1)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4096)
*Hardened preconditions*: i ≥ 0[.](#9.sentence-1)
If T is U[N], i < N[.](#9.sentence-2)
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4100)
*Returns*: get()[i][.](#10.sentence-1)
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4104)
*Throws*: Nothing[.](#11.sentence-1)
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4108)
*Remarks*: When T is not an array type,
it is unspecified whether this member function is declared[.](#12.sentence-1)
If it is declared, it is unspecified what its return type is,
except that the declaration (although not necessarily the definition)
of the function shall be well-formed[.](#12.sentence-2)
[🔗](#lib:use_count,shared_ptr)
`constexpr long use_count() const noexcept;
`
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4123)
*Synchronization*: None[.](#13.sentence-1)
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4127)
*Returns*: The number of shared_ptr objects, *this included,
that share ownership with *this, or 0 when *this is
empty[.](#14.sentence-1)
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4133)
[*Note [1](#note-1)*:
get() == nullptr does not imply a specific return value of use_count()[.](#15.sentence-1)
— *end note*]
[16](#16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4139)
[*Note [2](#note-2)*:
weak_ptr<T>::lock() can affect the return value of use_count()[.](#16.sentence-1)
— *end note*]
[17](#17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4145)
[*Note [3](#note-3)*:
When multiple threads
might affect the return value of use_count(),
the result is approximate[.](#17.sentence-1)
In particular, use_count() == 1 does not imply that accesses through
a previously destroyed shared_ptr have in any sense completed[.](#17.sentence-2)
— *end note*]
[🔗](#lib:operator_bool,shared_ptr)
`constexpr explicit operator bool() const noexcept;
`
[18](#18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4161)
*Returns*: get() != nullptr[.](#18.sentence-1)
[🔗](#lib:owner_before,shared_ptr)
`template<class U> constexpr bool owner_before(const shared_ptr<U>& b) const noexcept;
template<class U> constexpr bool owner_before(const weak_ptr<U>& b) const noexcept;
`
[19](#19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4173)
*Returns*: An unspecified value such that
- [(19.1)](#19.1)
owner_before(b) defines a strict weak ordering as defined in [[alg.sorting]](alg.sorting "26.8Sorting and related operations");
- [(19.2)](#19.2)
!owner_before(b) && !b.owner_before(*this) is true if and only if owner_equal(b) is true[.](#19.sentence-1)
[🔗](#lib:owner_hash,shared_ptr)
`size_t owner_hash() const noexcept;
`
[20](#20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4191)
*Returns*: An unspecified value such that,
for any object x where owner_equal(x) is true,owner_hash() == x.owner_hash() is true[.](#20.sentence-1)
[🔗](#lib:owner_equal,shared_ptr)
`template<class U>
constexpr bool owner_equal(const shared_ptr<U>& b) const noexcept;
template<class U>
constexpr bool owner_equal(const weak_ptr<U>& b) const noexcept;
`
[21](#21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4207)
*Returns*: true if and only if*this and b share ownership or are both empty[.](#21.sentence-1)
Otherwise returns false[.](#21.sentence-2)
[22](#22)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4213)
*Remarks*: owner_equal is an equivalence relation[.](#22.sentence-1)

View File

@@ -0,0 +1,23 @@
[util.smartptr.shared.spec]
# 20 Memory management library [[mem]](./#mem)
## 20.3 Smart pointers [[smartptr]](smartptr#util.smartptr.shared.spec)
### 20.3.2 Shared-ownership pointers [[util.sharedptr]](util.sharedptr#util.smartptr.shared.spec)
#### 20.3.2.2 Class template shared_ptr [[util.smartptr.shared]](util.smartptr.shared#spec)
#### 20.3.2.2.9 Specialized algorithms [util.smartptr.shared.spec]
[🔗](#lib:swap,shared_ptr)
`template<class T>
constexpr void swap(shared_ptr<T>& a, shared_ptr<T>& b) noexcept;
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4661)
*Effects*: Equivalent to a.swap(b)[.](#1.sentence-1)

View File

@@ -0,0 +1,297 @@
[util.smartptr.weak]
# 20 Memory management library [[mem]](./#mem)
## 20.3 Smart pointers [[smartptr]](smartptr#util.smartptr.weak)
### 20.3.2 Shared-ownership pointers [[util.sharedptr]](util.sharedptr#util.smartptr.weak)
#### 20.3.2.3 Class template weak_ptr [util.smartptr.weak]
#### [20.3.2.3.1](#general) General [[util.smartptr.weak.general]](util.smartptr.weak.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4839)
The weak_ptr class template stores a weak reference to an object
that is already managed by a shared_ptr[.](#general-1.sentence-1)
To access the object, aweak_ptr can be converted to a shared_ptr using the member
function lock[.](#general-1.sentence-2)
namespace std {template<class T> class weak_ptr {public:using element_type = remove_extent_t<T>; // [[util.smartptr.weak.const]](#const "20.3.2.3.2Constructors"), constructorsconstexpr weak_ptr() noexcept; template<class Y>constexpr weak_ptr(const shared_ptr<Y>& r) noexcept; constexpr weak_ptr(const weak_ptr& r) noexcept; template<class Y>constexpr weak_ptr(const weak_ptr<Y>& r) noexcept; constexpr weak_ptr(weak_ptr&& r) noexcept; template<class Y>constexpr weak_ptr(weak_ptr<Y>&& r) noexcept; // [[util.smartptr.weak.dest]](#dest "20.3.2.3.3Destructor"), destructorconstexpr ~weak_ptr(); // [[util.smartptr.weak.assign]](#assign "20.3.2.3.4Assignment"), assignmentconstexpr weak_ptr& operator=(const weak_ptr& r) noexcept; template<class Y>constexpr weak_ptr& operator=(const weak_ptr<Y>& r) noexcept; template<class Y>constexpr weak_ptr& operator=(const shared_ptr<Y>& r) noexcept; constexpr weak_ptr& operator=(weak_ptr&& r) noexcept; template<class Y>constexpr weak_ptr& operator=(weak_ptr<Y>&& r) noexcept; // [[util.smartptr.weak.mod]](#mod "20.3.2.3.5Modifiers"), modifiersconstexpr void swap(weak_ptr& r) noexcept; constexpr void reset() noexcept; // [[util.smartptr.weak.obs]](#obs "20.3.2.3.6Observers"), observersconstexpr long use_count() const noexcept; constexpr bool expired() const noexcept; constexpr shared_ptr<T> lock() const noexcept; template<class U>constexpr bool owner_before(const shared_ptr<U>& b) const noexcept; template<class U>constexpr bool owner_before(const weak_ptr<U>& b) const noexcept;
size_t owner_hash() const noexcept; template<class U>constexpr bool owner_equal(const shared_ptr<U>& b) const noexcept; template<class U>constexpr bool owner_equal(const weak_ptr<U>& b) const noexcept; }; template<class T> weak_ptr(shared_ptr<T>) -> weak_ptr<T>;}
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4900)
Specializations of weak_ptr shall be [*Cpp17CopyConstructible*](utility.arg.requirements#:Cpp17CopyConstructible "16.4.4.2Template argument requirements[utility.arg.requirements]") and[*Cpp17CopyAssignable*](utility.arg.requirements#:Cpp17CopyAssignable "16.4.4.2Template argument requirements[utility.arg.requirements]"), allowing their use in standard
containers[.](#general-2.sentence-1)
The template parameter T of weak_ptr may be an
incomplete type[.](#general-2.sentence-2)
#### [20.3.2.3.2](#const) Constructors [[util.smartptr.weak.const]](util.smartptr.weak.const)
[🔗](#lib:weak_ptr,constructor)
`constexpr weak_ptr() noexcept;
`
[1](#const-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4914)
*Effects*: Constructs an empty weak_ptr object that stores a null pointer value[.](#const-1.sentence-1)
[2](#const-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4918)
*Postconditions*: use_count() == 0[.](#const-2.sentence-1)
[🔗](#lib:weak_ptr,constructor_)
`constexpr weak_ptr(const weak_ptr& r) noexcept;
template<class Y> constexpr weak_ptr(const weak_ptr<Y>& r) noexcept;
template<class Y> constexpr weak_ptr(const shared_ptr<Y>& r) noexcept;
`
[3](#const-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4931)
*Constraints*: For the second and third constructors, Y* is compatible with T*[.](#const-3.sentence-1)
[4](#const-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4935)
*Effects*: If r is empty, constructs
an empty weak_ptr object that stores a null pointer value;
otherwise, constructs
a weak_ptr object that shares ownership
with r and stores a copy of the pointer stored in r[.](#const-4.sentence-1)
[5](#const-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4943)
*Postconditions*: use_count() == r.use_count()[.](#const-5.sentence-1)
[🔗](#lib:weak_ptr,constructor__)
`constexpr weak_ptr(weak_ptr&& r) noexcept;
template<class Y> constexpr weak_ptr(weak_ptr<Y>&& r) noexcept;
`
[6](#const-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4955)
*Constraints*: For the second constructor, Y* is compatible with T*[.](#const-6.sentence-1)
[7](#const-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4959)
*Effects*: Move constructs a weak_ptr instance from r[.](#const-7.sentence-1)
[8](#const-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4963)
*Postconditions*: *this contains the old value of r[.](#const-8.sentence-1)
r is empty, stores a null pointer value, and r.use_count() == 0[.](#const-8.sentence-2)
#### [20.3.2.3.3](#dest) Destructor [[util.smartptr.weak.dest]](util.smartptr.weak.dest)
[🔗](#lib:weak_ptr,destructor)
`constexpr ~weak_ptr();
`
[1](#dest-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4977)
*Effects*: Destroys this weak_ptr object but has no
effect on the object its stored pointer points to[.](#dest-1.sentence-1)
#### [20.3.2.3.4](#assign) Assignment [[util.smartptr.weak.assign]](util.smartptr.weak.assign)
[🔗](#lib:operator=,weak_ptr)
`constexpr weak_ptr& operator=(const weak_ptr& r) noexcept;
template<class Y> constexpr weak_ptr& operator=(const weak_ptr<Y>& r) noexcept;
template<class Y> constexpr weak_ptr& operator=(const shared_ptr<Y>& r) noexcept;
`
[1](#assign-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4993)
*Effects*: Equivalent to weak_ptr(r).swap(*this)[.](#assign-1.sentence-1)
[2](#assign-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4997)
*Returns*: *this[.](#assign-2.sentence-1)
[3](#assign-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5001)
*Remarks*: The implementation may meet the effects (and the
implied guarantees) via different means, without creating a temporary object[.](#assign-3.sentence-1)
[🔗](#lib:operator=,weak_ptr_)
`constexpr weak_ptr& operator=(weak_ptr&& r) noexcept;
template<class Y> constexpr weak_ptr& operator=(weak_ptr<Y>&& r) noexcept;
`
[4](#assign-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5014)
*Effects*: Equivalent to weak_ptr(std::move(r)).swap(*this)[.](#assign-4.sentence-1)
[5](#assign-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5018)
*Returns*: *this[.](#assign-5.sentence-1)
#### [20.3.2.3.5](#mod) Modifiers [[util.smartptr.weak.mod]](util.smartptr.weak.mod)
[🔗](#lib:swap,weak_ptr)
`constexpr void swap(weak_ptr& r) noexcept;
`
[1](#mod-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5030)
*Effects*: Exchanges the contents of *this and r[.](#mod-1.sentence-1)
[🔗](#lib:reset,weak_ptr)
`constexpr void reset() noexcept;
`
[2](#mod-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5041)
*Effects*: Equivalent to weak_ptr().swap(*this)[.](#mod-2.sentence-1)
#### [20.3.2.3.6](#obs) Observers [[util.smartptr.weak.obs]](util.smartptr.weak.obs)
[🔗](#lib:use_count,weak_ptr)
`constexpr long use_count() const noexcept;
`
[1](#obs-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5053)
*Returns*: 0 if *this is empty;
otherwise, the number of shared_ptr instances
that share ownership with *this[.](#obs-1.sentence-1)
[🔗](#lib:expired,weak_ptr)
`constexpr bool expired() const noexcept;
`
[2](#obs-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5066)
*Returns*: use_count() == 0[.](#obs-2.sentence-1)
[🔗](#lib:lock,weak_ptr)
`constexpr shared_ptr<T> lock() const noexcept;
`
[3](#obs-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5077)
*Returns*: expired() ? shared_ptr<T>() : shared_ptr<T>(*this), executed atomically[.](#obs-3.sentence-1)
[🔗](#lib:owner_before,weak_ptr)
`template<class U> constexpr bool owner_before(const shared_ptr<U>& b) const noexcept;
template<class U> constexpr bool owner_before(const weak_ptr<U>& b) const noexcept;
`
[4](#obs-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5089)
*Returns*: An unspecified value such that
- [(4.1)](#obs-4.1)
owner_before(b) defines a strict weak ordering as defined in [[alg.sorting]](alg.sorting "26.8Sorting and related operations");
- [(4.2)](#obs-4.2)
!owner_before(b) && !b.owner_before(*this) is true if and only if owner_equal(b) is true[.](#obs-4.sentence-1)
[🔗](#lib:owner_hash,weak_ptr)
`size_t owner_hash() const noexcept;
`
[5](#obs-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5106)
*Returns*: An unspecified value such that,
for any object x where owner_equal(x) is true,owner_hash() == x.owner_hash() is true[.](#obs-5.sentence-1)
[🔗](#lib:owner_equal,weak_ptr)
`template<class U>
constexpr bool owner_equal(const shared_ptr<U>& b) const noexcept;
template<class U>
constexpr bool owner_equal(const weak_ptr<U>& b) const noexcept;
`
[6](#obs-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5122)
*Returns*: true if and only if*this and b share ownership or are both empty[.](#obs-6.sentence-1)
Otherwise returns false[.](#obs-6.sentence-2)
[7](#obs-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5128)
*Remarks*: owner_equal is an equivalence relation[.](#obs-7.sentence-1)
#### [20.3.2.3.7](#spec) Specialized algorithms [[util.smartptr.weak.spec]](util.smartptr.weak.spec)
[🔗](#lib:swap,weak_ptr_)
`template<class T>
constexpr void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept;
`
[1](#spec-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5142)
*Effects*: Equivalent to a.swap(b)[.](#spec-1.sentence-1)

View File

@@ -0,0 +1,55 @@
[util.smartptr.weak.assign]
# 20 Memory management library [[mem]](./#mem)
## 20.3 Smart pointers [[smartptr]](smartptr#util.smartptr.weak.assign)
### 20.3.2 Shared-ownership pointers [[util.sharedptr]](util.sharedptr#util.smartptr.weak.assign)
#### 20.3.2.3 Class template weak_ptr [[util.smartptr.weak]](util.smartptr.weak#assign)
#### 20.3.2.3.4 Assignment [util.smartptr.weak.assign]
[🔗](#lib:operator=,weak_ptr)
`constexpr weak_ptr& operator=(const weak_ptr& r) noexcept;
template<class Y> constexpr weak_ptr& operator=(const weak_ptr<Y>& r) noexcept;
template<class Y> constexpr weak_ptr& operator=(const shared_ptr<Y>& r) noexcept;
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4993)
*Effects*: Equivalent to weak_ptr(r).swap(*this)[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4997)
*Returns*: *this[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5001)
*Remarks*: The implementation may meet the effects (and the
implied guarantees) via different means, without creating a temporary object[.](#3.sentence-1)
[🔗](#lib:operator=,weak_ptr_)
`constexpr weak_ptr& operator=(weak_ptr&& r) noexcept;
template<class Y> constexpr weak_ptr& operator=(weak_ptr<Y>&& r) noexcept;
`
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5014)
*Effects*: Equivalent to weak_ptr(std::move(r)).swap(*this)[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5018)
*Returns*: *this[.](#5.sentence-1)

View File

@@ -0,0 +1,30 @@
[util.smartptr.weak.bad]
# 20 Memory management library [[mem]](./#mem)
## 20.3 Smart pointers [[smartptr]](smartptr#util.smartptr.weak.bad)
### 20.3.2 Shared-ownership pointers [[util.sharedptr]](util.sharedptr#util.smartptr.weak.bad)
#### 20.3.2.1 Class bad_weak_ptr [util.smartptr.weak.bad]
[🔗](#lib:bad_weak_ptr)
namespace std {class bad_weak_ptr : public exception {public:// see [[exception]](exception "17.9.3Class exception") for the specification of the special member functionsconstexpr const char* what() const noexcept override; };}
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3468)
An exception of type bad_weak_ptr is thrown by the shared_ptr constructor taking a weak_ptr[.](#1.sentence-1)
[🔗](#lib:what,bad_weak_ptr)
`constexpr const char* what() const noexcept override;
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L3478)
*Returns*: An implementation-defined ntbs[.](#2.sentence-1)

View File

@@ -0,0 +1,83 @@
[util.smartptr.weak.const]
# 20 Memory management library [[mem]](./#mem)
## 20.3 Smart pointers [[smartptr]](smartptr#util.smartptr.weak.const)
### 20.3.2 Shared-ownership pointers [[util.sharedptr]](util.sharedptr#util.smartptr.weak.const)
#### 20.3.2.3 Class template weak_ptr [[util.smartptr.weak]](util.smartptr.weak#const)
#### 20.3.2.3.2 Constructors [util.smartptr.weak.const]
[🔗](#lib:weak_ptr,constructor)
`constexpr weak_ptr() noexcept;
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4914)
*Effects*: Constructs an empty weak_ptr object that stores a null pointer value[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4918)
*Postconditions*: use_count() == 0[.](#2.sentence-1)
[🔗](#lib:weak_ptr,constructor_)
`constexpr weak_ptr(const weak_ptr& r) noexcept;
template<class Y> constexpr weak_ptr(const weak_ptr<Y>& r) noexcept;
template<class Y> constexpr weak_ptr(const shared_ptr<Y>& r) noexcept;
`
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4931)
*Constraints*: For the second and third constructors, Y* is compatible with T*[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4935)
*Effects*: If r is empty, constructs
an empty weak_ptr object that stores a null pointer value;
otherwise, constructs
a weak_ptr object that shares ownership
with r and stores a copy of the pointer stored in r[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4943)
*Postconditions*: use_count() == r.use_count()[.](#5.sentence-1)
[🔗](#lib:weak_ptr,constructor__)
`constexpr weak_ptr(weak_ptr&& r) noexcept;
template<class Y> constexpr weak_ptr(weak_ptr<Y>&& r) noexcept;
`
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4955)
*Constraints*: For the second constructor, Y* is compatible with T*[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4959)
*Effects*: Move constructs a weak_ptr instance from r[.](#7.sentence-1)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4963)
*Postconditions*: *this contains the old value of r[.](#8.sentence-1)
r is empty, stores a null pointer value, and r.use_count() == 0[.](#8.sentence-2)

View File

@@ -0,0 +1,23 @@
[util.smartptr.weak.dest]
# 20 Memory management library [[mem]](./#mem)
## 20.3 Smart pointers [[smartptr]](smartptr#util.smartptr.weak.dest)
### 20.3.2 Shared-ownership pointers [[util.sharedptr]](util.sharedptr#util.smartptr.weak.dest)
#### 20.3.2.3 Class template weak_ptr [[util.smartptr.weak]](util.smartptr.weak#dest)
#### 20.3.2.3.3 Destructor [util.smartptr.weak.dest]
[🔗](#lib:weak_ptr,destructor)
`constexpr ~weak_ptr();
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4977)
*Effects*: Destroys this weak_ptr object but has no
effect on the object its stored pointer points to[.](#1.sentence-1)

View File

@@ -0,0 +1,34 @@
[util.smartptr.weak.general]
# 20 Memory management library [[mem]](./#mem)
## 20.3 Smart pointers [[smartptr]](smartptr#util.smartptr.weak.general)
### 20.3.2 Shared-ownership pointers [[util.sharedptr]](util.sharedptr#util.smartptr.weak.general)
#### 20.3.2.3 Class template weak_ptr [[util.smartptr.weak]](util.smartptr.weak#general)
#### 20.3.2.3.1 General [util.smartptr.weak.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4839)
The weak_ptr class template stores a weak reference to an object
that is already managed by a shared_ptr[.](#1.sentence-1)
To access the object, aweak_ptr can be converted to a shared_ptr using the member
function lock[.](#1.sentence-2)
namespace std {template<class T> class weak_ptr {public:using element_type = remove_extent_t<T>; // [[util.smartptr.weak.const]](util.smartptr.weak.const "20.3.2.3.2Constructors"), constructorsconstexpr weak_ptr() noexcept; template<class Y>constexpr weak_ptr(const shared_ptr<Y>& r) noexcept; constexpr weak_ptr(const weak_ptr& r) noexcept; template<class Y>constexpr weak_ptr(const weak_ptr<Y>& r) noexcept; constexpr weak_ptr(weak_ptr&& r) noexcept; template<class Y>constexpr weak_ptr(weak_ptr<Y>&& r) noexcept; // [[util.smartptr.weak.dest]](util.smartptr.weak.dest "20.3.2.3.3Destructor"), destructorconstexpr ~weak_ptr(); // [[util.smartptr.weak.assign]](util.smartptr.weak.assign "20.3.2.3.4Assignment"), assignmentconstexpr weak_ptr& operator=(const weak_ptr& r) noexcept; template<class Y>constexpr weak_ptr& operator=(const weak_ptr<Y>& r) noexcept; template<class Y>constexpr weak_ptr& operator=(const shared_ptr<Y>& r) noexcept; constexpr weak_ptr& operator=(weak_ptr&& r) noexcept; template<class Y>constexpr weak_ptr& operator=(weak_ptr<Y>&& r) noexcept; // [[util.smartptr.weak.mod]](util.smartptr.weak.mod "20.3.2.3.5Modifiers"), modifiersconstexpr void swap(weak_ptr& r) noexcept; constexpr void reset() noexcept; // [[util.smartptr.weak.obs]](util.smartptr.weak.obs "20.3.2.3.6Observers"), observersconstexpr long use_count() const noexcept; constexpr bool expired() const noexcept; constexpr shared_ptr<T> lock() const noexcept; template<class U>constexpr bool owner_before(const shared_ptr<U>& b) const noexcept; template<class U>constexpr bool owner_before(const weak_ptr<U>& b) const noexcept;
size_t owner_hash() const noexcept; template<class U>constexpr bool owner_equal(const shared_ptr<U>& b) const noexcept; template<class U>constexpr bool owner_equal(const weak_ptr<U>& b) const noexcept; }; template<class T> weak_ptr(shared_ptr<T>) -> weak_ptr<T>;}
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L4900)
Specializations of weak_ptr shall be [*Cpp17CopyConstructible*](utility.arg.requirements#:Cpp17CopyConstructible "16.4.4.2Template argument requirements[utility.arg.requirements]") and[*Cpp17CopyAssignable*](utility.arg.requirements#:Cpp17CopyAssignable "16.4.4.2Template argument requirements[utility.arg.requirements]"), allowing their use in standard
containers[.](#2.sentence-1)
The template parameter T of weak_ptr may be an
incomplete type[.](#2.sentence-2)

View File

@@ -0,0 +1,33 @@
[util.smartptr.weak.mod]
# 20 Memory management library [[mem]](./#mem)
## 20.3 Smart pointers [[smartptr]](smartptr#util.smartptr.weak.mod)
### 20.3.2 Shared-ownership pointers [[util.sharedptr]](util.sharedptr#util.smartptr.weak.mod)
#### 20.3.2.3 Class template weak_ptr [[util.smartptr.weak]](util.smartptr.weak#mod)
#### 20.3.2.3.5 Modifiers [util.smartptr.weak.mod]
[🔗](#lib:swap,weak_ptr)
`constexpr void swap(weak_ptr& r) noexcept;
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5030)
*Effects*: Exchanges the contents of *this and r[.](#1.sentence-1)
[🔗](#lib:reset,weak_ptr)
`constexpr void reset() noexcept;
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5041)
*Effects*: Equivalent to weak_ptr().swap(*this)[.](#2.sentence-1)

View File

@@ -0,0 +1,100 @@
[util.smartptr.weak.obs]
# 20 Memory management library [[mem]](./#mem)
## 20.3 Smart pointers [[smartptr]](smartptr#util.smartptr.weak.obs)
### 20.3.2 Shared-ownership pointers [[util.sharedptr]](util.sharedptr#util.smartptr.weak.obs)
#### 20.3.2.3 Class template weak_ptr [[util.smartptr.weak]](util.smartptr.weak#obs)
#### 20.3.2.3.6 Observers [util.smartptr.weak.obs]
[🔗](#lib:use_count,weak_ptr)
`constexpr long use_count() const noexcept;
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5053)
*Returns*: 0 if *this is empty;
otherwise, the number of shared_ptr instances
that share ownership with *this[.](#1.sentence-1)
[🔗](#lib:expired,weak_ptr)
`constexpr bool expired() const noexcept;
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5066)
*Returns*: use_count() == 0[.](#2.sentence-1)
[🔗](#lib:lock,weak_ptr)
`constexpr shared_ptr<T> lock() const noexcept;
`
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5077)
*Returns*: expired() ? shared_ptr<T>() : shared_ptr<T>(*this), executed atomically[.](#3.sentence-1)
[🔗](#lib:owner_before,weak_ptr)
`template<class U> constexpr bool owner_before(const shared_ptr<U>& b) const noexcept;
template<class U> constexpr bool owner_before(const weak_ptr<U>& b) const noexcept;
`
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5089)
*Returns*: An unspecified value such that
- [(4.1)](#4.1)
owner_before(b) defines a strict weak ordering as defined in [[alg.sorting]](alg.sorting "26.8Sorting and related operations");
- [(4.2)](#4.2)
!owner_before(b) && !b.owner_before(*this) is true if and only if owner_equal(b) is true[.](#4.sentence-1)
[🔗](#lib:owner_hash,weak_ptr)
`size_t owner_hash() const noexcept;
`
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5106)
*Returns*: An unspecified value such that,
for any object x where owner_equal(x) is true,owner_hash() == x.owner_hash() is true[.](#5.sentence-1)
[🔗](#lib:owner_equal,weak_ptr)
`template<class U>
constexpr bool owner_equal(const shared_ptr<U>& b) const noexcept;
template<class U>
constexpr bool owner_equal(const weak_ptr<U>& b) const noexcept;
`
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5122)
*Returns*: true if and only if*this and b share ownership or are both empty[.](#6.sentence-1)
Otherwise returns false[.](#6.sentence-2)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5128)
*Remarks*: owner_equal is an equivalence relation[.](#7.sentence-1)

View File

@@ -0,0 +1,23 @@
[util.smartptr.weak.spec]
# 20 Memory management library [[mem]](./#mem)
## 20.3 Smart pointers [[smartptr]](smartptr#util.smartptr.weak.spec)
### 20.3.2 Shared-ownership pointers [[util.sharedptr]](util.sharedptr#util.smartptr.weak.spec)
#### 20.3.2.3 Class template weak_ptr [[util.smartptr.weak]](util.smartptr.weak#spec)
#### 20.3.2.3.7 Specialized algorithms [util.smartptr.weak.spec]
[🔗](#lib:swap,weak_ptr)
`template<class T>
constexpr void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept;
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5142)
*Effects*: Equivalent to a.swap(b)[.](#1.sentence-1)