Header intrusive_shared_ptr.h¶
The core smart pointer template and its std::atomic specialization.
-
template<class T, class Traits>
class intrusive_shared_ptr¶ A smart pointer that stores
T *and delegates reference-count manipulation toTraits.Note
The template is declared with
[[clang::trivial_abi]]attribute when compiled under Clang. See trivial_abi for the rationale.Traits requirements.
Traitsmust expose two static methods with the following signatures:<unspecified> add_ref(T *) noexcept <unspecified> sub_ref(T *) noexcept
The return value of either method is ignored. The argument is never
nullptr.
Member types¶
Construction, assignment, destruction¶
-
intrusive_shared_ptr() noexcept¶
-
intrusive_shared_ptr(std::nullptr_t) noexcept¶
Construct a null pointer.
-
intrusive_shared_ptr(const intrusive_shared_ptr &src) noexcept¶
-
intrusive_shared_ptr(intrusive_shared_ptr &&src) noexcept¶
Copy and move construction from the same type and traits. The move constructor performs no changes to the reference count.
-
template<class Y, class YTraits>
intrusive_shared_ptr(const intrusive_shared_ptr<Y, YTraits> &src) noexcept¶ -
template<class Y, class YTraits>
intrusive_shared_ptr(intrusive_shared_ptr<Y, YTraits> &&src) noexcept¶ Converting copy and move construction from any object of a type
Ysuch thatY *is convertible toT *, using the same or different traits. For the move, if the source and destination traits are the same, no changes to the source reference count are performed.
-
intrusive_shared_ptr &operator=(const intrusive_shared_ptr &src) noexcept¶
-
intrusive_shared_ptr &operator=(intrusive_shared_ptr &&src) noexcept¶
-
template<class Y, class YTraits>
intrusive_shared_ptr &operator=(const intrusive_shared_ptr<Y, YTraits> &src) noexcept¶ -
template<class Y, class YTraits>
intrusive_shared_ptr &operator=(intrusive_shared_ptr<Y, YTraits> &&src) noexcept¶ Copy and move assignment, with the same type/traits and converting overloads as the constructors above. As with the move constructor, a move between identical traits performs no changes to the source reference count.
-
~intrusive_shared_ptr() noexcept¶
Non-virtual destructor.
-
static intrusive_shared_ptr noref(T *p) noexcept¶
Create a smart pointer from a raw pointer without modifying the reference count (attach).
-
static intrusive_shared_ptr ref(T *p) noexcept¶
Create a smart pointer from a raw pointer and increment the reference count (retain).
Observers¶
-
T &operator*() const noexcept¶
Return a reference to the pointee. Undefined if the stored pointer is
nullptr.
-
template<class M>
M &operator->*(M T::* memptr) const noexcept¶ Return the result of
get()->*memptr, allowing access through a pointer to member of the pointee.
-
explicit operator bool() const noexcept¶
trueif the pointer is non-null.
Modifiers¶
-
T *release() noexcept¶
Release ownership of the stored pointer. The object is set to null and the caller assumes ownership; the reference count is not adjusted.
-
void reset() noexcept¶
Clear the stored pointer, decrementing the reference count.
-
void swap(intrusive_shared_ptr &other) noexcept¶
Swap with another pointer of the same type. See also the non-member
swap().
-
output_param get_output_param() noexcept¶
-
inout_param get_inout_param() noexcept¶
Return a temporary exposing
operator T**() && noexceptthat yields aT**aliasing the smart pointer’s internal storage, for passing to C functions that write back a reference-counted pointer.get_output_paramfirst resets the pointer to null. Use it for output parameters, where the callee returns a freshly counted pointer.get_inout_parampasses the current value through unchanged. Use it for in/out parameters, where the callee both reads and replaces it.
Tip
In C++23 and later, prefer
std::out_ptr/std::inout_ptr(enabled by the specializations below) over these methods.
Non-member functions¶
All of these are noexcept.
-
void swap(intrusive_shared_ptr<T, Traits> &lhs, intrusive_shared_ptr<T, Traits> &rhs) noexcept¶
Swap two pointers of the same type. Found by ADL only.
-
bool operator==(...) noexcept¶
-
bool operator!=(...) noexcept¶
Equality and inequality between
intrusive_shared_ptrof compatible types (with any traits), raw pointers, andnullptr.
-
bool operator<(...) noexcept¶
-
bool operator<=(...) noexcept¶
-
bool operator>=(...) noexcept¶
-
bool operator>(...) noexcept¶
Ordering between
intrusive_shared_ptrof compatible types (with any traits) and raw pointers. On C++20 these are replaced by a singleoperator<=>.
-
size_t hash_value(const intrusive_shared_ptr<T, Traits> &ptr) noexcept¶
Hash of the stored pointer value (e.g. for Boost.Hash).
-
template<class Char>
std::basic_ostream<Char> &operator<<(std::basic_ostream<Char> &str, const intrusive_shared_ptr<T, Traits> &ptr)¶ Write the stored pointer value to a stream. Found by ADL only.
-
template<class Dest>
Dest intrusive_const_cast(intrusive_shared_ptr src) noexcept¶ -
template<class Dest>
Dest intrusive_static_cast(intrusive_shared_ptr src) noexcept¶ -
template<class Dest>
Dest intrusive_dynamic_cast(intrusive_shared_ptr src) noexcept¶ Perform the equivalent of
const_cast/static_cast/dynamic_caston the argument.Destmust be a validintrusive_shared_ptrtype whose underlying type is convertible from the source’s via the corresponding cast.intrusive_dynamic_castreturns a null result if the underlyingdynamic_castfails.
Specializations¶
-
template<class T, class Traits>
struct std::out_ptr_t<intrusive_shared_ptr<T, Traits>, T*>¶
-
template<class T, class Traits>
struct std::inout_ptr_t<intrusive_shared_ptr<T, Traits>, T*>¶ Enable
std::out_ptr/std::inout_ptrwithintrusive_shared_ptr. Provided when the standard library offers<out_ptr>support.
-
template<class T, class Traits, class CharT>
struct std::formatter<intrusive_shared_ptr<T, Traits>, CharT>¶ Enable
std::formatwithintrusive_shared_ptr. Provided when the standard library offersstd::formatsupport.
-
template<class T, class Traits>
struct std::hash<intrusive_shared_ptr<T, Traits>>¶ Enable use as a key in unordered associative containers.
-
template<class Traits, class T>
class std::atomic<intrusive_shared_ptr<T, Traits>>¶ Provides the standard
std::atomicinterface forintrusive_shared_ptr. It is not lock-free: operations are serialized with an internal lock.-
using value_type = isptr::intrusive_shared_ptr<T, Traits>¶
The pointer type being wrapped.
-
static constexpr bool is_always_lock_free¶
Always
false.
Construction / assignment
-
constexpr atomic() noexcept¶
Initialize with a null pointer.
-
atomic(value_type desired) noexcept¶
Initialize holding
desired.
-
~atomic() noexcept¶
Releases the held pointer.
-
value_type operator=(value_type desired) noexcept¶
Same as
store().
-
operator value_type() const noexcept¶
Same as
load().
Atomic operations
Each behaves like the matching
std::atomicmember.-
value_type load(std::memory_order order = std::memory_order_seq_cst) const noexcept¶
Read the stored pointer.
-
void store(value_type desired, std::memory_order order = std::memory_order_seq_cst) noexcept¶
Replace the stored pointer.
-
value_type exchange(value_type desired, std::memory_order order = std::memory_order_seq_cst) noexcept¶
Replace the stored pointer and return the previous value.
-
bool compare_exchange_strong(value_type &expected, value_type desired, std::memory_order success, std::memory_order failure) noexcept¶
-
bool compare_exchange_strong(value_type &expected, value_type desired, std::memory_order order = std::memory_order_seq_cst) noexcept¶
Compare and swap.
-
bool compare_exchange_weak(value_type &expected, value_type desired, std::memory_order success, std::memory_order failure) noexcept¶
-
bool compare_exchange_weak(value_type &expected, value_type desired, std::memory_order order = std::memory_order_seq_cst) noexcept¶
Compare and swap. May fail spuriously.
-
bool is_lock_free() const noexcept¶
Always
false.
-
using value_type = isptr::intrusive_shared_ptr<T, Traits>¶