intrusive_ptr
intrusive_ptr copied to clipboard
Proposal for std::intrusive_ptr
Proposal for std::intrusive_ptr
Synopsis
#include <memory>
namespace std {
template<typename T, typename D = default_delete<T>>
class intrusive_base;
template<typename T>
class intrusive_ptr;
template<typename T>
class intrusive_weak_ptr;
template<typename T, class D>
class intrusive_base {
public:
constexpr intrusive_base() noexcept;
constexpr intrusive_base(const intrusive_base & rhs) noexcept;
intrusive_base & operator=(const intrusive_base & rhs) noexcept;
~intrusive_base();
public:
const deleter_type & get_deleter() const noexcept;
deleter_type & get_deleter() noexcept;
bool unique() const volatile noexcept;
long use_count() const volatile noexcept;
long weak_count() const noexcept;
void reserve_weak() const volatile;
template<typename U = T> intrusive_ptr<const volatile U> shared_from_this() const volatile noexcept;
template<typename U = T> intrusive_ptr<const U> shared_from_this() const noexcept;
template<typename U = T> intrusive_ptr<volatile U> shared_from_this() volatile noexcept;
template<typename U = T> intrusive_ptr<U> shared_from_this() noexcept;
template<typename U = T> intrusive_weak_ptr<const volatile U> weak_from_this() const volatile;
template<typename U = T> intrusive_weak_ptr<const U> weak_from_this() const;
template<typename U = T> intrusive_weak_ptr<volatile U> weak_from_this() volatile;
template<typename U = T> intrusive_weak_ptr<U> weak_from_this();
};
template<typename T>
class intrusive_ptr {
public:
using pointer = T *;
using element_type = T;
using deleter_type = /* see below */;
constexpr intrusive_ptr(nullptr_t = nullptr) noexcept;
explicit constexpr intrusive_ptr(element_type * rhs) noexcept;
template<typename U, typename E> intrusive_ptr(unique_ptr<U, E> && rhs) noexcept;
template<typename U> intrusive_ptr(const intrusive_ptr<U> & rhs) noexcept;
template<typename U> intrusive_ptr(intrusive_ptr<U> && rhs) noexcept;
intrusive_ptr(const intrusive_ptr & rhs) noexcept;
intrusive_ptr(intrusive_ptr && rhs) noexcept;
intrusive_ptr & operator=(const intrusive_ptr & rhs) noexcept;
intrusive_ptr & operator=(intrusive_ptr && rhs) noexcept;
~intrusive_ptr();
element_type * get() const noexcept;
element_type * release() noexcept;
long use_count() const noexcept;
long weak_count() const noexcept;
void reset(nullptr_t = nullptr) noexcept;
void reset(element_type * rhs) noexcept;
void swap(intrusive_ptr & rhs) noexcept;
explicit constexpr operator bool() const noexcept;
element_type & operator*() const;
element_type * operator->() const;
};
template<typename T1, typename T2> bool operator==(const intrusive_ptr<T1> & lhs, const intrusive_ptr<T2> & rhs) noexcept;
template<typename T1, typename T2> bool operator==(const intrusive_ptr<T1> & lhs, T2 * rhs) noexcept;
template<typename T1, typename T2> bool operator==(T1 * lhs, const intrusive_ptr<T2> & rhs) noexcept;
template<typename T1, typename T2> bool operator!=(const intrusive_ptr<T1> & lhs, const intrusive_ptr<T2> & rhs) noexcept;
template<typename T1, typename T2> bool operator!=(const intrusive_ptr<T1> & lhs, T2 * rhs) noexcept;
template<typename T1, typename T2> bool operator!=(T1 * lhs, const intrusive_ptr<T2> & rhs) noexcept;
template<typename T1, typename T2> bool operator< (const intrusive_ptr<T1> & lhs, const intrusive_ptr<T2> & rhs) noexcept;
template<typename T1, typename T2> bool operator< (const intrusive_ptr<T1> & lhs, T2 * rhs) noexcept;
template<typename T1, typename T2> bool operator< (T1 * lhs, const intrusive_ptr<T2> & rhs) noexcept;
template<typename T1, typename T2> bool operator> (const intrusive_ptr<T1> & lhs, const intrusive_ptr<T2> & rhs) noexcept;
template<typename T1, typename T2> bool operator> (const intrusive_ptr<T1> & lhs, T2 * rhs) noexcept;
template<typename T1, typename T2> bool operator> (T1 * lhs, const intrusive_ptr<T2> & rhs) noexcept;
template<typename T1, typename T2> bool operator<=(const intrusive_ptr<T1> & lhs, const intrusive_ptr<T2> & rhs) noexcept;
template<typename T1, typename T2> bool operator<=(const intrusive_ptr<T1> & lhs, T2 * rhs) noexcept;
template<typename T1, typename T2> bool operator<=(T1 * lhs, const intrusive_ptr<T2> & rhs) noexcept;
template<typename T1, typename T2> bool operator>=(const intrusive_ptr<T1> & lhs, const intrusive_ptr<T2> & rhs) noexcept;
template<typename T1, typename T2> bool operator>=(const intrusive_ptr<T1> & lhs, T2 * rhs) noexcept;
template<typename T1, typename T2> bool operator>=(T1 * lhs, const intrusive_ptr<T2> & rhs) noexcept;
template<typename T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs) noexcept;
template<typename T, typename ... Args> intrusive_ptr<T> make_intrusive(Args &&... args);
template<typename U, typename T> intrusive_ptr<U> static_pointer_cast(intrusive_ptr<T> src) noexcept;
template<typename U, typename T> intrusive_ptr<U> dynamic_pointer_cast(intrusive_ptr<T> src) noexcept;
template<typename U, typename T> intrusive_ptr<U> const_pointer_cast(intrusive_ptr<T> src) noexcept;
template<typename T>
class intrusive_weak_ptr {
public:
using pointer = typename intrusive_ptr<T>::pointer;
using element_type = typename intrusive_ptr<T>::element_type;
using deleter_type = typename intrusive_ptr<T>::deleter_type;
constexpr intrusive_weak_ptr(nullptr_t = nullptr) noexcept;
explicit intrusive_weak_ptr(element_type * rhs);
intrusive_weak_ptr(const intrusive_ptr<T> & rhs);
template<typename U> intrusive_weak_ptr(const intrusive_weak_ptr<U> & rhs) noexcept;
template<typename U> intrusive_weak_ptr(intrusive_weak_ptr<U> && rhs) noexcept;
intrusive_weak_ptr(const intrusive_weak_ptr & rhs) noexcept;
intrusive_weak_ptr(intrusive_weak_ptr && rhs) noexcept;
intrusive_weak_ptr & operator=(const intrusive_weak_ptr & rhs) noexcept;
intrusive_weak_ptr & operator=(intrusive_weak_ptr && rhs) noexcept;
~intrusive_weak_ptr();
bool expired() const noexcept;
long weak_count() const noexcept;
template<typename U = T> intrusive_ptr<U> lock() const noexcept;
void reset(nullptr_t = nullptr) noexcept;
void reset(element_type * rhs);
void swap(intrusive_weak_ptr & rhs) noexcept;
};
template<typename T> bool operator==(const intrusive_weak_ptr<T> & lhs, const intrusive_weak_ptr<T> & rhs) const noexcept;
template<typename T> bool operator!=(const intrusive_weak_ptr<T> & lhs, const intrusive_weak_ptr<T> & rhs) const noexcept;
template<typename T> bool operator< (const intrusive_weak_ptr<T> & lhs, const intrusive_weak_ptr<T> & rhs) const noexcept;
template<typename T> bool operator> (const intrusive_weak_ptr<T> & lhs, const intrusive_weak_ptr<T> & rhs) const noexcept;
template<typename T> bool operator<=(const intrusive_weak_ptr<T> & lhs, const intrusive_weak_ptr<T> & rhs) const noexcept;
template<typename T> bool operator>=(const intrusive_weak_ptr<T> & lhs, const intrusive_weak_ptr<T> & rhs) const noexcept;
template<typename T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs) noexcept;
}
template<typename T, class D> class intrusive_base
In general
TandDshall be complete types.intrusive_base<T, D>shall be a public, non-ambiguous base ofT.Dshall satisfy the requirements of DefaultConstructible. None of the default constructor, the copy/move constructor, the copy/move assignment operator ofDshall throw exceptions.
constexpr intrusive_base() noexcept;
- Post-condition:
use_count() == 1.
constexpr intrusive_base(const intrusive_base & rhs) noexcept;
- Effects:
intrusive_base().
intrusive_base & operator=(const intrusive_base & rhs) noexcept;
- Effects: No operation.
- Returns:
*this.
~intrusive_base();
- Effects: If
use_count() > 1callsterminate().
const deleter_type & get_deleter() const noexcept;
deleter_type & get_deleter() noexcept;
- Returns: A reference to the stored deleter.
bool unique() const volatile noexcept;
- Returns:
use_count() == 1.
long use_count() const volatile noexcept;
- Returns: The reference count of this object.
long weak_count() const volatile noexcept;
- Returns: The weak reference count of this object.
void reserve_weak() const volatile;
- Effects: Satisifies any allocation requests for resources that would be required if an
intrusive_weak_ptrwas to be constructed. Construction ofintrusive_weak_ptrreferring this object shall not throw any exceptions hereafter. - Throws:
bad_alloc, or an implementation-defined exception when a resource other than memory could not be obtained.
template<typename U = T> intrusive_ptr<const volatile U> shared_from_this() const volatile noexcept;
template<typename U = T> intrusive_ptr<const U> shared_from_this() const noexcept;
template<typename U = T> intrusive_ptr<volatile U> shared_from_this() volatile noexcept;
template<typename U = T> intrusive_ptr<U> shared_from_this() noexcept;
- Effects: Let
pube the result of conversion fromthisto typecv U *. Ifpuis not null, increments the reference count ofpu. - Returns:
intrusive_ptr<cv U>(pu). - Post-condition: If
puis not null,use_count()is one greater than the value before the call.
template<typename U = T> intrusive_weak_ptr<const volatile U> weak_from_this() const volatile;
template<typename U = T> intrusive_weak_ptr<const U> weak_from_this() const;
template<typename U = T> intrusive_weak_ptr<volatile U> weak_from_this() volatile;
template<typename U = T> intrusive_weak_ptr<U> weak_from_this();
- Returns:
intrusive_weak_ptr<cv U>(shared_from_this()), as ifshared_from_this()had never returned a null pointer. - Throws: Any exceptions that might be thrown by
reserve_weak(). - Post-condition:
weak_count()is one greater than the value before the call.
template<typename T> class intrusive_ptr
In general
Tshall be a complete type.- Let
intrusive_base<T, D>be a public, non-ambiguous base ofT.deleter_typeis the template parameterD. If no such base can be found, the program is ill-formed.
constexpr intrusive_ptr(nullptr_t = nullptr) noexcept;
- Post-condition:
get() == nullptranduse_count() == 0andweak_count() == 0.
explicit constexpr intrusive_ptr(element_type * rhs) noexcept;
- Effects: If
rhsis not null, increments the reference count of*rhs. - Post-condition:
get() == rhs. Ifrhsis not null,rhs->use_count()is one greater than the value before the call.
template<typename U, typename E> intrusive_ptr(unique_ptr<U, E> && rhs) noexcept;
- Remarks: This constructor shall not participate in overload resolution unless
U *is implicitly convertible toT *andEis implicitly convertible toD. - Effects:
intrusive_ptr(rhs.release()).
template<typename U> intrusive_ptr(const intrusive_ptr<U> & rhs) noexcept;
- Remarks: This constructor shall not participate in overload resolution unless
U *is implicitly convertible toT *. - Effects: If
rhsis not null, increments the reference count of*rhs. - Post-condition:
get() == rhs.get()anduse_count() == rhs.use_count(). Ifrhs.use_count()is greater than zero before the call,use_count()is one greater than that value.
template<typename U> intrusive_ptr(intrusive_ptr<U> && rhs) noexcept;
- Remarks: This constructor shall not participate in overload resolution unless
U *is implicitly convertible toT *. - Post-condition:
get()equals the value ofrhs.get()before the call andrhs.get() == nullptr.use_count()equals the value ofrhs.use_count()before the call andrhs.use_count() == 0.
intrusive_ptr(const intrusive_ptr & rhs) noexcept;
- Effects:
intrusive_ptr(rhs.get())
intrusive_ptr(intrusive_ptr && rhs) noexcept;
- Effects:
intrusive_ptr(rhs.release())
intrusive_ptr & operator=(const intrusive_ptr & rhs) noexcept;
- Effects:
intrusive_ptr(rhs).swap(*this).
intrusive_ptr & operator=(intrusive_ptr && rhs) noexcept;
- Effects:
reset()followed byrhs.swap(*this).
~intrusive_ptr();
-
Effects: If
get()is not null, decrements the reference count of*get(), and if the result is zero, deletes the object as follows:using base = intrusive_base<T, D>; auto d = move(get()->base::get_deleter()); move(d)(get());
element_type * get() const noexcept;
- Returns: The stored pointer.
element_type * release() noexcept;
- Effects: Sets the stored pointer to
nullptrwithout deleting any objects. - Returns: The value of
get()before the call. - Post-condition:
get() == nullptr.
long use_count() const noexcept;
- Returns: If
get()is null,0. Otherwise,get()->intrusive_base<T, D>::use_count().
long weak_count() const noexcept;
- Returns: If
get()is null,0. Otherwise,get()->intrusive_base<T, D>::weak_count().
void reset(nullptr_t = nullptr) noexcept;
- Effects:
intrusive_ptr().swap(*this).
void reset(element_type * rhs) noexcept;
- Effects:
intrusive_ptr(rhs).swap(*this).
void swap(intrusive_ptr & rhs) noexcept;
- Post-condition:
get()equals the value ofrhs.get()before the call andrhs.get()equals the value ofget()before the call.use_count()equals the value ofrhs.use_count()before the call andrhs.use_count()equals the value ofuse_count()before the call.
explicit constexpr operator bool() const noexcept;
- Returns:
get() != nullptr.
element_type & operator*() const;
- Pre-condition:
get()shall not be null. - Returns:
*get().
element_type * operator->() const;
- Pre-condition:
get()shall not be null. - Returns:
get().
template<typename T1, typename T2> bool operator==(const intrusive_ptr<T1> & lhs, const intrusive_ptr<T2> & rhs) noexcept;
template<typename T1, typename T2> bool operator==(const intrusive_ptr<T1> & lhs, T2 * rhs) noexcept;
template<typename T1, typename T2> bool operator==(T1 * lhs, const intrusive_ptr<T2> & rhs) noexcept;
- Returns:
lhs.get() == rhs.get(),lhs.get() == rhsandlhs == rhs.get(), respectively.
template<typename T1, typename T2> bool operator!=(const intrusive_ptr<T1> & lhs, const intrusive_ptr<T2> & rhs) noexcept;
template<typename T1, typename T2> bool operator!=(const intrusive_ptr<T1> & lhs, T2 * rhs) noexcept;
template<typename T1, typename T2> bool operator!=(T1 * lhs, const intrusive_ptr<T2> & rhs) noexcept;
- Returns:
lhs.get() != rhs.get(),lhs.get() != rhsandlhs != rhs.get(), respectively.
template<typename T1, typename T2> bool operator<(const intrusive_ptr<T1> & lhs, const intrusive_ptr<T2> & rhs) noexcept;
template<typename T1, typename T2> bool operator<(const intrusive_ptr<T1> & lhs, T2 * rhs) noexcept;
template<typename T1, typename T2> bool operator<(T1 * lhs, const intrusive_ptr<T2> & rhs) noexcept;
- Returns:
lhs.get() < rhs.get(),lhs.get() < rhsandlhs < rhs.get(), respectively.
template<typename T1, typename T2> bool operator>(const intrusive_ptr<T1> & lhs, const intrusive_ptr<T2> & rhs) noexcept;
template<typename T1, typename T2> bool operator>(const intrusive_ptr<T1> & lhs, T2 * rhs) noexcept;
template<typename T1, typename T2> bool operator>(T1 * lhs, const intrusive_ptr<T2> & rhs) noexcept;
- Returns:
lhs.get() > rhs.get(),lhs.get() > rhsandlhs > rhs.get(), respectively.
template<typename T1, typename T2> bool operator<=(const intrusive_ptr<T1> & lhs, const intrusive_ptr<T2> & rhs) noexcept;
template<typename T1, typename T2> bool operator<=(const intrusive_ptr<T1> & lhs, T2 * rhs) noexcept;
template<typename T1, typename T2> bool operator<=(T1 * lhs, const intrusive_ptr<T2> & rhs) noexcept;
- Returns:
lhs.get() <= rhs.get(),lhs.get() <= rhsandlhs <= rhs.get(), respectively.
template<typename T1, typename T2> bool operator>=(const intrusive_ptr<T1> & lhs, const intrusive_ptr<T2> & rhs) noexcept;
template<typename T1, typename T2> bool operator>=(const intrusive_ptr<T1> & lhs, T2 * rhs) noexcept;
template<typename T1, typename T2> bool operator>=(T1 * lhs, const intrusive_ptr<T2> & rhs) noexcept;
- Returns:
lhs.get() >= rhs.get(),lhs.get() >= rhsandlhs >= rhs.get(), respectively.
template<typename T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs) noexcept;
- Effects:
lhs.swap(rhs).
template<typename T, typename ... Args> intrusive_ptr<T> make_intrusive(Args &&... args);
- Returns:
intrusive_ptr<T>(new T(forward<Args>(args)...)).
template<typename U, typename T> intrusive_ptr<U> static_pointer_cast(intrusive_ptr<T> src) noexcept;
- Effects: Let
ube the result ofstatic_cast<U *>(src.get()). Callssrc.release(). - Returns:
intrusive_ptr<U>(u).
template<typename U, typename T> intrusive_ptr<U> dynamic_pointer_cast(intrusive_ptr<T> src) noexcept;
- Effects: Let
ube the result ofdynamic_cast<U *>(src.get()). Ifuis not null, callssrc.release(). - Returns:
intrusive_ptr<U>(u).
template<typename U, typename T> intrusive_ptr<U> const_pointer_cast(intrusive_ptr<T> src) noexcept;
- Effects: Let
ube the result ofconst_cast<U *>(src.get()). Callssrc.release(). - Returns:
intrusive_ptr<U>(u).
template<typename T> class intrusive_weak_ptr
In general
Tshall be a complete type.- Let
intrusive_base<T, D>be a public, non-ambiguous base ofT.deleter_typeis the template parameterD. If no such base can be found, the program is ill-formed.
constexpr intrusive_weak_ptr(nullptr_t = nullptr) noexcept;
- Post-condition:
expired()andweak_count() == 0.
explicit intrusive_weak_ptr(element_type * rhs);
- Effects: If
rhsis not null, increments the weak reference count of*rhs. - Throws: Any exceptions that might be thrown by
rhs->reserve_weak(). - Post-condition:
lock().get() == rhs. Ifrhsis not null,rhs->weak_count()is one greater than the value before the call.
intrusive_weak_ptr(const intrusive_ptr<T> & rhs);
- Effects:
intrusive_weak_ptr(rhs.get()).
template<typename U> intrusive_weak_ptr(const intrusive_weak_ptr<U> & rhs) noexcept;
- Remarks: This constructor shall not participate in overload resolution unless
U *is implicitly convertible toT *. - Effects: If
rhs.weak_count()is greater than zero, increments the weak reference count of the object refered byrhs, as if it had never expired. - Post-condition:
weak_count() == rhs.weak_count(). Ifrhs.weak_count()is greater than zero before the call,weak_count()is one greater than that value.
template<typename U> intrusive_weak_ptr(intrusive_weak_ptr<U> && rhs) noexcept;
- Remarks: This constructor shall not participate in overload resolution unless
U *is implicitly convertible toT *. - Post-condition:
weak_count()equals the value ofrhs.weak_count()before the call andrhs.weak_count() == 0.
intrusive_weak_ptr(const intrusive_weak_ptr & rhs) noexcept;
- Effects:
intrusive_weak_ptr(rhs.lock().get()), as if the object referred byrhshad never expired, if any.
intrusive_weak_ptr(intrusive_weak_ptr && rhs) noexcept;
- Effects:
intrusive_weak_ptr(rhs.lock().get())thenrhs.reset(), as if the object referred byrhshad never expired, if any.
intrusive_weak_ptr & operator=(const intrusive_weak_ptr & rhs) noexcept;
- Effects:
intrusive_weak_ptr(rhs).swap(*this).
intrusive_weak_ptr & operator=(intrusive_weak_ptr && rhs) noexcept;
- Effects:
reset()followed byrhs.swap(*this).
~intrusive_weak_ptr();
- Effects: Let
ptbe a pointer to the object that*thisis referring as if that object had never expired, or a null pointer if no such object exists. Ifptis not null, decrements the weak reference count of*pt.
bool expired() const noexcept;
- Effects: Let
ptbe a pointer to the object that*thisis referring as if that object had never expired, or a null pointer if no such object exists. - Returns: If
ptis null,true. Otherwise,pt->use_count() > 0.
long weak_count() const noexcept;
- Effects: Let
ptbe a pointer to the object that*thisis referring as if that object had never expired, or a null pointer if no such object exists. - Returns: If
ptis null,0. Otherwise,pt->weak_count().
template<typename U = T> intrusive_ptr<U> lock() const noexcept;
- Effects: Atomically executes: Let
ptbe a pointer to the object that*thisis referring as if that object had never expired, or a null pointer if no such object exists. Letpube the result of conversion fromputo typeU *. Ifpuis not null, increments the reference count ofpu. - Returns:
intrusive_ptr<U>(pu). - Post-condition: If
puis not null,use_count()is one greater thanpt->intrusive_base<T, D>::use_count()before the call.
void reset(nullptr_t = nullptr) noexcept;
- Effects:
intrusive_weak_ptr().swap(*this).
void reset(element_type * rhs);
- Effects:
intrusive_weak_ptr(rhs).swap(*this).
void swap(intrusive_weak_ptr & rhs) noexcept;
- Post-condition:
lock()equals the value ofrhs.lock()before the call andrhs.lock()equals the value oflock()before the call.weak_count()equals the value ofrhs.weak_count()before the call andrhs.weak_count()equals the value ofweak_count()before the call.
template<typename T> bool operator==(const intrusive_weak_ptr<T> & lhs, const intrusive_weak_ptr<T> & rhs) const noexcept;
template<typename T> bool operator!=(const intrusive_weak_ptr<T> & lhs, const intrusive_weak_ptr<T> & rhs) const noexcept;
template<typename T> bool operator< (const intrusive_weak_ptr<T> & lhs, const intrusive_weak_ptr<T> & rhs) const noexcept;
template<typename T> bool operator> (const intrusive_weak_ptr<T> & lhs, const intrusive_weak_ptr<T> & rhs) const noexcept;
template<typename T> bool operator<=(const intrusive_weak_ptr<T> & lhs, const intrusive_weak_ptr<T> & rhs) const noexcept;
template<typename T> bool operator>=(const intrusive_weak_ptr<T> & lhs, const intrusive_weak_ptr<T> & rhs) const noexcept;
- Remarks: These functions define an otherwise unspecified strick weak ordering of
intrusive_weak_ptr, enabling use ofintrusive_weak_ptrin associative containers.
template<typename T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs) noexcept;
- Effects:
lhs.swap(rhs).