19 General utilities library [utilities]

19.11 Smart pointers [smartptr]

19.11.1 Class template unique_­ptr [unique.ptr]

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 can reset (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 this subclause has the strict ownership semantics, specified above, of a unique pointer.
In partial satisfaction of these semantics, each such U is Cpp17MoveConstructible and Cpp17MoveAssignable, but is not Cpp17CopyConstructible nor Cpp17CopyAssignable.
The template parameter T of unique_­ptr may be an incomplete type.
[Note
:
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
]

19.11.1.1 Default deleters [unique.ptr.dltr]

19.11.1.1.1 In 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.

19.11.1.1.2 default_­delete [unique.ptr.dltr.dflt]

namespace std {
  template<class T> struct default_delete {
    constexpr default_delete() noexcept = default;
    template<class U> default_delete(const default_delete<U>&) noexcept;
    void operator()(T*) const;
  };
}
template<class U> default_delete(const default_delete<U>& other) noexcept;
Effects: Constructs a default_­delete object from another default_­delete<U> object.
Remarks: This constructor shall not participate in overload resolution unless U* is implicitly convertible to T*.
void operator()(T* ptr) const;
Effects: Calls delete on ptr.
Remarks: If T is an incomplete type, the program is ill-formed.

19.11.1.1.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> default_delete(const default_delete<U[]>&) noexcept;
    template<class U> void operator()(U* ptr) const;
  };
}
template<class U> default_delete(const default_delete<U[]>& other) noexcept;
Effects: Constructs a default_­delete object from another default_­delete<U[]> object.
Remarks: This constructor shall not participate in overload resolution unless U(*)[] is convertible to T(*)[].
template<class U> void operator()(U* ptr) const;
Effects: Calls delete[] on ptr.
Remarks: If U is an incomplete type, the program is ill-formed.
This function shall not participate in overload resolution unless U(*)[] is convertible to T(*)[].

19.11.1.2 unique_­ptr for single objects [unique.ptr.single]

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;

    // [unique.ptr.single.ctor], constructors
    constexpr unique_ptr() noexcept;
    explicit unique_ptr(pointer p) noexcept;
    unique_ptr(pointer p, see below d1) noexcept;
    unique_ptr(pointer p, see below d2) noexcept;
    unique_ptr(unique_ptr&& u) noexcept;
    constexpr unique_ptr(nullptr_t) noexcept;
    template<class U, class E>
      unique_ptr(unique_ptr<U, E>&& u) noexcept;

    // [unique.ptr.single.dtor], destructor
    ~unique_ptr();

    // [unique.ptr.single.asgn], assignment
    unique_ptr& operator=(unique_ptr&& u) noexcept;
    template<class U, class E>
      unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept;
    unique_ptr& operator=(nullptr_t) noexcept;

    // [unique.ptr.single.observers], observers
    add_lvalue_reference_t<T> operator*() const;
    pointer operator->() const noexcept;
    pointer get() const noexcept;
    deleter_type& get_deleter() noexcept;
    const deleter_type& get_deleter() const noexcept;
    explicit operator bool() const noexcept;

    // [unique.ptr.single.modifiers], modifiers
    pointer release() noexcept;
    void reset(pointer p = pointer()) noexcept;
    void swap(unique_ptr& u) noexcept;

    // disable copy from lvalue
    unique_ptr(const unique_ptr&) = delete;
    unique_ptr& operator=(const unique_ptr&) = delete;
  };
}
The default type for the template parameter D is default_­delete.
A client-supplied template argument D shall be a function object type, lvalue reference to function, or lvalue reference to function object type for which, given a value d of type D and a value ptr of type unique_­ptr<T, D>​::​pointer, the expression d(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 satisfy the Cpp17Destructible requirements (Table 29).
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.
Otherwise unique_­ptr<T, D>​::​pointer shall be a synonym for element_­type*.
The type unique_­ptr<T, D>​::​pointer shall satisfy the Cpp17NullablePointer requirements (Table 30).
[Example
:
Given an allocator type X (Table 33) and letting A be a synonym for allocator_­traits<X>, the types A​::​pointer, A​::​const_­pointer, A​::​void_­pointer, and A​::​const_­void_­pointer may be used as unique_­ptr<T, D>​::​pointer.
end example
]

19.11.1.2.1 Constructors [unique.ptr.single.ctor]

constexpr unique_ptr() noexcept; constexpr unique_ptr(nullptr_t) noexcept;
Requires: D shall satisfy the Cpp17DefaultConstructible requirements (Table 24), and that construction shall not throw an exception.
Effects: Constructs a unique_­ptr object that owns nothing, value-initializing the stored pointer and the stored deleter.
Ensures: get() == nullptr.
get_­deleter() returns a reference to the stored deleter.
Remarks: If is_­pointer_­v<deleter_­type> is true or is_­default_­constructible_­v<deleter_­type> is false, this constructor shall not participate in overload resolution.
explicit unique_ptr(pointer p) noexcept;
Requires: D shall satisfy the Cpp17DefaultConstructible requirements (Table 24), and that construction shall not throw an exception.
Effects: Constructs a unique_­ptr which owns p, initializing the stored pointer with p and value-initializing the stored deleter.
Ensures: get() == p.
get_­deleter() returns a reference to the stored deleter.
Remarks: If is_­pointer_­v<deleter_­type> is true or is_­default_­constructible_­v<deleter_­type> is false, this constructor shall not participate in overload resolution.
If class template argument deduction ([over.match.class.deduct]) would select the function template corresponding to this constructor, then the program is ill-formed.
unique_ptr(pointer p, see below d1) noexcept; unique_ptr(pointer p, see below d2) noexcept;
The signature of these constructors depends upon whether D is a reference type.
If D is a non-reference type A, then the signatures are:
unique_ptr(pointer p, const A& d) noexcept;
unique_ptr(pointer p, A&& d) noexcept;
If D is an lvalue reference type A&, then the signatures are:
unique_ptr(pointer p, A& d) noexcept;
unique_ptr(pointer p, A&& d) = delete;
If D is an lvalue reference type const A&, then the signatures are:
unique_ptr(pointer p, const A& d) noexcept;
unique_ptr(pointer p, const A&& d) = delete;
Requires: For the first constructor, if D is not a reference type, D shall satisfy the Cpp17CopyConstructible requirements and such construction shall not exit via an exception.
For the second constructor, if D is not a reference type, D shall satisfy the Cpp17MoveConstructible requirements and such construction shall 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).
Remarks: These constructors shall not participate in overload resolution unless is_­constructible_­v<D, decltype(d)> is true.
Ensures: 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 class template argument deduction ([over.match.class.deduct]) would select a function template corresponding to either of these constructors, then the program is ill-formed.
[Example
:
D d;
unique_ptr<int, D> p1(new int, D());        // D must be Cpp17MoveConstructible
unique_ptr<int, D> p2(new int, d);          // D must be Cpp17CopyConstructible
unique_ptr<int, D&> p3(new int, d);         // p3 holds a reference to d
unique_ptr<int, const D&> p4(new int, D()); // error: rvalue deleter object combined
                                            // with reference deleter type
end example
]
unique_ptr(unique_ptr&& u) noexcept;
Requires: If D is not a reference type, D shall satisfy the Cpp17MoveConstructible requirements (Table 25).
Construction of the deleter from an rvalue of type D shall not throw an exception.
Effects: Constructs a unique_­ptr from u.
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
:
The construction of the deleter can be implemented with std​::​forward<D>.
end note
]
Ensures: 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 from u.get_­deleter().
If D is a reference type then get_­deleter() and u.get_­deleter() both reference the same lvalue deleter.
template<class U, class E> unique_ptr(unique_ptr<U, E>&& u) noexcept;
Requires: If E is not a reference type, construction of the deleter from an rvalue of type E shall be well-formed and shall not throw an exception.
Otherwise, E is a reference type and construction of the deleter from an lvalue of type E shall be well-formed and shall not throw an exception.
Remarks: This constructor shall not participate in overload resolution unless:
  • unique_­ptr<U, E>​::​pointer is implicitly convertible to pointer,
  • U is not an array type, and
  • either D is a reference type and E is the same type as D, or D is not a reference type and E is implicitly convertible to D.
