1#ifndef LIBSBX_MEMORY_OBSERVER_PTR_HPP_
2#define LIBSBX_MEMORY_OBSERVER_PTR_HPP_
7#include <libsbx/utility/assert.hpp>
11template<
typename Type,
typename Value>
12concept smart_pointer =
requires(Type t, Value v) {
13 { Type::value_type} -> std::same_as<Value>;
14 { t.get() } -> std::same_as<Value>;
26template<
typename Type>
31 using value_type = Type;
32 using pointer = value_type*;
33 using const_pointer =
const value_type*;
43 template<smart_po
inter<value_type> Po
inter>
45 : _value{value.get()} { }
47 template<
typename Other>
48 requires (std::is_convertible_v<Other*, pointer>)
50 : _value{
reinterpret_cast<pointer
>(other.get())} { }
62 constexpr auto operator=(std::nullptr_t)
noexcept ->
observer_ptr& {
67 constexpr auto operator=(pointer value)
noexcept ->
observer_ptr& {
72 constexpr auto release()
noexcept -> pointer {
78 constexpr auto reset(pointer value =
nullptr)
noexcept ->
void {
82 constexpr auto swap(
observer_ptr& other)
noexcept ->
void {
83 std::swap(_value, other._value);
86 constexpr auto is_valid()
const noexcept ->
bool {
87 return _value !=
nullptr;
90 constexpr operator bool()
const noexcept {
94 constexpr auto operator->()
const noexcept -> const_pointer {
95 utility::assert_that(is_valid(),
"Cannot dereference a null pointer.");
99 constexpr auto operator->()
noexcept -> pointer {
100 utility::assert_that(is_valid(),
"Cannot dereference a null pointer.");
104 constexpr auto operator*()
const noexcept(
noexcept(*std::declval<pointer>())) -> std::add_const_t<std::add_lvalue_reference_t<value_type>> {
105 utility::assert_that(is_valid(),
"Cannot dereference a null pointer.");
109 constexpr auto operator*()
noexcept(
noexcept(*std::declval<pointer>())) -> std::add_lvalue_reference_t<value_type> {
110 utility::assert_that(is_valid(),
"Cannot dereference a null pointer.");
114 constexpr auto get()
const noexcept -> const_pointer {
118 constexpr auto get()
noexcept -> pointer {
138template<
typename Type>
140 return lhs.get() == rhs.get();
143template<
typename Type, smart_po
inter<Type> Po
inter>
144constexpr auto operator==(
const observer_ptr<Type>& lhs,
const Pointer& rhs)
noexcept ->
bool {
145 return lhs.get() == rhs.get();
157template<
typename Type>
158constexpr auto make_observer(Type* value)
noexcept -> observer_ptr<Type> {
159 return observer_ptr<Type>{value};
162template<
typename Type>
163constexpr auto make_observer(Type& value)
noexcept -> observer_ptr<Type> {
164 return observer_ptr<Type>{std::addressof(value)};
167template<
typename Type, smart_po
inter<Type> Po
inter>
168constexpr auto make_observer(Pointer& value)
noexcept -> observer_ptr<Type> {
169 return observer_ptr<Type>{value.get()};
174template<
typename Type>
175struct std::hash<sbx::memory::observer_ptr<Type>> {
177 return std::hash<Type*>{}(value.get());
A non-owning pointer that can be used to observe the value of a pointer.
Definition: observer_ptr.hpp:27