20 Memory management library [mem] (original) (raw)

20.3 Smart pointers [smartptr]


20.3.1 Unique-ownership pointers [unique.ptr]

20.3.1.1 General [unique.ptr.general]

20.3.1.2 Default deleters [unique.ptr.dltr]

20.3.1.2.1 General [unique.ptr.dltr.general]

20.3.1.2.2 default_delete [unique.ptr.dltr.dflt]

20.3.1.2.3 default_delete<T[]> [unique.ptr.dltr.dflt1]

20.3.1.3 unique_ptr for single objects [unique.ptr.single]

20.3.1.3.1 General [unique.ptr.single.general]

20.3.1.3.2 Constructors [unique.ptr.single.ctor]

20.3.1.3.3 Destructor [unique.ptr.single.dtor]

20.3.1.3.4 Assignment [unique.ptr.single.asgn]

20.3.1.3.5 Observers [unique.ptr.single.observers]

20.3.1.3.6 Modifiers [unique.ptr.single.modifiers]

20.3.1.4 unique_ptr for array objects with a runtime length [unique.ptr.runtime]

20.3.1.4.1 General [unique.ptr.runtime.general]

20.3.1.4.2 Constructors [unique.ptr.runtime.ctor]

20.3.1.4.3 Assignment [unique.ptr.runtime.asgn]

20.3.1.4.4 Observers [unique.ptr.runtime.observers]

20.3.1.4.5 Modifiers [unique.ptr.runtime.modifiers]

20.3.1.5 Creation [unique.ptr.create]

20.3.1.6 Specialized algorithms [unique.ptr.special]

20.3.1.7 I/O [unique.ptr.io]

20.3.2 Shared-ownership pointers [util.sharedptr]

20.3.2.1 Class bad_weak_ptr [util.smartptr.weak.bad]

20.3.2.2 Class template shared_ptr [util.smartptr.shared]

20.3.2.2.1 General [util.smartptr.shared.general]

20.3.2.2.2 Constructors [util.smartptr.shared.const]

20.3.2.2.3 Destructor [util.smartptr.shared.dest]

20.3.2.2.4 Assignment [util.smartptr.shared.assign]

20.3.2.2.5 Modifiers [util.smartptr.shared.mod]

20.3.2.2.6 Observers [util.smartptr.shared.obs]

20.3.2.2.7 Creation [util.smartptr.shared.create]

20.3.2.2.8 Comparison [util.smartptr.shared.cmp]

20.3.2.2.9 Specialized algorithms [util.smartptr.shared.spec]

20.3.2.2.10 Casts [util.smartptr.shared.cast]

20.3.2.2.11 get_deleter [util.smartptr.getdeleter]

20.3.2.2.12 I/O [util.smartptr.shared.io]

20.3.2.3 Class template weak_ptr [util.smartptr.weak]

20.3.2.3.1 General [util.smartptr.weak.general]

20.3.2.3.2 Constructors [util.smartptr.weak.const]

20.3.2.3.3 Destructor [util.smartptr.weak.dest]

20.3.2.3.4 Assignment [util.smartptr.weak.assign]

20.3.2.3.5 Modifiers [util.smartptr.weak.mod]

20.3.2.3.6 Observers [util.smartptr.weak.obs]

20.3.2.3.7 Specialized algorithms [util.smartptr.weak.spec]

20.3.2.4 Class template owner_less [util.smartptr.ownerless]

20.3.2.5 Struct owner_hash [util.smartptr.owner.hash]

20.3.2.6 Struct owner_equal [util.smartptr.owner.equal]

20.3.2.7 Class template enable_shared_from_this [util.smartptr.enab]

20.3.3 Smart pointer hash support [util.smartptr.hash]

20.3.4 Smart pointer adaptors [smartptr.adapt]

20.3.4.1 Class template out_ptr_t [out.ptr.t]

20.3.4.2 Function template out_ptr [out.ptr]

20.3.4.3 Class template inout_ptr_t [inout.ptr.t]

20.3.4.4 Function template inout_ptr [inout.ptr]


20.3.1 Unique-ownership pointers [unique.ptr]

20.3.1.1 General [unique.ptr.general]

A unique pointer is an object that owns another object and manages that other object through a pointer.

More precisely, a unique pointer is an object u that stores a pointer to a second object p and will dispose of p when u is itself destroyed (e.g., when leaving block scope ([stmt.dcl])).

In this context, u is said to own p.

The mechanism by which u disposes of p is known as_p_'s associated deleter, a function object whose correct invocation results in p's appropriate disposition (typically its deletion).

Let the notation u.p denote the pointer stored by u, and let u.d denote the associated deleter.

Upon request, u canreset (replace) u.p and u.d with another pointer and deleter, but properly disposes of its owned object via the associated deleter before such replacement is considered completed.