Effects: Constructs a unique_­ptr from u.
If E is a reference type, this deleter is copy constructed from u's deleter; otherwise, this deleter is move constructed from u's deleter.
[Note
:
The deleter constructor can be implemented with std​::​forward<E>.
end note
]
Ensures: 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 from u.get_­deleter().

19.11.1.2.2 Destructor [unique.ptr.single.dtor]

~unique_ptr();
Requires: The expression get_­deleter()(get()) shall be well-formed, shall have well-defined behavior, and shall not throw exceptions.
[Note
:
The use of default_­delete requires T to be a complete type.
end note
]
Effects: If get() == nullptr there are no effects.
Otherwise get_­deleter()(get()).

19.11.1.2.3 Assignment [unique.ptr.single.asgn]

unique_ptr& operator=(unique_ptr&& u) noexcept;
Requires: If D is not a reference type, D shall satisfy the Cpp17MoveAssignable requirements (Table 27) and assignment of the deleter from an rvalue of type D shall not throw an exception.
Otherwise, D is a reference type; remove_­reference_­t<D> shall satisfy the Cpp17CopyAssignable requirements and assignment of the deleter from an lvalue of type D shall not throw an exception.
Effects: Calls reset(u.release()) followed by get_­deleter() = std​::​forward<D>(u.get_­deleter()).
Returns: *this.
Ensures: u.get() == nullptr.
template<class U, class E> unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept;
Requires: If E is not a reference type, assignment of the deleter from an rvalue of type E shall be well-formed and shall not throw an exception.
Otherwise, E is a reference type and assignment of the deleter from an lvalue of type E shall be well-formed and shall not throw an exception.
Remarks: This operator shall not participate in overload resolution unless:
  • unique_­ptr<U, E>​::​pointer is implicitly convertible to pointer, and
  • U is not an array type, and
  • is_­assignable_­v<D&, E&&> is true.
Effects: Calls reset(u.release()) followed by get_­deleter() = std​::​forward<E>(u.get_­deleter()).
Returns: *this.
Ensures: u.get() == nullptr.
unique_ptr& operator=(nullptr_t) noexcept;
Effects: As if by reset().
Ensures: get() == nullptr.
Returns: *this.

19.11.1.2.4 Observers [unique.ptr.single.observers]

add_lvalue_reference_t<T> operator*() const;
Requires: get() != nullptr.
Returns: *get().
pointer operator->() const noexcept;
Requires: get() != nullptr.
Returns: get().
[Note
:
The use of this function typically requires that T be a complete type.
end note
]
pointer get() const noexcept;
Returns: The stored pointer.
deleter_type& get_deleter() noexcept; const deleter_type& get_deleter() const noexcept;
Returns: A reference to the stored deleter.
explicit operator bool() const noexcept;
Returns: get() != nullptr.

19.11.1.2.5 Modifiers [unique.ptr.single.modifiers]

pointer release() noexcept;
Ensures: get() == nullptr.
Returns: The value get() had at the start of the call to release.
void reset(pointer p = pointer()) noexcept;
Requires: The expression get_­deleter()(get()) shall be well-formed, shall have well-defined behavior, and shall not throw exceptions.
Effects: Assigns p to the stored pointer, and then if and only if the old value of the stored pointer, old_­p, was not equal to nullptr, calls get_­deleter()(old_­p).
[Note
:
The order of these operations is significant because the call to get_­deleter() may destroy *this.
end note
]
Ensures: get() == p.
[Note
:
The postcondition does not hold if the call to get_­deleter() destroys *this since this->get() is no longer a valid expression.
end note
]
void swap(unique_ptr& u) noexcept;
Requires: get_­deleter() shall be swappable and shall not throw an exception under swap.
Effects: Invokes swap on the stored pointers and on the stored deleters of *this and u.

19.11.1.3 unique_­ptr for array objects with a runtime length [unique.ptr.runtime]

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;

    // [unique.ptr.runtime.ctor], constructors
    constexpr unique_ptr() noexcept;
    template<class U> explicit unique_ptr(U p) noexcept;
    template<class U> unique_ptr(U p, see below d) noexcept;
    template<class U> unique_ptr(U p, see below d) noexcept;
    unique_ptr(unique_ptr&& u) noexcept;
    template<class U, class E>
      unique_ptr(unique_ptr<U, E>&& u) noexcept;
    constexpr unique_ptr(nullptr_t) noexcept;

    // destructor
    ~unique_ptr();

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

    // [unique.ptr.runtime.observers], observers
    T& operator[](size_t i) const;
    pointer get() const noexcept;
    deleter_type& get_deleter() noexcept;
    const deleter_type& get_deleter() const noexcept;
    explicit operator bool() const noexcept;

    // [unique.ptr.runtime.modifiers], modifiers
    pointer release() noexcept;
    template<class U> void reset(U p) noexcept;
    void reset(nullptr_t = nullptr) noexcept;
    void swap(unique_ptr& u) noexcept;

    // disable copy from lvalue
    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.
  • Conversions between different types of unique_­ptr<T[], D> that would be disallowed for the corresponding pointer-to-array types, and conversions to or from the non-array forms of unique_­ptr, produce an ill-formed program.
  • Pointers to types derived from T are rejected by the constructors, and by reset.
  • The observers operator* and operator-> are not provided.
  • The indexing observer operator[] is provided.
  • The default deleter will call delete[].
Descriptions are provided below only for members that differ from the primary template.
The template argument T shall be a complete type.

19.11.1.3.1 Constructors [unique.ptr.runtime.ctor]

