20 General utilities library [utilities]

20.7 Smart pointers [smartptr]

20.7.2 Shared-ownership pointers [util.smartptr]

20.7.2.3 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:
    typedef T element_type;

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

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

    // [util.smartptr.weak.assign], assignment
    weak_ptr& operator=(weak_ptr const& r) noexcept;
    template<class Y> weak_ptr& operator=(weak_ptr<Y> const& r) noexcept;
    template<class Y> weak_ptr& operator=(shared_ptr<Y> const& 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(shared_ptr<U> const& b);
    template<class U> bool owner_before(weak_ptr<U> const& b);
  };

  // [util.smartptr.weak.spec], specialized algorithms
  template<class T> void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept;
} // namespace std

Specializations of weak_ptr shall be CopyConstructible and CopyAssignable, allowing their use in standard containers. The template parameter T of weak_ptr may be an incomplete type.

20.7.2.3.1 weak_ptr constructors [util.smartptr.weak.const]

constexpr weak_ptr() noexcept;

Effects: Constructs an empty weak_ptr object.

Postconditions: 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;

Requires: The second and third constructors shall not participate in the overload resolution unless Y* is implicitly convertible to 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.

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

20.7.2.3.2 weak_ptr 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.

20.7.2.3.3 weak_ptr 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.

20.7.2.3.4 weak_ptr 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).

20.7.2.3.5 weak_ptr 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.

Note: use_count() is not necessarily efficient. — end note ]

bool expired() const noexcept;

Returns: use_count() == 0.

Note: expired() may be faster than use_count().  — end note ]

shared_ptr<T> lock() const noexcept;

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

template<class U> bool owner_before(shared_ptr<U> const& b); template<class U> bool owner_before(weak_ptr<U> const& b);

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.

20.7.2.3.6 weak_ptr 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).

20.7.2.3.7 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> struct owner_less;

  template<class T> struct owner_less<shared_ptr<T> > {
    typedef bool result_type;
    typedef shared_ptr<T> first_argument_type;
    typedef shared_ptr<T> second_argument_type;
    bool operator()(shared_ptr<T> const&, shared_ptr<T> const&) const;
    bool operator()(shared_ptr<T> const&, weak_ptr<T> const&) const;
    bool operator()(weak_ptr<T> const&, shared_ptr<T> const&) const;
  };

  template<class T> struct owner_less<weak_ptr<T> > {
    typedef bool result_type;
    typedef weak_ptr<T> first_argument_type;
    typedef weak_ptr<T> second_argument_type;
    bool operator()(weak_ptr<T> const&, weak_ptr<T> const&) const;
    bool operator()(shared_ptr<T> const&, weak_ptr<T> const&) const;
    bool operator()(weak_ptr<T> const&, shared_ptr<T> const&) const;
  };
}

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.