di 0.1.0
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:
30 using Type = T;
31
34 = default;
35
39
40 constexpr explicit Box(T* pointer)
42 : m_pointer(pointer) {}
43
44 Box(Box const&) = delete;
45 constexpr Box(Box&& other)
47 : m_pointer(other.release()), m_deleter(util::forward<Deleter>(other.get_deleter())) {}
48
49 constexpr Box(T* pointer, Deleter const& deleter)
51 : m_pointer(pointer), m_deleter(deleter) {}
52
53 template<concepts::MoveConstructible D = Deleter>
55 constexpr Box(T* pointer, D&& deleter) : m_pointer(pointer, util::forward<D>(deleter)) {}
56
57 template<typename D = Deleter>
60
61 template<typename U, typename E>
65 constexpr Box(Box<U, E>&& other) : m_pointer(other.release()), m_deleter(util::forward<E>(other.get_deleter())) {}
66
67 constexpr ~Box() { reset(); }
68
69 auto operator=(Box const&) -> Box& = delete;
70 constexpr auto operator=(Box&& other) -> Box&
72 {
73 reset(other.release());
74 m_deleter = util::forward<Deleter>(other.get_deleter());
75 return *this;
76 }
77
78 template<typename U, typename E>
81 constexpr auto operator=(Box<U, E>&& other) -> Box& {
82 reset(other.release());
83 m_deleter = util::forward<Deleter>(other.get_deleter());
84 return *this;
85 }
86
87 constexpr auto operator=(nullptr_t) -> Box& {
88 reset();
89 return *this;
90 }
91
92 constexpr auto release() -> T* { return util::exchange(m_pointer, nullptr); }
93 constexpr void reset(T* pointer = nullptr) {
94 auto* old_pointer = m_pointer;
95 m_pointer = pointer;
96 if (old_pointer) {
97 function::invoke(m_deleter, old_pointer);
98 }
99 }
100
101 constexpr auto get() const -> T* { return m_pointer; }
102
103 constexpr auto get_deleter() -> Deleter& { return m_deleter; }
104 constexpr auto get_deleter() const -> Deleter const& { return m_deleter; }
105
106 constexpr explicit operator bool() const { return !!m_pointer; }
107
108 constexpr auto operator*() const -> T& {
109 DI_ASSERT(*this);
110 return *get();
111 }
112 constexpr auto operator->() const -> T* {
113 DI_ASSERT(*this);
114 return get();
115 }
116
117 constexpr auto begin() const -> T* { return get(); }
118 constexpr auto end() const -> T* {
119 if (get()) {
120 return get() + 1;
121 }
122 return nullptr;
123 }
124
125private:
126 template<typename U>
127 constexpr friend auto operator==(Box const& a, Box<U> const& b) -> bool {
128 return const_cast<void*>(static_cast<void const volatile*>(a.get())) ==
129 const_cast<void*>(static_cast<void const volatile*>(b.get()));
130 }
131
132 template<typename U>
133 constexpr friend auto operator<=>(Box const& a, Box<U> const& b) {
134 return const_cast<void*>(static_cast<void const volatile*>(a.get())) <=>
135 const_cast<void*>(static_cast<void const volatile*>(b.get()));
136 }
137
138 constexpr friend auto operator==(Box const& a, nullptr_t) -> bool { return a.get() == static_cast<T*>(nullptr); }
139 constexpr friend auto operator<=>(Box const& a, nullptr_t) {
140 return a == nullptr ? di::strong_ordering::equal : di::strong_ordering::greater;
141 }
142
143 T* m_pointer { nullptr };
144 [[no_unique_address]] Deleter m_deleter {};
145};
146
147namespace detail {
148 template<typename T>
149 struct MakeBoxFunction {
150 template<typename... Args>
151 requires(!concepts::LanguageArray<T> && concepts::ConstructibleFrom<T, Args...>)
152 constexpr auto operator()(Args&&... args) const -> meta::AllocatorResult<platform::DefaultAllocator, Box<T>> {
153 if constexpr (concepts::FallibleAllocator<platform::DefaultAllocator>) {
154 auto* result = ::new (std::nothrow) T(util::forward<Args>(args)...);
155 if (!result) {
156 return vocab::Unexpected(BasicError::NotEnoughMemory);
157 }
158 return Box<T>(result);
159 } else {
160 auto* result = ::new T(util::forward<Args>(args)...);
161 DI_ASSERT(result);
162 return Box<T>(result);
163 }
164 }
165 };
166}
167
168template<typename T>
169constexpr inline auto make_box = detail::MakeBoxFunction<T> {};
170}
171
172namespace di {
173using vocab::Box;
174using vocab::DefaultDelete;
175using vocab::make_box;
176}
#define DI_ASSERT(...)
Definition assert_bool.h:7
Box()=default
constexpr friend auto operator==(Box const &a, Box< U > const &b) -> bool
Definition box.h:127
constexpr auto end() const -> T *
Definition box.h:118
constexpr Box(T *pointer, Deleter const &deleter)
Definition box.h:49
Box(Box const &)=delete
constexpr Box(T *pointer, D &&deleter)
Definition box.h:55
constexpr Box(nullptr_t)
Definition box.h:36
constexpr friend auto operator<=>(Box const &a, nullptr_t)
Definition box.h:139
constexpr auto operator=(Box &&other) -> Box &requires(concepts::MoveAssignable< Deleter >)
Definition box.h:70
T Type
Definition box.h:30
constexpr auto get_deleter() -> Deleter &
Definition box.h:103
constexpr ~Box()
Definition box.h:67
auto operator=(Box const &) -> Box &=delete
constexpr friend auto operator==(Box const &a, nullptr_t) -> bool
Definition box.h:138
constexpr Box(T *pointer)
Definition box.h:40
constexpr auto release() -> T *
Definition box.h:92
constexpr friend auto operator<=>(Box const &a, Box< U > const &b)
Definition box.h:133
constexpr auto operator*() const -> T &
Definition box.h:108
constexpr auto operator=(nullptr_t) -> Box &
Definition box.h:87
constexpr auto begin() const -> T *
Definition box.h:117
constexpr auto get_deleter() const -> Deleter const &
Definition box.h:104
constexpr Box(Box< U, E > &&other)
Definition box.h:65
Box()=default
constexpr auto operator->() const -> T *
Definition box.h:112
constexpr void reset(T *pointer=nullptr)
Definition box.h:93
constexpr Box(Box &&other)
Definition box.h:45
Box(T *, meta::RemoveReference< D > &&)=delete
constexpr auto get() const -> T *
Definition box.h:101
Definition operations.h:19
Definition operations.h:99
Definition operations.h:34
Definition operations.h:24
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 lazy.h:165
constexpr auto make_box
Definition box.h:169
Unexpected(E &&) -> Unexpected< meta::UnwrapRefDecay< E > >
Definition any_storable.h:9
DefaultDelete()=default
constexpr DefaultDelete(DefaultDelete< U > const &)
Definition box.h:22
constexpr void operator()(T *pointer) const
Definition box.h:24