template<class U> 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 except that it additionally shall not participate in overload resolution unless
  • U is the same type as pointer, or
  • pointer is the same type as element_­type*, U is a pointer type V*, and V(*)[] is convertible to element_­type(*)[].
template<class U> unique_ptr(U p, see below d) noexcept; template<class U> 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 except that they shall not participate in overload resolution unless either
  • U is the same type as pointer,
  • U is nullptr_­t, or
  • pointer is the same type as element_­type*, U is a pointer type V*, and V(*)[] is convertible to element_­type(*)[].
template<class U, class E> unique_ptr(unique_ptr<U, E>&& u) noexcept;
This constructor behaves the same as in the primary template, except that it shall not participate in overload resolution unless all of the following conditions hold, where UP is unique_­ptr<U, E>:
  • U is an array type, and
  • pointer is the same type as element_­type*, and
  • UP​::​pointer is the same type as UP​::​element_­type*, and
  • UP​::​element_­type(*)[] is convertible to element_­type(*)[], and
  • either D is a reference type and E is the same type as D, or D is not a reference type and E is implicitly convertible to D.
[Note
:
This replaces the overload-resolution specification of the primary template
end note
]

19.11.1.3.2 Assignment [unique.ptr.runtime.asgn]

template<class U, class E> unique_ptr& operator=(unique_ptr<U, E>&& u)noexcept;
This operator behaves the same as in the primary template, except that it shall not participate in overload resolution unless all of the following conditions hold, where UP is unique_­ptr<U, E>:
  • U is an array type, and
  • pointer is the same type as element_­type*, and
  • UP​::​pointer is the same type as UP​::​element_­type*, and
  • UP​::​element_­type(*)[] is convertible to element_­type(*)[], and
  • is_­assignable_­v<D&, E&&> is true.
[Note
:
This replaces the overload-resolution specification of the primary template
end note
]

19.11.1.3.3 Observers [unique.ptr.runtime.observers]

T& operator[](size_t i) const;
Requires: i < the number of elements in the array to which the stored pointer points.
Returns: get()[i].

19.11.1.3.4 Modifiers [unique.ptr.runtime.modifiers]

void reset(nullptr_t p = nullptr) noexcept;
Effects: Equivalent to reset(pointer()).
template<class U> void reset(U p) noexcept;
This function behaves the same as the reset member of the primary template, except that it shall not participate in overload resolution unless either
  • U is the same type as pointer, or
  • pointer is the same type as element_­type*, U is a pointer type V*, and V(*)[] is convertible to element_­type(*)[].

19.11.1.4 Creation [unique.ptr.create]

template<class T, class... Args> unique_ptr<T> make_unique(Args&&... args);
Remarks: This function shall not participate in overload resolution unless T is not an array.
Returns: unique_­ptr<T>(new T(std​::​forward<Args>(args)...)).
template<class T> unique_ptr<T> make_unique(size_t n);
Remarks: This function shall not participate in overload resolution unless 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;
Remarks: This function shall not participate in overload resolution unless T is an array of known bound.

19.11.1.5 Specialized algorithms [unique.ptr.special]

template<class T, class D> void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) noexcept;
Remarks: This function shall not participate in overload resolution unless is_­swappable_­v<D> is true.
Effects: Calls x.swap(y).
template<class T1, class D1, class T2, class D2> 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> 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> bool operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
Requires: Let CT denote
common_type_t<typename unique_ptr<T1, D1>::pointer,
              typename unique_ptr<T2, D2>::pointer>
Then the specialization less<CT> shall be a function object type that induces a strict weak ordering on the pointer values.
Returns: less<CT>()(x.get(), y.get()).
Remarks: If unique_­ptr<T1, D1>​::​pointer is not implicitly convertible to CT or unique_­ptr<T2, D2>​::​pointer is not implicitly convertible to CT, the program is ill-formed.
template<class T1, class D1, class T2, class D2> bool operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
Returns: y < x.
template<class T1, class D1, class T2, class D2> bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
Returns: !(y < x).
template<class T1, class D1, class T2, class D2> bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
Returns: !(x < y).
template<class T, class D> bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept; template<class T, class D> bool operator==(nullptr_t, const unique_ptr<T, D>& x) noexcept;
Returns: !x.
template<class T, class D> bool operator!=(const unique_ptr<T, D>& x, nullptr_t) noexcept; template<class T, class D> bool operator!=(nullptr_t, const unique_ptr<T, D>& x) noexcept;
Returns: (bool)x.
template<class T, class D> bool operator<(const unique_ptr<T, D>& x, nullptr_t); template<class T, class D> bool operator<(nullptr_t, const unique_ptr<T, D>& x);
Requires: The specialization less<unique_­ptr<T, D>​::​pointer> shall be a function object type that induces a strict weak ordering on the pointer values.
Returns: The first function template returns
less<unique_ptr<T, D>::pointer>()(x.get(), nullptr)
The second function template returns
less<unique_ptr<T, D>::pointer>()(nullptr, x.get())
template<class T, class D> bool operator>(const unique_ptr<T, D>& x, nullptr_t); template<class T, class D> 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> bool operator<=(const unique_ptr<T, D>& x, nullptr_t); template<class T, class D> 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> bool operator>=(const unique_ptr<T, D>& x, nullptr_t); template<class T, class D> 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).

19.11.1.6 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);
Effects: Equivalent to: os << p.get();
Returns: os.
Remarks: This function shall not participate in overload resolution unless os << p.get() is a valid expression.

19.11.2 Class bad_­weak_­ptr [util.smartptr.weak.bad]

namespace std {
  class bad_weak_ptr : public exception {
  public:
    bad_weak_ptr() noexcept;
  };
}
An exception of type bad_­weak_­ptr is thrown by the shared_­ptr constructor taking a weak_­ptr.
bad_weak_ptr() noexcept;
Ensures: what() returns an implementation-defined ntbs.

19.11.3 Class template shared_­ptr [util.smartptr.shared]