Each object of a type U instantiated from the unique_ptr template specified in [unique.ptr] has the strict ownership semantics, specified above, of a unique pointer.

The template parameter T of unique_ptr may be an incomplete type.

[Note 1:

The uses of unique_ptr include providing exception safety for dynamically allocated memory, passing ownership of dynamically allocated memory to a function, and returning dynamically allocated memory from a function.

— _end note_]

20.3.1.2 Default deleters [unique.ptr.dltr]

20.3.1.2.1 General [unique.ptr.dltr.general]

The class template default_delete serves as the default deleter (destruction policy) for the class template unique_ptr.

The template parameter T of default_delete may be an incomplete type.

20.3.1.2.2 default_delete [unique.ptr.dltr.dflt]

namespace std { template<class T> struct default_delete { constexpr default_delete() noexcept = default;template<class U> constexpr default_delete(const default_delete<U>&) noexcept;constexpr void operator()(T*) const;};}

template<class U> constexpr default_delete(const default_delete<U>& other) noexcept;

Constraints: U* is implicitly convertible to T*.

Effects: Constructs a default_delete object from another default_delete<U> object.

constexpr void operator()(T* ptr) const;

Mandates: T is a complete type.

Effects: Calls delete on ptr.

20.3.1.2.3 default_delete<T[]> [unique.ptr.dltr.dflt1]

namespace std { template<class T> struct default_delete<T[]> { constexpr default_delete() noexcept = default;template<class U> constexpr default_delete(const default_delete<U[]>&) noexcept;template<class U> constexpr void operator()(U* ptr) const;};}

template<class U> constexpr default_delete(const default_delete<U[]>& other) noexcept;

Constraints: U(*)[] is convertible to T(*)[].

Effects: Constructs a default_delete object from another default_delete<U[]> object.

template<class U> constexpr void operator()(U* ptr) const;

Constraints: U(*)[] is convertible to T(*)[].

Mandates: U is a complete type.

Effects: Calls delete[] on ptr.

20.3.1.3 unique_ptr for single objects [unique.ptr.single]

20.3.1.3.1 General [unique.ptr.single.general]

namespace std { template<class T, class D = default_delete<T>> class unique_ptr { public: using pointer = see below;using element_type = T;using deleter_type = D;constexpr unique_ptr() noexcept;constexpr explicit unique_ptr(type_identity_t<pointer> p) noexcept;constexpr unique_ptr(type_identity_t<pointer> p, see below d1) noexcept;constexpr unique_ptr(type_identity_t<pointer> p, see below d2) noexcept;constexpr unique_ptr(unique_ptr&& u) noexcept;constexpr unique_ptr(nullptr_t) noexcept;template<class U, class E> constexpr unique_ptr(unique_ptr<U, E>&& u) noexcept;constexpr ~unique_ptr();constexpr unique_ptr& operator=(unique_ptr&& u) noexcept;template<class U, class E> constexpr unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept;constexpr unique_ptr& operator=(nullptr_t) noexcept;constexpr add_lvalue_reference_t<T> operator*() const noexcept(see below);constexpr pointer operator->() const noexcept;constexpr pointer get() const noexcept;constexpr deleter_type& get_deleter() noexcept;constexpr const deleter_type& get_deleter() const noexcept;constexpr explicit operator bool() const noexcept;constexpr pointer release() noexcept;constexpr void reset(pointer p = pointer()) noexcept;constexpr void swap(unique_ptr& u) noexcept; unique_ptr(const unique_ptr&) = delete; unique_ptr& operator=(const unique_ptr&) = delete;};}

A program that instantiates the definition of unique_ptr<T, D>is ill-formed if T* is an invalid type.

[Note 1:

This prevents the instantiation of specializations such asunique_ptr<T&, D> and unique_ptr<int() const, D>.

— _end note_]

The default type for the template parameter D isdefault_delete.

A client-supplied template argumentD shall be a function object type ([function.objects]), lvalue reference to function, or lvalue reference to function object type for which, given a value d of type D and a valueptr of type unique_ptr<T, D>​::​pointer, the expressiond(ptr) is valid and has the effect of disposing of the pointer as appropriate for that deleter.

If the deleter's type D is not a reference type, D shall meet the Cpp17Destructible requirements (Table 35).

If the qualified-id remove_reference_t<D>​::​pointer is valid and denotes a type ([temp.deduct]), then unique_ptr<T, D>​::​pointer shall be a synonym for remove_reference_t<D>​::​pointer.

Otherwiseunique_ptr<T, D>​::​pointer shall be a synonym for element_type*.

The type unique_ptr<T, D>​::​pointer shall meet the Cpp17NullablePointer requirements (Table 36).

