#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;
}
T
andD
shall be complete types.intrusive_base<T, D>
shall be a public, non-ambiguous base ofT
.D
shall satisfy the requirements of DefaultConstructible. None of the default constructor, the copy/move constructor, the copy/move assignment operator ofD
shall throw exceptions.
- Post-condition:
use_count() == 1
.
- Effects:
intrusive_base()
.
- Effects: No operation.
- Returns:
*this
.
- Effects: If
use_count() > 1
callsterminate()
.
- Returns: A reference to the stored deleter.
- Returns:
use_count() == 1
.
- Returns: The reference count of this object.
- Returns: The weak reference count of this object.
- Effects: Satisifies any allocation requests for resources that would be required if an
intrusive_weak_ptr
was to be constructed. Construction ofintrusive_weak_ptr
referring 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;
- Effects: Let
pu
be the result of conversion fromthis
to typecv U *
. Ifpu
is not null, increments the reference count ofpu
. - Returns:
intrusive_ptr<cv U>(pu)
. - Post-condition: If
pu
is not null,use_count()
is one greater than the value before the call.
- 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.
T
shall be a complete type.- Let
intrusive_base<T, D>
be a public, non-ambiguous base ofT
.deleter_type
is the template parameterD
. If no such base can be found, the program is ill-formed.
- Post-condition:
get() == nullptr
anduse_count() == 0
andweak_count() == 0
.
- Effects: If
rhs
is not null, increments the reference count of*rhs
. - Post-condition:
get() == rhs
. Ifrhs
is not null,rhs->use_count()
is one greater than the value before the call.
- Remarks: This constructor shall not participate in overload resolution unless
U *
is implicitly convertible toT *
andE
is implicitly convertible toD
. - Effects:
intrusive_ptr(rhs.release())
.
- Remarks: This constructor shall not participate in overload resolution unless
U *
is implicitly convertible toT *
. - Effects: If
rhs
is 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.
- 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
.
- Effects:
intrusive_ptr(rhs.get())
- Effects:
intrusive_ptr(rhs.release())
- Effects:
intrusive_ptr(rhs).swap(*this)
.
- Effects:
reset()
followed byrhs.swap(*this)
.
-
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());
- Returns: The stored pointer.
- Effects: Sets the stored pointer to
nullptr
without deleting any objects. - Returns: The value of
get()
before the call. - Post-condition:
get() == nullptr
.
- Returns: If
get()
is null,0
. Otherwise,get()->intrusive_base<T, D>::use_count()
.
- Returns: If
get()
is null,0
. Otherwise,get()->intrusive_base<T, D>::weak_count()
.
- Effects:
intrusive_ptr().swap(*this)
.
- Effects:
intrusive_ptr(rhs).swap(*this)
.
- 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.
- Returns:
get() != nullptr
.
- Pre-condition:
get()
shall not be null. - Returns:
*get()
.
- 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() == rhs
andlhs == 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() != rhs
andlhs != 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() < rhs
andlhs < 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() > rhs
andlhs > 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() <= rhs
andlhs <= 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() >= rhs
andlhs >= rhs.get()
, respectively.
- Effects:
lhs.swap(rhs)
.
- 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
u
be 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
u
be the result ofdynamic_cast<U *>(src.get())
. Ifu
is 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
u
be the result ofconst_cast<U *>(src.get())
. Callssrc.release()
. - Returns:
intrusive_ptr<U>(u)
.
T
shall be a complete type.- Let
intrusive_base<T, D>
be a public, non-ambiguous base ofT
.deleter_type
is the template parameterD
. If no such base can be found, the program is ill-formed.
- Post-condition:
expired()
andweak_count() == 0
.
- Effects: If
rhs
is 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
. Ifrhs
is not null,rhs->weak_count()
is one greater than the value before the call.
- Effects:
intrusive_weak_ptr(rhs.get())
.
- 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.
- 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
.
- Effects:
intrusive_weak_ptr(rhs.lock().get())
, as if the object referred byrhs
had never expired, if any.
- Effects:
intrusive_weak_ptr(rhs.lock().get())
thenrhs.reset()
, as if the object referred byrhs
had never expired, if any.
- Effects:
intrusive_weak_ptr(rhs).swap(*this)
.
- Effects:
reset()
followed byrhs.swap(*this)
.
- Effects: Let
pt
be a pointer to the object that*this
is referring as if that object had never expired, or a null pointer if no such object exists. Ifpt
is not null, decrements the weak reference count of*pt
.
- Effects: Let
pt
be a pointer to the object that*this
is referring as if that object had never expired, or a null pointer if no such object exists. - Returns: If
pt
is null,true
. Otherwise,pt->use_count() > 0
.
- Effects: Let
pt
be a pointer to the object that*this
is referring as if that object had never expired, or a null pointer if no such object exists. - Returns: If
pt
is null,0
. Otherwise,pt->weak_count()
.
- Effects: Atomically executes: Let
pt
be a pointer to the object that*this
is referring as if that object had never expired, or a null pointer if no such object exists. Letpu
be the result of conversion frompu
to typeU *
. Ifpu
is not null, increments the reference count ofpu
. - Returns:
intrusive_ptr<U>(pu)
. - Post-condition: If
pu
is not null,use_count()
is one greater thanpt->intrusive_base<T, D>::use_count()
before the call.
- Effects:
intrusive_weak_ptr().swap(*this)
.
- Effects:
intrusive_weak_ptr(rhs).swap(*this)
.
- 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_ptr
in associative containers.
- Effects:
lhs.swap(rhs)
.