The shared_­ptr class template stores a pointer, usually obtained via new.
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.
A shared_­ptr is said to be empty if it does not own a pointer.
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], constructors
    constexpr shared_ptr() noexcept;
    constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { }
    template<class Y>
      explicit shared_ptr(Y* p);
    template<class Y, class D>
      shared_ptr(Y* p, D d);
    template<class Y, class D, class A>
      shared_ptr(Y* p, D d, A a);
    template<class D>
      shared_ptr(nullptr_t p, D d);
    template<class D, class A>
      shared_ptr(nullptr_t p, D d, A a);
    template<class Y>
      shared_ptr(const shared_ptr<Y>& r, element_type* p) noexcept;
    shared_ptr(const shared_ptr& r) noexcept;
    template<class Y>
      shared_ptr(const shared_ptr<Y>& r) noexcept;
    shared_ptr(shared_ptr&& r) noexcept;
    template<class Y>
      shared_ptr(shared_ptr<Y>&& r) noexcept;
    template<class Y>
      explicit shared_ptr(const weak_ptr<Y>& r);
    template<class Y, class D>
      shared_ptr(unique_ptr<Y, D>&& r);

    // [util.smartptr.shared.dest], destructor
    ~shared_ptr();

    // [util.smartptr.shared.assign], assignment
    shared_ptr& operator=(const shared_ptr& r) noexcept;
    template<class Y>
      shared_ptr& operator=(const shared_ptr<Y>& r) noexcept;
    shared_ptr& operator=(shared_ptr&& r) noexcept;
    template<class Y>
      shared_ptr& operator=(shared_ptr<Y>&& r) noexcept;
    template<class Y, class D>
      shared_ptr& operator=(unique_ptr<Y, D>&& r);

    // [util.smartptr.shared.mod], modifiers
    void swap(shared_ptr& r) noexcept;
    void reset() noexcept;
    template<class Y>
      void reset(Y* p);
    template<class Y, class D>
      void reset(Y* p, D d);
    template<class Y, class D, class A>
      void reset(Y* p, D d, A a);

    // [util.smartptr.shared.obs], observers
    element_type* get() const noexcept;
    T& operator*() const noexcept;
    T* operator->() const noexcept;
    element_type& operator[](ptrdiff_t i) const;
    long use_count() const noexcept;
    explicit operator bool() const noexcept;
    template<class U>
      bool owner_before(const shared_ptr<U>& b) const noexcept;
    template<class U>
      bool owner_before(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>;
}
Specializations of shared_­ptr shall be Cpp17CopyConstructible, Cpp17CopyAssignable, and Cpp17LessThanComparable, allowing their use in standard containers.
Specializations of shared_­ptr shall be contextually convertible to bool, allowing their use in boolean expressions and declarations in conditions.
The template parameter T of shared_­ptr may be an incomplete type.
[Example
:
if (shared_ptr<X> px = dynamic_pointer_cast<X>(py)) {
  // do something with px
}
end example
]
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.
Changes in use_­count() do not reflect modifications that can introduce data races.
For the purposes of subclause [smartptr], a pointer type Y* is said to be compatible with a pointer type T* when either Y* is convertible to T* or Y is U[N] and T is cv U[].

19.11.3.1 Constructors [util.smartptr.shared.const]

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, 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]).
constexpr shared_ptr() noexcept;
Effects: Constructs an empty shared_­ptr object.
Ensures: use_­count() == 0 && get() == nullptr.
template<class Y> explicit shared_ptr(Y* p);
Requires: Y shall be a complete type.
The expression delete[] p, when T is an array type, or delete p, when T is not an array type, shall have well-defined behavior, and shall not throw exceptions.
Effects: When T is not an array type, constructs a shared_­ptr object that owns the pointer p.
Otherwise, constructs a shared_­ptr that owns p and a deleter of an unspecified type that calls delete[] p.
When T is not an array type, enables shared_­from_­this with p.
If an exception is thrown, delete p is called when T is not an array type, delete[] p otherwise.
Ensures: use_­count() == 1 && get() == p.
Throws: bad_­alloc, or an implementation-defined exception when a resource other than memory could not be obtained.
Remarks: When T is an array type, this constructor shall not participate in overload resolution unless the expression delete[] p is well-formed and either T is U[N] and Y(*)[N] is convertible to T*, or T is U[] and Y(*)[] is convertible to T*.
When T is not an array type, this constructor shall not participate in overload resolution unless the expression delete p is well-formed and Y* is convertible to T*.
template<class Y, class D> shared_ptr(Y* p, D d); template<class Y, class D, class A> shared_ptr(Y* p, D d, A a); template<class D> shared_ptr(nullptr_t p, D d); template<class D, class A> shared_ptr(nullptr_t p, D d, A a);
Requires: Construction of d and a deleter of type D initialized with std​::​move(d) shall not throw exceptions.
The expression d(p) shall have well-defined behavior and shall not throw exceptions.
A shall satisfy the Cpp17Allocator requirements (Table 33).
Effects: Constructs a shared_­ptr object that owns the object p and the deleter d.
When T is not an array type, the first and second constructors enable shared_­from_­this with p.
The second and fourth constructors shall use a copy of a to allocate memory for internal use.
If an exception is thrown, d(p) is called.
Ensures: use_­count() == 1 && get() == p.
Throws: bad_­alloc, or an implementation-defined exception when a resource other than memory could not be obtained.
Remarks: When T is an array type, this constructor shall not participate in overload resolution unless is_­move_­constructible_­v<D> is true, the expression d(p) is well-formed, and either T is U[N] and Y(*)[N] is convertible to T*, or T is U[] and Y(*)[] is convertible to T*.
When T is not an array type, this constructor shall not participate in overload resolution unless is_­move_­constructible_­v<D> is true, the expression d(p) is well-formed, and Y* is convertible to T*.
template<class Y> shared_ptr(const shared_ptr<Y>& r, element_type* p) noexcept;
Effects: Constructs a shared_­ptr instance that stores p and shares ownership with r.
Ensures: get() == p && use_­count() == r.use_­count().
[Note
:
To avoid the possibility of a dangling pointer, the user of this constructor should ensure that p remains valid at least until the ownership group of r is destroyed.
end note
]
[Note
:
This constructor allows creation of an empty shared_­ptr instance with a non-null stored pointer.
end note
]
shared_ptr(const shared_ptr& r) noexcept; template<class Y> shared_ptr(const shared_ptr<Y>& r) noexcept;
Remarks: The second constructor shall not participate in overload resolution unless Y* is compatible with T*.
Effects: If r is empty, constructs an empty shared_­ptr object; otherwise, constructs a shared_­ptr object that shares ownership with r.
Ensures: get() == r.get() && use_­count() == r.use_­count().
shared_ptr(shared_ptr&& r) noexcept; template<class Y> shared_ptr(shared_ptr<Y>&& r) noexcept;
Remarks: The second constructor shall not participate in overload resolution unless Y* is compatible with T*.
Effects: Move constructs a shared_­ptr instance from r.
Ensures: *this shall contain the old value of r.
r shall be empty.
r.get() == nullptr.
template<class Y> explicit shared_ptr(const weak_ptr<Y>& r);
Effects: Constructs a shared_­ptr object that shares ownership with r and stores a copy of the pointer stored in r.
If an exception is thrown, the constructor has no effect.
Ensures: use_­count() == r.use_­count().
Throws: bad_­weak_­ptr when r.expired().
Remarks: This constructor shall not participate in overload resolution unless Y* is compatible with T*.
template<class Y, class D> shared_ptr(unique_ptr<Y, D>&& r);
Remarks: This constructor shall not participate in overload resolution unless Y* is compatible with T* and unique_­ptr<Y, D>​::​pointer is convertible to element_­type*.
Effects: If r.get() == nullptr, equivalent to shared_­ptr().
Otherwise, if D is not a reference type, equivalent to shared_­ptr(r.release(), r.get_­deleter()).
Otherwise, equivalent to shared_­ptr(r.release(), ref(r.get_­deleter())).
If an exception is thrown, the constructor has no effect.