[Example 1:

Given an allocator type X ([allocator.requirements.general]) and letting A be a synonym for allocator_traits<X>, the types A​::​pointer,A​::​const_pointer, A​::​void_pointer, and A​::​const_void_pointermay be used as unique_ptr<T, D>​::​pointer.

— _end example_]

20.3.1.3.2 Constructors [unique.ptr.single.ctor]

constexpr unique_ptr() noexcept;constexpr unique_ptr(nullptr_t) noexcept;

Constraints: is_pointer_v<deleter_type> is false andis_default_constructible_v<deleter_type> is true.

Effects: Constructs a unique_ptr object that owns nothing, value-initializing the stored pointer and the stored deleter.

Postconditions: get() == nullptr.

get_deleter()returns a reference to the stored deleter.

constexpr explicit unique_ptr(type_identity_t<pointer> p) noexcept;

Constraints: is_pointer_v<deleter_type> is false andis_default_constructible_v<deleter_type> is true.

Effects: Constructs a unique_ptr which ownsp, initializing the stored pointer with p and value-initializing the stored deleter.

Postconditions: get() == p.

get_deleter()returns a reference to the stored deleter.

constexpr unique_ptr(type_identity_t<pointer> p, const D& d) noexcept;constexpr unique_ptr(type_identity_t<pointer> p, remove_reference_t<D>&& d) noexcept;

Constraints: is_constructible_v<D, decltype(d)> is true.

Preconditions: For the first constructor, if D is not a reference type,D meets the Cpp17CopyConstructible requirements and such construction does not exit via an exception.

For the second constructor, if D is not a reference type,D meets the Cpp17MoveConstructible requirements and such construction does not exit via an exception.

Effects: Constructs a unique_ptr object which owns p, initializing the stored pointer with p and initializing the deleter from std​::​forward<decltype(d)>(d).

Postconditions: get() == p.

get_deleter() returns a reference to the stored deleter.

If D is a reference type then get_deleter()returns a reference to the lvalue d.

Remarks: If D is a reference type, the second constructor is defined as deleted.

[Example 1: D d; unique_ptr<int, D> p1(new int, D()); unique_ptr<int, D> p2(new int, d); unique_ptr<int, D&> p3(new int, d); unique_ptr<int, const D&> p4(new int, D()); — _end example_]

constexpr unique_ptr(unique_ptr&& u) noexcept;

Constraints: is_move_constructible_v<D> is true.

Preconditions: If D is not a reference type,D meets the Cpp17MoveConstructiblerequirements (Table 31).

Construction of the deleter from an rvalue of type D does not throw an exception.

Effects: Constructs a unique_ptr fromu.

If D is a reference type, this deleter is copy constructed from u's deleter; otherwise, this deleter is move constructed from u's deleter.

[Note 1:

The construction of the deleter can be implemented with std​::​forward<D>.

— _end note_]

Postconditions: get() yields the value u.get()yielded before the construction.

u.get() == nullptr.

get_deleter() returns a reference to the stored deleter that was constructed fromu.get_deleter().

If D is a reference type thenget_deleter() and u.get_deleter() both reference the same lvalue deleter.

template<class U, class E> constexpr unique_ptr(unique_ptr<U, E>&& u) noexcept;

Constraints:

Preconditions: If E is not a reference type, construction of the deleter from an rvalue of type Eis well-formed and does not throw an exception.

Otherwise, E is a reference type and construction of the deleter from an lvalue of type Eis well-formed and does not throw an exception.

Effects: Constructs a unique_ptr from u.

If E is a reference type, this deleter is copy constructed fromu's deleter; otherwise, this deleter is move constructed from u's deleter.

[Note 2:

The deleter constructor can be implemented withstd​::​forward<E>.

— _end note_]

Postconditions: get() yields the value u.get()yielded before the construction.

u.get() == nullptr.

get_deleter() returns a reference to the stored deleter that was constructed fromu.get_deleter().

20.3.1.3.3 Destructor [unique.ptr.single.dtor]

Effects: Equivalent to:if (get()) get_deleter()(get());

[Note 1:

The use of default_delete requires T to be a complete type.

— _end note_]

Remarks: The behavior is undefined if the evaluation of get_deleter()(get()) throws an exception.

20.3.1.3.4 Assignment [unique.ptr.single.asgn]

constexpr unique_ptr& operator=(unique_ptr&& u) noexcept;

Constraints: is_move_assignable_v<D> is true.

Preconditions: If D is not a reference type, D meets theCpp17MoveAssignable requirements (Table 33) and assignment of the deleter from an rvalue of type D does not throw an exception.

Otherwise, D is a reference type;remove_reference_t<D> meets the Cpp17CopyAssignablerequirements and assignment of the deleter from an lvalue of type D does not throw an exception.

Effects: Calls reset(u.release()) followed byget_deleter() = std​::​forward<D>(u.get_deleter()).

Postconditions: If this != addressof(u),u.get() == nullptr, otherwise u.get() is unchanged.

