Iros
 
Loading...
Searching...
No Matches
box.h
Go to the documentation of this file.
1#pragma once
2
7#include "di/meta/language.h"
9#include "di/types/prelude.h"
10#include "di/util/exchange.h"
11#include "di/util/std_new.h"
14
15namespace di::vocab {
16template<typename T>
18 DefaultDelete() = default;
19
20 template<typename U>
22 constexpr DefaultDelete(DefaultDelete<U> const&) {}
23
24 constexpr void operator()(T* pointer) const { delete pointer; }
25};
26
27template<typename T, typename Deleter = DefaultDelete<T>>
28class Box {
29public:
32 = default;
33
37
38 constexpr explicit Box(T* pointer)
40 : m_pointer(pointer) {}
41
42 Box(Box const&) = delete;
43 constexpr Box(Box&& other)
45 : m_pointer(other.release()), m_deleter(util::forward<Deleter>(other.get_deleter())) {}
46
47 constexpr Box(T* pointer, Deleter const& deleter)
49 : m_pointer(pointer), m_deleter(deleter) {}
50
51 template<concepts::MoveConstructible D = Deleter>
53 constexpr Box(T* pointer, D&& deleter) : m_pointer(pointer, util::forward<D>(deleter)) {}
54
55 template<typename D = Deleter>
58
59 template<typename U, typename E>
63 constexpr Box(Box<U, E>&& other) : m_pointer(other.release()), m_deleter(util::forward<E>(other.get_deleter())) {}
64
65 constexpr ~Box() { reset(); }
66
67 auto operator=(Box const&) -> Box& = delete;
68 constexpr auto operator=(Box&& other) -> Box& requires(concepts::MoveAssignable<Deleter>) {
69 reset(other.release());
70 m_deleter = util::forward<Deleter>(other.get_deleter());
71 return *this;
72 }
73
74 template<typename U, typename E>
77 constexpr auto operator=(Box<U, E>&& other) -> Box& {
78 reset(other.release());
79 m_deleter = util::forward<Deleter>(other.get_deleter());
80 return *this;
81 }
82
83 constexpr auto operator=(nullptr_t) -> Box& {
84 reset();
85 return *this;
86 }
87
88 constexpr auto release() -> T* { return util::exchange(m_pointer, nullptr); }
89 constexpr void reset(T* pointer = nullptr) {
90 auto* old_pointer = m_pointer;
91 m_pointer = pointer;
92 if (old_pointer) {
93 function::invoke(m_deleter, old_pointer);
94 }
95 }
96
97 constexpr auto get() const -> T* { return m_pointer; }
98
99 constexpr auto get_deleter() -> Deleter& { return m_deleter; }
100 constexpr auto get_deleter() const -> Deleter const& { return m_deleter; }
101
102 constexpr explicit operator bool() const { return !!m_pointer; }
103
104 constexpr auto operator*() const -> T& {
105 DI_ASSERT(*this);
106 return *get();
107 }
108 constexpr auto operator->() const -> T* {
109 DI_ASSERT(*this);
110 return get();
111 }
112
113private:
114 template<typename U>
115 constexpr friend auto operator==(Box const& a, Box<U> const& b) -> bool {
116 return const_cast<void*>(static_cast<void const volatile*>(a.get())) ==
117 const_cast<void*>(static_cast<void const volatile*>(b.get()));
118 }
119
120 template<typename U>
121 constexpr friend auto operator<=>(Box const& a, Box<U> const& b) {
122 return const_cast<void*>(static_cast<void const volatile*>(a.get())) <=>
123 const_cast<void*>(static_cast<void const volatile*>(b.get()));
124 }
125
126 constexpr friend auto operator==(Box const& a, nullptr_t) -> bool { return a.get() == static_cast<T*>(nullptr); }
127 constexpr friend auto operator<=>(Box const& a, nullptr_t) {
128 return a == nullptr ? di::strong_ordering::equal : di::strong_ordering::greater;
129 }
130
131 T* m_pointer { nullptr };
132 [[no_unique_address]] Deleter m_deleter {};
133};
134
135namespace detail {
136 template<typename T>
138 template<typename... Args>
140 constexpr auto operator()(Args&&... args) const -> meta::AllocatorResult<platform::DefaultAllocator, Box<T>> {
142 auto* result = ::new (std::nothrow) T(util::forward<Args>(args)...);
143 if (!result) {
144 return vocab::Unexpected(BasicError::NotEnoughMemory);
145 }
146 return Box<T>(result);
147 } else {
148 auto* result = ::new T(util::forward<Args>(args)...);
149 DI_ASSERT(result);
150 return Box<T>(result);
151 }
152 }
153 };
154}
155
156template<typename T>
157constexpr inline auto make_box = detail::MakeBoxFunction<T> {};
158}
159
160namespace di {
161using vocab::Box;
162using vocab::DefaultDelete;
163using vocab::make_box;
164}
#define DI_ASSERT(...)
Definition assert_bool.h:7
Definition box.h:28
constexpr friend auto operator==(Box const &a, Box< U > const &b) -> bool
Definition box.h:115
constexpr Box(T *pointer, Deleter const &deleter)
Definition box.h:47
Box(Box const &)=delete
constexpr Box(T *pointer, D &&deleter)
Definition box.h:53
constexpr Box(nullptr_t)
Definition box.h:34
constexpr friend auto operator<=>(Box const &a, nullptr_t)
Definition box.h:127
constexpr auto operator=(Box &&other) -> Box &requires(concepts::MoveAssignable< Deleter >)
Definition box.h:68
constexpr auto get_deleter() -> Deleter &
Definition box.h:99
constexpr ~Box()
Definition box.h:65
auto operator=(Box const &) -> Box &=delete
constexpr friend auto operator==(Box const &a, nullptr_t) -> bool
Definition box.h:126
constexpr Box(T *pointer)
Definition box.h:38
constexpr auto release() -> T *
Definition box.h:88
constexpr friend auto operator<=>(Box const &a, Box< U > const &b)
Definition box.h:121
constexpr auto operator*() const -> T &
Definition box.h:104
constexpr auto operator=(nullptr_t) -> Box &
Definition box.h:83
constexpr auto get_deleter() const -> Deleter const &
Definition box.h:100
constexpr Box(Box< U, E > &&other)
Definition box.h:63
Box()=default
constexpr auto operator->() const -> T *
Definition box.h:108
constexpr void reset(T *pointer=nullptr)
Definition box.h:89
constexpr Box(Box &&other)
Definition box.h:43
Box(T *, meta::RemoveReference< D > &&)=delete
constexpr auto get() const -> T *
Definition box.h:97
Definition operations.h:19
Definition operations.h:11
Definition operations.h:99
Definition operations.h:34
Definition operations.h:24
Definition allocator.h:20
Implicit conversion for this test refers to the ability to return a value of function from a type.
Definition operations.h:89
Definition language.h:30
Definition language.h:110
Definition operations.h:46
Definition operations.h:43
Definition language.h:61
Definition language.h:50
Definition core.h:114
constexpr auto invoke
Definition invoke.h:100
meta::LikeExpected< decltype(di::allocate(util::declval< Alloc & >(), 0, 0)), T > AllocatorResult
Definition allocator.h:25
Type< detail::RemoveReferenceHelper< T > > RemoveReference
Definition core.h:71
container::InfallibleAllocator DefaultAllocator
Definition custom.h:39
std::nullptr_t nullptr_t
Definition nullptr_t.h:12
Definition vocab.h:96
constexpr auto exchange(T &object, U &&new_value) -> T
Definition exchange.h:8
Definition erasure_cast.h:7
Definition lazy.h:165
constexpr auto make_box
Definition box.h:157
Unexpected(E &&) -> Unexpected< meta::UnwrapRefDecay< E > >
Definition zstring_parser.h:9
constexpr DefaultDelete(DefaultDelete< U > const &)
Definition box.h:22
constexpr void operator()(T *pointer) const
Definition box.h:24