19.11.3.2 Destructor [util.smartptr.shared.dest]

~shared_ptr();
Effects:
  • If *this is empty or shares ownership with another shared_­ptr instance (use_­count() > 1), there are no side effects.
  • Otherwise, if *this owns an object p and a deleter d, d(p) is called.
  • Otherwise, *this owns a pointer p, and delete p is called.
[Note
:
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.
end note
]

19.11.3.3 Assignment [util.smartptr.shared.assign]

shared_ptr& operator=(const shared_ptr& r) noexcept; template<class Y> shared_ptr& operator=(const shared_ptr<Y>& r) noexcept;
Effects: Equivalent to shared_­ptr(r).swap(*this).
Returns: *this.
[Note
:
The use count updates caused by the temporary object construction and destruction are not observable side effects, so the implementation may meet the effects (and the implied guarantees) via different means, without creating a temporary.
In particular, in the example:
shared_ptr<int> p(new int);
shared_ptr<void> q(p);
p = p;
q = p;
both assignments may be no-ops.
end note
]
shared_ptr& operator=(shared_ptr&& r) noexcept; template<class Y> shared_ptr& operator=(shared_ptr<Y>&& r) noexcept;
Effects: Equivalent to shared_­ptr(std​::​move(r)).swap(*this).
Returns: *this.
template<class Y, class D> shared_ptr& operator=(unique_ptr<Y, D>&& r);
Effects: Equivalent to shared_­ptr(std​::​move(r)).swap(*this).
Returns: *this.

19.11.3.4 Modifiers [util.smartptr.shared.mod]

void swap(shared_ptr& r) noexcept;
Effects: Exchanges the contents of *this and r.
void reset() noexcept;
Effects: Equivalent to shared_­ptr().swap(*this).
template<class Y> void reset(Y* p);
Effects: Equivalent to shared_­ptr(p).swap(*this).
template<class Y, class D> void reset(Y* p, D d);
Effects: Equivalent to shared_­ptr(p, d).swap(*this).
template<class Y, class D, class A> void reset(Y* p, D d, A a);
Effects: Equivalent to shared_­ptr(p, d, a).swap(*this).

19.11.3.5 Observers [util.smartptr.shared.obs]

element_type* get() const noexcept;
Returns: The stored pointer.
T& operator*() const noexcept;
Requires: get() != 0.
Returns: *get().
Remarks: When T is an array type or cv void, it is unspecified whether this member function is declared.
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.
T* operator->() const noexcept;
Requires: get() != 0.
Returns: get().
Remarks: When T is an array type, it is unspecified whether this member function is declared.
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.
element_type& operator[](ptrdiff_t i) const;
Requires: get() != 0 && i >= 0.
If T is U[N], i < N.
Returns: get()[i].
Remarks: When T is not an array type, it is unspecified whether this member function is declared.
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.
Throws: Nothing.
long use_count() const noexcept;
Returns: The number of shared_­ptr objects, *this included, that share ownership with *this, or 0 when *this is empty.
Synchronization: None.
[Note
:
get() == nullptr does not imply a specific return value of use_­count().
end note
]
[Note
:
weak_­ptr<T>​::​lock() can affect the return value of use_­count().
end note
]
[Note
:
When multiple threads can affect the return value of use_­count(), the result should be treated as approximate.
In particular, use_­count() == 1 does not imply that accesses through a previously destroyed shared_­ptr have in any sense completed.
end note
]
explicit operator bool() const noexcept;
Returns: get() != 0.
template<class U> bool owner_before(const shared_ptr<U>& b) const noexcept; template<class U> bool owner_before(const weak_ptr<U>& b) const noexcept;
Returns: An unspecified value such that
  • x.owner_­before(y) defines a strict weak ordering as defined in [alg.sorting];
  • under the equivalence relation defined by owner_­before, !a.owner_­before(b) && !b.owner_­before(a), two shared_­ptr or weak_­ptr instances are equivalent if and only if they share ownership or are both empty.

19.11.3.6 Creation [util.smartptr.shared.create]

The common requirements that apply to all make_­shared and allocate_­shared overloads, unless specified otherwise, are described below.
template<class T, ...> shared_ptr<T> make_shared(args); template<class T, class A, ...> shared_ptr<T> allocate_shared(const A& a, args);
Requires: A shall satisfy the Cpp17Allocator requirements (Table 33).
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).
The object is initialized from args as specified by the concrete overload.
The allocate_­shared templates use a copy of a (rebound for an unspecified value_­type) to allocate memory.
If an exception is thrown, the functions have no effect.
Returns: A shared_­ptr instance that stores and owns the address of the newly constructed object.
Ensures: r.get() != 0 && r.use_­count() == 1, where r is the return value.
Throws: bad_­alloc, or an exception thrown from allocate or from the initialization of the object.
Remarks:
  • Implementations should perform no more than one memory allocation.
    [Note
    :
    This provides efficiency equivalent to an intrusive smart pointer.
    end note
    ]
  • 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.
  • 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.
  • 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.
  • 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
    • allocator_­traits<A2>​::​construct(a2, pv, v) or
    • allocator_­traits<A2>​::​construct(a2, pv, l...)
    respectively, where pv points to storage suitable to hold an object of type U and a2 of type A2 is a rebound copy of the allocator a passed to allocate_­shared such that its value_­type is remove_­cv_­t<U>.
  • 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.
  • When a (sub)object of non-array type U is specified to have a default initial value, allocate_­shared shall initialize this (sub)object via the expression allocator_­traits<A2>​::​construct(a2, pv), where pv points to storage suitable to hold an object of type U and a2 of type A2 is a rebound copy of the allocator a passed to allocate_­shared such that its value_­type is remove_­cv_­t<U>.
  • Array elements are initialized in ascending order of their addresses.
  • 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.
[Note
:
These functions will typically allocate more memory than sizeof(T) to allow for internal bookkeeping structures such as reference counts.
end note
]
template<class T, class... Args> shared_ptr<T> make_shared(Args&&... args); // T is not array template<class T, class A, class... Args> shared_ptr<T> allocate_shared(const A& a, Args&&... args); // T is not array
Returns: A shared_­ptr to an object of type T with an initial value T(forward<Args>(args)...).
Remarks: These overloads shall only participate in overload resolution when T is not an array type.
The shared_­ptr constructors called by these functions enable shared_­from_­this with the address of the newly constructed object of type T.
[Example
:
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
]
template<class T> shared_ptr<T> make_shared(size_t N); // T is U[] template<class T, class A> shared_ptr<T> allocate_shared(const A& a, size_t N); // T is U[]
Returns: A shared_­ptr to an object of type U[N] with a default initial value, where U is remove_­extent_­t<T>.
Remarks: These overloads shall only participate in overload resolution when T is of the form U[].
[Example
:
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
]
template<class T> shared_ptr<T> make_shared(); // T is U[N] template<class T, class A> shared_ptr<T> allocate_shared(const A& a); // T is U[N]
Returns: A shared_­ptr to an object of type T with a default initial value.
Remarks: These overloads shall only participate in overload resolution when T is of the form U[N].
[Example
:
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
]
template<class T> shared_ptr<T> make_shared(size_t N, const remove_extent_t<T>& u); // T is U[] template<class T, class A> shared_ptr<T> allocate_shared(const A& a, size_t N, const remove_extent_t<T>& u); // T is U[]
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.
Remarks: These overloads shall only participate in overload resolution when T is of the form U[].
[Example
:
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
]
template<class T> shared_ptr<T> make_shared(const remove_extent_t<T>& u); // T is U[N] template<class T, class A> shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& u); // T is U[N]
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.
Remarks: These overloads shall only participate in overload resolution when T is of the form U[N].
[Example
:
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
]