template<class U, class E> constexpr unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept;

Constraints:

Preconditions: If E is not a reference type, assignment of the deleter from an rvalue of type Eis well-formed and does not throw an exception.

Otherwise, E is a reference type and assignment of the deleter from an lvalue of type Eis well-formed and does not throw an exception.

Effects: Calls reset(u.release()) followed byget_deleter() = std​::​forward<E>(u.get_deleter()).

Postconditions: u.get() == nullptr.

constexpr unique_ptr& operator=(nullptr_t) noexcept;

Effects: As if by reset().

Postconditions: get() == nullptr.

20.3.1.3.5 Observers [unique.ptr.single.observers]

constexpr add_lvalue_reference_t<T> operator*() const noexcept(noexcept(*declval<pointer>()));

Mandates: reference_converts_from_temporary_v<add_lvalue_reference_t<T>, decltype(
*declval<pointer>())> is false.

Preconditions: get() != nullptr is true.

constexpr pointer operator->() const noexcept;

Preconditions: get() != nullptr.

[Note 1:

The use of this function typically requires that T be a complete type.

— _end note_]

constexpr pointer get() const noexcept;

Returns: The stored pointer.

constexpr deleter_type& get_deleter() noexcept;constexpr const deleter_type& get_deleter() const noexcept;

Returns: A reference to the stored deleter.

constexpr explicit operator bool() const noexcept;

Returns: get() != nullptr.

20.3.1.3.6 Modifiers [unique.ptr.single.modifiers]

constexpr pointer release() noexcept;

Postconditions: get() == nullptr.

Returns: The value get() had at the start of the call to release.

constexpr void reset(pointer p = pointer()) noexcept;

Effects: Assigns p to the stored pointer, and then, with the old value of the stored pointer, old_p, evaluates if (old_p) get_deleter()(old_p);

[Note 1:

The order of these operations is significant because the call to get_deleter() might destroy *this.

— _end note_]

Postconditions: get() == p.

[Note 2:

The postcondition does not hold if the call to get_deleter()destroys *this since this->get() is no longer a valid expression.

— _end note_]

Remarks: The behavior is undefined if the evaluation of get_deleter()(old_p) throws an exception.

constexpr void swap(unique_ptr& u) noexcept;

Effects: Invokes swap on the stored pointers and on the stored deleters of *this and u.

20.3.1.4 unique_ptr for array objects with a runtime length [unique.ptr.runtime]

20.3.1.4.1 General [unique.ptr.runtime.general]

namespace std { template<class T, class D> class unique_ptr<T[], D> { public: using pointer = see below;using element_type = T;using deleter_type = D;constexpr unique_ptr() noexcept;template<class U> constexpr explicit unique_ptr(U p) noexcept;template<class U> constexpr unique_ptr(U p, see below d) noexcept;template<class U> constexpr unique_ptr(U p, see below d) noexcept;constexpr unique_ptr(unique_ptr&& u) noexcept;template<class U, class E> constexpr unique_ptr(unique_ptr<U, E>&& u) noexcept;constexpr unique_ptr(nullptr_t) noexcept;constexpr ~unique_ptr();constexpr unique_ptr& operator=(unique_ptr&& u) noexcept;template<class U, class E> constexpr unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept;constexpr unique_ptr& operator=(nullptr_t) noexcept;constexpr T& operator[](size_t i) const;constexpr pointer get() const noexcept;constexpr deleter_type& get_deleter() noexcept;constexpr const deleter_type& get_deleter() const noexcept;constexpr explicit operator bool() const noexcept;constexpr pointer release() noexcept;template<class U> constexpr void reset(U p) noexcept;constexpr void reset(nullptr_t = nullptr) noexcept;constexpr void swap(unique_ptr& u) noexcept; unique_ptr(const unique_ptr&) = delete; unique_ptr& operator=(const unique_ptr&) = delete;};}

A specialization for array types is provided with a slightly altered interface.

Descriptions are provided below only for members that differ from the primary template.

The template argument T shall be a complete type.

20.3.1.4.2 Constructors [unique.ptr.runtime.ctor]

template<class U> constexpr explicit unique_ptr(U p) noexcept;

This constructor behaves the same as the constructor in the primary template that takes a single parameter of type pointer.

Constraints:

template<class U> constexpr unique_ptr(U p, _see below_ d) noexcept;template<class U> constexpr unique_ptr(U p, _see below_ d) noexcept;

These constructors behave the same as the constructors in the primary template that take a parameter of type pointer and a second parameter.

Constraints:

template<class U, class E> constexpr unique_ptr(unique_ptr<U, E>&& u) noexcept;

This constructor behaves the same as in the primary template.

Constraints: Where UP is unique_ptr<U, E>:

[Note 1:

This replaces the Constraints: specification of the primary template.

— _end note_]

20.3.1.4.3 Assignment [unique.ptr.runtime.asgn]

template<class U, class E> constexpr unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept;

This operator behaves the same as in the primary template.

Constraints: Where UP is unique_ptr<U, E>:

[Note 1:

This replaces the Constraints: specification of the primary template.

— _end note_]

20.3.1.4.4 Observers [unique.ptr.runtime.observers]

constexpr T& operator[](size_t i) const;

Preconditions: i < the number of elements in the array to which the stored pointer points.

20.3.1.4.5 Modifiers [unique.ptr.runtime.modifiers]

constexpr void reset(nullptr_t p = nullptr) noexcept;

Effects: Equivalent to reset(pointer()).

template<class U> constexpr void reset(U p) noexcept;

This function behaves the same as the reset member of the primary template.

Constraints:

20.3.1.5 Creation [unique.ptr.create]

template<class T, class... Args> constexpr unique_ptr<T> make_unique(Args&&... args);

Constraints: T is not an array type.

Returns: unique_ptr<T>(new T(std​::​forward<Args>(args)...)).

template<class T> constexpr unique_ptr<T> make_unique(size_t n);

Constraints: T is an array of unknown bound.

Returns: unique_ptr<T>(new remove_extent_t<T>[n]()).

template<class T, class... Args> _unspecified_ make_unique(Args&&...) = delete;

Constraints: T is an array of known bound.

template<class T> constexpr unique_ptr<T> make_unique_for_overwrite();

Constraints: T is not an array type.

Returns: unique_ptr<T>(new T).

template<class T> constexpr unique_ptr<T> make_unique_for_overwrite(size_t n);

Constraints: T is an array of unknown bound.

Returns: unique_ptr<T>(new remove_extent_t<T>[n]).

template<class T, class... Args> _unspecified_ make_unique_for_overwrite(Args&&...) = delete;

Constraints: T is an array of known bound.

20.3.1.6 Specialized algorithms [unique.ptr.special]

template<class T, class D> constexpr void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) noexcept;

Constraints: is_swappable_v<D> is true.

Effects: Calls x.swap(y).

template<class T1, class D1, class T2, class D2> constexpr bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);

Returns: x.get() == y.get().

template<class T1, class D1, class T2, class D2> constexpr bool operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);

Let CT denotecommon_type_t<typename unique_ptr<T1, D1>::pointer,typename unique_ptr<T2, D2>::pointer>

Mandates:

Preconditions: The specializationless<CT> is a function object type ([function.objects]) that induces a strict weak ordering ([alg.sorting]) on the pointer values.

Returns: less<CT>()(x.get(), y.get()).

template<class T1, class D1, class T2, class D2> constexpr bool operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);

template<class T1, class D1, class T2, class D2> constexpr bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);

template<class T1, class D1, class T2, class D2> constexpr bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);