19.11.3.7 Comparison [util.smartptr.shared.cmp]

template<class T, class U> bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
Returns: a.get() == b.get().
template<class T, class U> bool operator<(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
Returns: less<>()(a.get(), b.get()).
[Note
:
Defining a comparison function allows shared_­ptr objects to be used as keys in associative containers.
end note
]
template<class T> bool operator==(const shared_ptr<T>& a, nullptr_t) noexcept; template<class T> bool operator==(nullptr_t, const shared_ptr<T>& a) noexcept;
Returns: !a.
template<class T> bool operator!=(const shared_ptr<T>& a, nullptr_t) noexcept; template<class T> bool operator!=(nullptr_t, const shared_ptr<T>& a) noexcept;
Returns: (bool)a.
template<class T> bool operator<(const shared_ptr<T>& a, nullptr_t) noexcept; template<class T> bool operator<(nullptr_t, const shared_ptr<T>& a) noexcept;
Returns: The first function template returns
less<typename shared_ptr<T>::element_type*>()(a.get(), nullptr)
The second function template returns
less<typename shared_ptr<T>::element_type*>()(nullptr, a.get())
template<class T> bool operator>(const shared_ptr<T>& a, nullptr_t) noexcept; template<class T> bool operator>(nullptr_t, const shared_ptr<T>& a) noexcept;
Returns: The first function template returns nullptr < a.
The second function template returns a < nullptr.
template<class T> bool operator<=(const shared_ptr<T>& a, nullptr_t) noexcept; template<class T> bool operator<=(nullptr_t, const shared_ptr<T>& a) noexcept;
Returns: The first function template returns !(nullptr < a).
The second function template returns !(a < nullptr).
template<class T> bool operator>=(const shared_ptr<T>& a, nullptr_t) noexcept; template<class T> bool operator>=(nullptr_t, const shared_ptr<T>& a) noexcept;
Returns: The first function template returns !(a < nullptr).
The second function template returns !(nullptr < a).

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

template<class T> void swap(shared_ptr<T>& a, shared_ptr<T>& b) noexcept;
Effects: Equivalent to a.swap(b).

19.11.3.9 Casts [util.smartptr.shared.cast]

template<class T, class U> shared_ptr<T> static_pointer_cast(const shared_ptr<U>& r) noexcept;
Requires: The expression static_­cast<T*>((U*)nullptr) shall be well-formed.
Returns:
shared_ptr<T>(r, static_cast<typename shared_ptr<T>::element_type*>(r.get()))
[Note
:
The seemingly equivalent expression shared_­ptr<T>(static_­cast<T*>(r.get())) will eventually result in undefined behavior, attempting to delete the same object twice.
end note
]
template<class T, class U> shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& r) noexcept;
Requires: The expression dynamic_­cast<T*>((U*)nullptr) shall be well-formed.
The expression dynamic_­cast<typename shared_­ptr<T>​::​element_­type*>(r.get()) shall be well formed and shall have well-defined behavior.
Returns:
  • When dynamic_­cast<typename shared_­ptr<T>​::​element_­type*>(r.get()) returns a non-null value p, shared_­ptr<T>(r, p).
  • Otherwise, shared_­ptr<T>().
[Note
:
The seemingly equivalent expression shared_­ptr<T>(dynamic_­cast<T*>(r.get())) will eventually result in undefined behavior, attempting to delete the same object twice.
end note
]
template<class T, class U> shared_ptr<T> const_pointer_cast(const shared_ptr<U>& r) noexcept;
Requires: The expression const_­cast<T*>((U*)nullptr) shall be well-formed.
Returns:
shared_ptr<T>(r, const_cast<typename shared_ptr<T>::element_type*>(r.get()))
[Note
:
The seemingly equivalent expression shared_­ptr<T>(const_­cast<T*>(r.get())) will eventually result in undefined behavior, attempting to delete the same object twice.
end note
]
template<class T, class U> shared_ptr<T> reinterpret_pointer_cast(const shared_ptr<U>& r) noexcept;
Requires: The expression reinterpret_­cast<T*>((U*)nullptr) shall be well-formed.
Returns:
shared_ptr<T>(r, reinterpret_cast<typename shared_ptr<T>::element_type*>(r.get()))
[Note
:
The seemingly equivalent expression shared_­ptr<T>(reinterpret_­cast<T*>(r.get())) will eventually result in undefined behavior, attempting to delete the same object twice.
end note
]

19.11.3.10 get_­deleter [util.smartptr.getdeleter]

template<class D, class T> D* get_deleter(const shared_ptr<T>& p) noexcept;
Returns: If p owns a deleter d of type cv-unqualified D, returns addressof(d); otherwise returns nullptr.
The returned pointer remains valid as long as there exists a shared_­ptr instance that owns d.
[Note
:
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 with p have been destroyed.
end note
]

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

template<class E, class T, class Y> basic_ostream<E, T>& operator<<(basic_ostream<E, T>& os, const shared_ptr<Y>& p);
Effects: As if by: os << p.get();
Returns: os.

19.11.4 Class template weak_­ptr [util.smartptr.weak]