template<class T1, class D1, class T2, class D2> requires [three_way_comparable_with](cmp.concept#concept:three%5Fway%5Fcomparable%5Fwith "17.12.4 Concept three_­way_­comparable [cmp.concept]")<typename unique_ptr<T1, D1>::pointer,typename unique_ptr<T2, D2>::pointer> constexpr compare_three_way_result_t<typename unique_ptr<T1, D1>::pointer,typename unique_ptr<T2, D2>::pointer> operator<=>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);

Returns: compare_three_way()(x.get(), y.get()).

template<class T, class D> constexpr bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept;

template<class T, class D> constexpr bool operator<(const unique_ptr<T, D>& x, nullptr_t);template<class T, class D> constexpr bool operator<(nullptr_t, const unique_ptr<T, D>& x);

Preconditions: The specialization less<unique_ptr<T, D>​::​pointer> is a function object type ([function.objects]) that induces a strict weak ordering ([alg.sorting]) on the pointer values.

Returns: The first function template returnsless<unique_ptr<T, D>::pointer>()(x.get(), nullptr)

The second function template returnsless<unique_ptr<T, D>::pointer>()(nullptr, x.get())

template<class T, class D> constexpr bool operator>(const unique_ptr<T, D>& x, nullptr_t);template<class T, class D> constexpr bool operator>(nullptr_t, const unique_ptr<T, D>& x);

Returns: The first function template returns nullptr < x.

The second function template returns x < nullptr.

template<class T, class D> constexpr bool operator<=(const unique_ptr<T, D>& x, nullptr_t);template<class T, class D> constexpr bool operator<=(nullptr_t, const unique_ptr<T, D>& x);

Returns: The first function template returns !(nullptr < x).

The second function template returns !(x < nullptr).

template<class T, class D> constexpr bool operator>=(const unique_ptr<T, D>& x, nullptr_t);template<class T, class D> constexpr bool operator>=(nullptr_t, const unique_ptr<T, D>& x);

Returns: The first function template returns !(x < nullptr).

The second function template returns !(nullptr < x).

template<class T, class D> requires [three_way_comparable](cmp.concept#concept:three%5Fway%5Fcomparable "17.12.4 Concept three_­way_­comparable [cmp.concept]")<typename unique_ptr<T, D>::pointer> constexpr compare_three_way_result_t<typename unique_ptr<T, D>::pointer> operator<=>(const unique_ptr<T, D>& x, nullptr_t);

Returns: compare_three_way()(x.get(), static_cast<typename unique_ptr<T, D>::pointer>(nullptr)).

20.3.1.7 I/O [unique.ptr.io]

template<class E, class T, class Y, class D> basic_ostream<E, T>& operator<<(basic_ostream<E, T>& os, const unique_ptr<Y, D>& p);

Constraints: os << p.get() is a valid expression.

Effects: Equivalent to: os << p.get();

20.3.2 Shared-ownership pointers [util.sharedptr]

20.3.2.1 Class bad_weak_ptr [util.smartptr.weak.bad]

namespace std { class bad_weak_ptr : public exception { public: constexpr const char* what() const noexcept override;};}

An exception of type bad_weak_ptr is thrown by the shared_ptrconstructor taking a weak_ptr.

constexpr const char* what() const noexcept override;

Returns: An implementation-defined ntbs.

20.3.2.2 Class template shared_ptr [util.smartptr.shared]

20.3.2.2.1 General [util.smartptr.shared.general]

20.3.2.2.2 Constructors [util.smartptr.shared.const]

20.3.2.2.3 Destructor [util.smartptr.shared.dest]

20.3.2.2.4 Assignment [util.smartptr.shared.assign]

20.3.2.2.5 Modifiers [util.smartptr.shared.mod]

20.3.2.2.6 Observers [util.smartptr.shared.obs]

20.3.2.2.7 Creation [util.smartptr.shared.create]

20.3.2.2.8 Comparison [util.smartptr.shared.cmp]

20.3.2.2.9 Specialized algorithms [util.smartptr.shared.spec]

20.3.2.2.10 Casts [util.smartptr.shared.cast]

20.3.2.2.11 get_deleter [util.smartptr.getdeleter]

Returns: If p owns a deleter d of type cv-unqualifiedD, returns addressof(d); otherwise returns nullptr.

The returned pointer remains valid as long as there exists a shared_ptr instance that owns d.

[Note 1:

It is unspecified whether the pointer remains valid longer than that.

This can happen if the implementation doesn't destroy the deleter until all weak_ptr instances that share ownership withp have been destroyed.

— _end note_]

20.3.2.2.12 I/O [util.smartptr.shared.io]

20.3.2.3 Class template weak_ptr [util.smartptr.weak]

20.3.2.3.1 General [util.smartptr.weak.general]

The weak_ptr class template stores a weak reference to an object that is already managed by a shared_ptr.

To access the object, aweak_ptr can be converted to a shared_ptr using the member function lock.

namespace std { template<class T> class weak_ptr { public: using element_type = remove_extent_t<T>;constexpr 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;constexpr ~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;constexpr weak_ptr& operator=(weak_ptr&& r) noexcept;template<class Y> constexpr weak_ptr& operator=(weak_ptr<Y>&& r) noexcept;constexpr void swap(weak_ptr& r) noexcept;constexpr void reset() noexcept;constexpr 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>;}

The template parameter T of weak_ptr may be an incomplete type.

20.3.2.3.2 Constructors [util.smartptr.weak.const]

constexpr weak_ptr() noexcept;

Effects: Constructs an empty weak_ptr object that stores a null pointer value.

Postconditions: use_count() == 0.

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;

Constraints: For the second and third constructors, Y* is compatible with T*.

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.

Postconditions: use_count() == r.use_count().

constexpr weak_ptr(weak_ptr&& r) noexcept;template<class Y> constexpr weak_ptr(weak_ptr<Y>&& r) noexcept;

Constraints: For the second constructor, Y* is compatible with T*.

Effects: Move constructs a weak_ptr instance from r.

Postconditions: *this contains the old value of r.

r is empty, stores a null pointer value, and r.use_count() == 0.

20.3.2.3.3 Destructor [util.smartptr.weak.dest]

Effects: Destroys this weak_ptr object but has no effect on the object its stored pointer points to.

20.3.2.3.4 Assignment [util.smartptr.weak.assign]

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;

Effects: Equivalent to weak_ptr(r).swap(*this).

Remarks: The implementation may meet the effects (and the implied guarantees) via different means, without creating a temporary object.

constexpr weak_ptr& operator=(weak_ptr&& r) noexcept;template<class Y> constexpr weak_ptr& operator=(weak_ptr<Y>&& r) noexcept;

Effects: Equivalent to weak_ptr(std​::​move(r)).swap(*this).

20.3.2.3.5 Modifiers [util.smartptr.weak.mod]

constexpr void swap(weak_ptr& r) noexcept;

Effects: Exchanges the contents of *this and r.

constexpr void reset() noexcept;

Effects: Equivalent to weak_ptr().swap(*this).

20.3.2.3.6 Observers [util.smartptr.weak.obs]

constexpr long use_count() const noexcept;

Returns: 0 if *this is empty; otherwise, the number of shared_ptr instances that share ownership with *this.

constexpr bool expired() const noexcept;

Returns: use_count() == 0.

constexpr shared_ptr<T> lock() const noexcept;

Returns: expired() ? shared_ptr<T>() : shared_ptr<T>(*this), executed atomically.

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;

Returns: An unspecified value such that

size_t owner_hash() const noexcept;

Returns: An unspecified value such that, for any object x where owner_equal(x) is true,owner_hash() == x.owner_hash() is true.

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;

Returns: true if and only if*this and b share ownership or are both empty.

Otherwise returns false.

Remarks: owner_equal is an equivalence relation.

20.3.2.3.7 Specialized algorithms [util.smartptr.weak.spec]

template<class T> constexpr void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept;

Effects: Equivalent to a.swap(b).

20.3.2.4 Class template owner_less [util.smartptr.ownerless]

The class template owner_less allows ownership-based mixed comparisons of shared and weak pointers.

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;};}

operator()(x, y) returns x.owner_before(y).

[Note 1:

Note that

— _end note_]

20.3.2.5 Struct owner_hash [util.smartptr.owner.hash]

The class owner_hash provides ownership-based hashing.

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;};}

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;

[Note 1:

For any object y where x.owner_equal(y) is true,x.owner_hash() == y.owner_hash() is true.

— _end note_]

20.3.2.6 Struct owner_equal [util.smartptr.owner.equal]

The class owner_equal provides ownership-based mixed equality comparisons of shared and weak pointers.

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;};}

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;

Returns: x.owner_equal(y).

[Note 1:

x.owner_equal(y) is trueif and only if x and y share ownership or are both empty.

— _end note_]

20.3.2.7 Class template enable_shared_from_this [util.smartptr.enab]

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.

[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)); } — _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; };}

The template parameter T of enable_shared_from_thismay be an incomplete type.

Effects: Value-initializes weak-this.

[Note 1:

weak-this is not changed.

— _end note_]

Returns: shared_ptr<T>(weak-this).

20.3.3 Smart pointer hash support [util.smartptr.hash]

template<class T, class D> struct hash<unique_ptr<T, D>>;

Letting UP be unique_ptr<T, D>, the specialization hash<UP> is enabled ([unord.hash]) if and only if hash<typename UP​::​pointer> is enabled.

When enabled, for an object p of type UP,hash<UP>()(p) evaluates to the same value as hash<typename UP​::​pointer>()(p.get()).

The member functions are not guaranteed to be noexcept.

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()).

20.3.4 Smart pointer adaptors [smartptr.adapt]

20.3.4.1 Class template out_ptr_t [out.ptr.t]

out_ptr_t is a class template used to adapt types such as smart pointers ([smartptr]) for functions that use output pointer parameters.

[Example 1:

#include <memory> #include <cstdio> int fopen_s(std::FILE** f, const char* name, const char* mode);struct fclose_deleter { void operator()(std::FILE* f) const noexcept { std::fclose(f);} };int main(int, char*[]) { constexpr const char* file_name = "ow.o"; std::unique_ptr<std::FILE, fclose_deleter> file_ptr;int err = fopen_s(std::out_ptrstd::FILE\*\(file_ptr), file_name, "r+b");if (err != 0) return 1;return 0;} unique_ptr can be used with out_ptrto be passed into an output pointer-style function, without needing to hold onto an intermediate pointer value and manually delete it on error or failure.

— _end example_]

namespace std { template<class Smart, class Pointer, class... Args> class out_ptr_t { public: constexpr explicit out_ptr_t(Smart&, Args...); out_ptr_t(const out_ptr_t&) = delete;constexpr ~out_ptr_t();constexpr operator Pointer*() const noexcept;operator void**() const noexcept;private: Smart& s; tuple<Args...> a; Pointer p; };}

If Smart is a specialization of shared_ptr andsizeof...(Args) == 0, the program is ill-formed.

[Note 1:

It is typically a user error to reset a shared_ptrwithout specifying a deleter, as shared_ptr will replace a custom deleter upon usage of reset, as specified in [util.smartptr.shared.mod].

— _end note_]

Program-defined specializations of out_ptr_tthat depend on at least one program-defined type need not meet the requirements for the primary template.

Evaluations of the conversion functions on the same object may conflict ([intro.races]).