The weak_­ptr class template stores a weak reference to an object that is already managed by a shared_­ptr.
To access the object, a weak_­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>;

    // [util.smartptr.weak.const], constructors
    constexpr weak_ptr() noexcept;
    template<class Y>
      weak_ptr(const shared_ptr<Y>& r) noexcept;
    weak_ptr(const weak_ptr& r) noexcept;
    template<class Y>
      weak_ptr(const weak_ptr<Y>& r) noexcept;
    weak_ptr(weak_ptr&& r) noexcept;
    template<class Y>
      weak_ptr(weak_ptr<Y>&& r) noexcept;

    // [util.smartptr.weak.dest], destructor
    ~weak_ptr();

    // [util.smartptr.weak.assign], assignment
    weak_ptr& operator=(const weak_ptr& r) noexcept;
    template<class Y>
      weak_ptr& operator=(const weak_ptr<Y>& r) noexcept;
    template<class Y>
      weak_ptr& operator=(const shared_ptr<Y>& r) noexcept;
    weak_ptr& operator=(weak_ptr&& r) noexcept;
    template<class Y>
      weak_ptr& operator=(weak_ptr<Y>&& r) noexcept;

    // [util.smartptr.weak.mod], modifiers
    void swap(weak_ptr& r) noexcept;
    void reset() noexcept;

    // [util.smartptr.weak.obs], observers
    long use_count() const noexcept;
    bool expired() const noexcept;
    shared_ptr<T> lock() const noexcept;
    template<class U>
      bool owner_before(const shared_ptr<U>& b) const noexcept;
    template<class U>
      bool owner_before(const weak_ptr<U>& b) const noexcept;
  };

  template<class T>
    weak_ptr(shared_ptr<T>) -> weak_ptr<T>;

  // [util.smartptr.weak.spec], specialized algorithms
  template<class T>
    void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept;
}
Specializations of weak_­ptr shall be Cpp17CopyConstructible and Cpp17CopyAssignable, allowing their use in standard containers.
The template parameter T of weak_­ptr may be an incomplete type.

19.11.4.1 Constructors [util.smartptr.weak.const]

constexpr weak_ptr() noexcept;
Effects: Constructs an empty weak_­ptr object.
Ensures: use_­count() == 0.
weak_ptr(const weak_ptr& r) noexcept; template<class Y> weak_ptr(const weak_ptr<Y>& r) noexcept; template<class Y> weak_ptr(const shared_ptr<Y>& r) noexcept;
Remarks: The second and third constructors shall not participate in overload resolution unless Y* is compatible with T*.
Effects: If r is empty, constructs an empty weak_­ptr object; otherwise, constructs a weak_­ptr object that shares ownership with r and stores a copy of the pointer stored in r.
Ensures: use_­count() == r.use_­count().
weak_ptr(weak_ptr&& r) noexcept; template<class Y> weak_ptr(weak_ptr<Y>&& r) noexcept;
Remarks: The second constructor shall not participate in overload resolution unless Y* is compatible with T*.
Effects: Move constructs a weak_­ptr instance from r.
Ensures: *this shall contain the old value of r.
r shall be empty.
r.use_­count() == 0.

19.11.4.2 Destructor [util.smartptr.weak.dest]

~weak_ptr();
Effects: Destroys this weak_­ptr object but has no effect on the object its stored pointer points to.

19.11.4.3 Assignment [util.smartptr.weak.assign]

weak_ptr& operator=(const weak_ptr& r) noexcept; template<class Y> weak_ptr& operator=(const weak_ptr<Y>& r) noexcept; template<class Y> 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.
Returns: *this.
weak_ptr& operator=(weak_ptr&& r) noexcept; template<class Y> weak_ptr& operator=(weak_ptr<Y>&& r) noexcept;
Effects: Equivalent to weak_­ptr(std​::​move(r)).swap(*this).
Returns: *this.

19.11.4.4 Modifiers [util.smartptr.weak.mod]

void swap(weak_ptr& r) noexcept;
Effects: Exchanges the contents of *this and r.
void reset() noexcept;
Effects: Equivalent to weak_­ptr().swap(*this).

19.11.4.5 Observers [util.smartptr.weak.obs]

long use_count() const noexcept;
Returns: 0 if *this is empty; otherwise, the number of shared_­ptr instances that share ownership with *this.
bool expired() const noexcept;
Returns: use_­count() == 0.
shared_ptr<T> lock() const noexcept;
Returns: expired() ? shared_­ptr<T>() : shared_­ptr<T>(*this), executed atomically.
template<class U> bool owner_before(const shared_ptr<U>& b) const noexcept; template<class U> bool owner_before(const weak_ptr<U>& b) const noexcept;
Returns: An unspecified value such that
  • x.owner_­before(y) defines a strict weak ordering as defined in [alg.sorting];
  • under the equivalence relation defined by owner_­before, !a.owner_­before(b) && !b.owner_­before(a), two shared_­ptr or weak_­ptr instances are equivalent if and only if they share ownership or are both empty.

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

template<class T> void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept;
Effects: Equivalent to a.swap(b).

19.11.5 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>> {
    bool operator()(const shared_ptr<T>&, const shared_ptr<T>&) const noexcept;
    bool operator()(const shared_ptr<T>&, const weak_ptr<T>&) const noexcept;
    bool operator()(const weak_ptr<T>&, const shared_ptr<T>&) const noexcept;
  };

  template<class T> struct owner_less<weak_ptr<T>> {
    bool operator()(const weak_ptr<T>&, const weak_ptr<T>&) const noexcept;
    bool operator()(const shared_ptr<T>&, const weak_ptr<T>&) const noexcept;
    bool operator()(const weak_ptr<T>&, const shared_ptr<T>&) const noexcept;
  };

  template<> struct owner_less<void> {
    template<class T, class U>
      bool operator()(const shared_ptr<T>&, const shared_ptr<U>&) const noexcept;
    template<class T, class U>
      bool operator()(const shared_ptr<T>&, const weak_ptr<U>&) const noexcept;
    template<class T, class U>
      bool operator()(const weak_ptr<T>&, const shared_ptr<U>&) const noexcept;
    template<class T, class U>
      bool operator()(const weak_ptr<T>&, const weak_ptr<U>&) const noexcept;

    using is_transparent = unspecified;
  };
}
operator()(x, y) shall return x.owner_­before(y).
[Note
:
Note that
  • operator() defines a strict weak ordering as defined in [alg.sorting];
  • under the equivalence relation defined by operator(), !operator()(a, b) && !operator()(b, a), two shared_­ptr or weak_­ptr instances are equivalent if and only if they share ownership or are both empty.
end note
]

19.11.6 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
:
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_before(q) && !q.owner_before(p)); // p and q share ownership
}
end example
]
namespace std {
  template<class T> class enable_shared_from_this {
  protected:
    constexpr enable_shared_from_this() noexcept;
    enable_shared_from_this(const enable_shared_from_this&) noexcept;
    enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept;
    ~enable_shared_from_this();

  public:
    shared_ptr<T> shared_from_this();
    shared_ptr<T const> shared_from_this() const;
    weak_ptr<T> weak_from_this() noexcept;
    weak_ptr<T const> weak_from_this() const noexcept;

  private:
    mutable weak_ptr<T> weak_this;  // exposition only
  };
}
The template parameter T of enable_­shared_­from_­this may be an incomplete type.
constexpr enable_shared_from_this() noexcept; enable_shared_from_this(const enable_shared_from_this<T>&) noexcept;
Effects: Value-initializes weak_­this.
enable_shared_from_this<T>& operator=(const enable_shared_from_this<T>&) noexcept;
Returns: *this.
[Note
:
weak_­this is not changed.
end note
]
shared_ptr<T> shared_from_this(); shared_ptr<T const> shared_from_this() const;
Returns: shared_­ptr<T>(weak_­this).
weak_ptr<T> weak_from_this() noexcept; weak_ptr<T const> weak_from_this() const noexcept;
Returns: weak_­this.