constexpr explicit out_ptr_t(Smart& smart, Args... args);

Effects: Initializes s with smart,a with std​::​forward<Args>(args)..., and value-initializes p.

Then, equivalent to:

[Note 2:

The constructor is not noexceptto allow for a variety of non-terminating and safe implementation strategies.

For example, an implementation can allocate a shared_ptr's internal node in the constructor and let implementation-defined exceptions escape safely.

The destructor can then move the allocated control block in directly and avoid any other exceptions.

— _end note_]

Effects: Equivalent to:

constexpr operator Pointer*() const noexcept;

Preconditions: operator void**() has not been called on *this.

Returns: addressof(const_cast<Pointer&>(p)).

operator void**() const noexcept;

Constraints: is_same_v<Pointer, void*> is false.

Mandates: is_pointer_v<Pointer> is true.

Preconditions: operator Pointer*() has not been called on *this.

Returns: A pointer value v such that:

Remarks: Accessing *v outside the lifetime of *thishas undefined behavior.

[Note 3:

reinterpret_cast<void**>(static_cast<Pointer*>(*this))can be a viable implementation strategy for some implementations.

— _end note_]

20.3.4.2 Function template out_ptr [out.ptr]

template<class Pointer = void, class Smart, class... Args> constexpr auto out_ptr(Smart& s, Args&&... args);

Let P be Pointerif is_void_v<Pointer> is false, otherwise POINTER_OF(Smart).

Returns: out_ptr_t<Smart, P, Args&&...>(s, std​::​forward<Args>(args)...).

20.3.4.3 Class template inout_ptr_t [inout.ptr.t]

inout_ptr_t is a class template used to adapt types such as smart pointers ([smartptr]) for functions that use output pointer parameters whose dereferenced values may first be deleted before being set to another allocated value.

[Example 1: #include <memory> struct star_fish* star_fish_alloc();int star_fish_populate(struct star_fish** ps, const char* description);struct star_fish_deleter { void operator() (struct star_fish* c) const noexcept;};using star_fish_ptr = std::unique_ptr<star_fish, star_fish_deleter>;int main(int, char*[]) { star_fish_ptr peach(star_fish_alloc());int err = star_fish_populate(std::inout_ptr(peach), "caring clown-fish liker");return err;}

A unique_ptr can be used with inout_ptrto be passed into an output pointer-style function.

The original value will be properly deleted according to the function it is used with and a new value reset in its place.

— _end example_]

namespace std { template<class Smart, class Pointer, class... Args> class inout_ptr_t { public: constexpr explicit inout_ptr_t(Smart&, Args...); inout_ptr_t(const inout_ptr_t&) = delete;constexpr ~inout_ptr_t();constexpr operator Pointer*() const noexcept;operator void**() const noexcept;private: Smart& s; tuple<Args...> a; Pointer p; };}

If Smart is a specialization of shared_ptr, the program is ill-formed.

[Note 1:

It is impossible to properly acquire unique ownership of the managed resource from a shared_ptr given its shared ownership model.

— _end note_]

Program-defined specializations of inout_ptr_tthat depend on at least one program-defined type need not meet the requirements for the primary template.

Evaluations of the conversion functions on the same object may conflict ([intro.races]).

constexpr explicit inout_ptr_t(Smart& smart, Args... args);

Effects: Initializes s with smart,a with std​::​forward<Args>(args)..., andp to either

Remarks: An implementation can call s.release().

[Note 2:

The constructor is not noexceptto allow for a variety of non-terminating and safe implementation strategies.

For example, an intrusive pointer implementation with a control block can allocate in the constructor and safely fail with an exception.

— _end note_]

constexpr ~inout_ptr_t();

Let release-statement be s.release();if an implementation does not call s.release() in the constructor.

Otherwise, it is empty.

Effects: Equivalent to:

constexpr operator Pointer*() const noexcept;

Preconditions: operator void**() has not been called on *this.

Returns: addressof(const_cast<Pointer&>(p)).

operator void**() const noexcept;

Constraints: is_same_v<Pointer, void*> is false.

Mandates: is_pointer_v<Pointer> is true.

Preconditions: operator Pointer*() has not been called on *this.

Returns: A pointer value v such that:

Remarks: Accessing *v outside the lifetime of *thishas undefined behavior.

[Note 3:

reinterpret_cast<void**>(static_cast<Pointer*>(*this))can be a viable implementation strategy for some implementations.

— _end note_]

20.3.4.4 Function template inout_ptr [inout.ptr]

template<class Pointer = void, class Smart, class... Args> constexpr auto inout_ptr(Smart& s, Args&&... args);

Let P be Pointer if is_void_v<Pointer> is false, otherwise POINTER_OF(Smart).

Returns: inout_ptr_t<Smart, P, Args&&...>(s, std​::​forward<Args>(args)...).