19.11.7 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) shall evaluate to the same value as hash<typename UP​::​pointer>()(p.get()).
The member functions are not guaranteed to be noexcept.
template<class T> struct hash<shared_ptr<T>>;
For an object p of type shared_­ptr<T>, hash<shared_­ptr<T>>()(p) shall evaluate to the same value as hash<typename shared_­ptr<T>​::​element_­type*>()(p.get()).

19.11.8 Atomic specializations for smart pointers [util.smartptr.atomic]

The library provides partial specializations of the atomic template for shared-ownership smart pointers.
The behavior of all operations is as specified in [atomics.types.generic], unless specified otherwise.
The template parameter T of these partial specializations may be an incomplete type.
All changes to an atomic smart pointer in this subclause, and all associated use_­count increments, are guaranteed to be performed atomically.
Associated use_­count decrements are sequenced after the atomic operation, but are not required to be part of it.
Any associated deletion and deallocation are sequenced after the atomic update step and are not part of the atomic operation.
[Note
:
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.
end note
]

19.11.8.1 Atomic specialization for shared_­ptr [util.smartptr.atomic.shared]

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;
    void store(shared_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
    shared_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
    operator shared_ptr<T>() const noexcept;

    shared_ptr<T> exchange(shared_ptr<T> desired,
                           memory_order order = memory_order::seq_cst) noexcept;

    bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
                               memory_order success, memory_order failure) noexcept;
    bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
                                 memory_order success, memory_order failure) noexcept;

    bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired,
                               memory_order order = memory_order::seq_cst) noexcept;
    bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired,
                                 memory_order order = memory_order::seq_cst) noexcept;

    constexpr atomic() noexcept = default;
    atomic(shared_ptr<T> desired) noexcept;
    atomic(const atomic&) = delete;
    void operator=(const atomic&) = delete;
    void operator=(shared_ptr<T> desired) noexcept;

  private:
    shared_ptr<T> p;            // exposition only
  };
}
constexpr atomic() noexcept = default;
Effects: Initializes p{}.
atomic(shared_ptr<T> desired) noexcept;
Effects: Initializes the object with the value desired.
Initialization is not an atomic operation ([intro.multithread]).
[Note
:
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.
This results in undefined behavior.
end note
]
void store(shared_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
Requires: The order argument shall not be memory_­order​::​consume, memory_­order​::​acquire, nor memory_­order​::​acq_­rel.
Effects: Atomically replaces the value pointed to by this with the value of desired as if by p.swap(desired).
Memory is affected according to the value of order.
void operator=(shared_ptr<T> desired) noexcept;
Effects: Equivalent to store(desired).
shared_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
Requires: order shall not be memory_­order​::​release nor memory_­order​::​acq_­rel.
Effects: Memory is affected according to the value of order.
Returns: Atomically returns p.
operator shared_ptr<T>() const noexcept;
Effects: Equivalent to: return load();
shared_ptr<T> exchange(shared_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
Effects: Atomically replaces p with desired as if by p.swap(desired).
Memory is affected according to the value of order.
This is an atomic read-modify-write operation ([intro.races]).
Returns: Atomically returns the value of p immediately before the effects.
bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired, memory_order success, memory_order failure) noexcept; bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired, memory_order success, memory_order failure) noexcept;
Requires: failure shall not be memory_­order​::​release nor memory_­order​::​acq_­rel.
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.
Returns: true if p was equivalent to expected, false otherwise.
Remarks: Two shared_­ptr objects are equivalent if they store the same pointer value and either share ownership, or both are empty.
The weak form may fail spuriously.
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]) on the memory pointed to by this.
Otherwise, the operation is an atomic load operation on that memory, and expected is updated with the existing value read from the atomic object in the attempted atomic update.
The use_­count update corresponding to the write to expected is part of the atomic operation.
The write to expected itself is not required to be part of the atomic operation.
bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
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.
bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
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.11.8.2 Atomic specialization for weak_­ptr [util.smartptr.atomic.weak]

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;
    void store(weak_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
    weak_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
    operator weak_ptr<T>() const noexcept;

    weak_ptr<T> exchange(weak_ptr<T> desired,
                         memory_order order = memory_order::seq_cst) noexcept;

    bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
                               memory_order success, memory_order failure) noexcept;
    bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
                                 memory_order success, memory_order failure) noexcept;

    bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired,
                               memory_order order = memory_order::seq_cst) noexcept;
    bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired,
                                 memory_order order = memory_order::seq_cst) noexcept;

    constexpr atomic() noexcept = default;
    atomic(weak_ptr<T> desired) noexcept;
    atomic(const atomic&) = delete;
    void operator=(const atomic&) = delete;
    void operator=(weak_ptr<T> desired) noexcept;

  private:
    weak_ptr<T> p;              // exposition only
  };
}
constexpr atomic() noexcept = default;
Effects: Initializes p{}.
atomic(weak_ptr<T> desired) noexcept;
Effects: Initializes the object with the value desired.
Initialization is not an atomic operation ([intro.multithread]).
[Note
:
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.
This results in undefined behavior.
end note
]
void store(weak_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
Requires: The order argument shall not be memory_­order​::​consume, memory_­order​::​acquire, nor memory_­order​::​acq_­rel.
Effects: Atomically replaces the value pointed to by this with the value of desired as if by p.swap(desired).
Memory is affected according to the value of order.
void operator=(weak_ptr<T> desired) noexcept;
Effects: Equivalent to store(desired).
weak_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
Requires: order shall not be memory_­order​::​release nor memory_­order​::​acq_­rel.
Effects: Memory is affected according to the value of order.
Returns: Atomically returns p.
operator weak_ptr<T>() const noexcept;
Effects: Equivalent to: return load();
weak_ptr<T> exchange(weak_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
Effects: Atomically replaces p with desired as if by p.swap(desired).
Memory is affected according to the value of order.
This is an atomic read-modify-write operation ([intro.races]).
Returns: Atomically returns the value of p immediately before the effects.
bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired, memory_order success, memory_order failure) noexcept; bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired, memory_order success, memory_order failure) noexcept;
Requires: failure shall not be memory_­order​::​release nor memory_­order​::​acq_­rel.
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.
Returns: true if p was equivalent to expected, false otherwise.
Remarks: Two weak_­ptr objects are equivalent if they store the same pointer value and either share ownership, or both are empty.
The weak form may fail spuriously.
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]) on the memory pointed to by this.
Otherwise, the operation is an atomic load operation on that memory, and expected is updated with the existing value read from the atomic object in the attempted atomic update.
The use_­count update corresponding to the write to expected is part of the atomic operation.
The write to expected itself is not required to be part of the atomic operation.
bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
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.
bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
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.