Iros
 
Loading...
Searching...
No Matches
any.h
Go to the documentation of this file.
1#pragma once
2
9#include "di/meta/core.h"
10#include "di/meta/operations.h"
11#include "di/meta/vocab.h"
12#include "di/util/addressof.h"
13#include "di/util/forward.h"
15#include "di/util/swap.h"
16#include "di/util/voidify.h"
17
18namespace di::any {
19namespace detail {
20 template<typename E, typename S, typename Interface>
21 struct MethodImplT {
22 struct Type {};
23 };
24
25 template<typename E, typename S, typename Interface>
27
28 template<typename E, typename S, typename Tag, typename R, concepts::RemoveCVRefSameAs<This> Self,
29 typename... BArgs, typename... Rest>
30 struct MethodImplT<E, S, meta::List<Method<Tag, R(Self, BArgs...)>, Rest...>> {
31 struct Type : MethodImpl<E, S, meta::List<Rest...>> {
32 constexpr static auto vtable(auto&& self) -> decltype(auto) { return (self.m_vtable); }
33 constexpr static auto storage(E& self) -> S& { return self; }
34 constexpr static auto storage(E const& self) -> S const& { return self; }
35
36 template<typename X>
38 constexpr friend auto tag_invoke(Tag, X&& self_in, BArgs... bargs) -> R {
39 auto&& self = static_cast<meta::Like<Self, E>>(self_in); // NOLINT(modernize-use-auto)
40 auto const& vtable = Type::vtable(self);
41 auto* storage = util::voidify(util::addressof(Type::storage(self)));
42
43 auto erased_fp = vtable[Method<Tag, R(Self, BArgs...)> {}];
44 return erased_fp(storage, util::forward<BArgs>(bargs)...);
45 }
46 };
47 };
48}
49
50template<typename UserInterface, typename Storage, typename VTablePolicy>
51struct AnyT {
52 class Type
53 : private detail::MethodImpl<Type, Storage, meta::MergeInterfaces<UserInterface, typename Storage::Interface>>
54 , public Storage {
55 template<typename, typename, typename>
56 friend struct detail::MethodImplT;
57
58 public:
59 using AnyStorage = Storage;
62
63 private:
65 "VTablePolicy policy returned an invalid VTable for the provided interface.");
66
67 constexpr static auto storage_category = Storage::storage_category();
68
69 constexpr static bool is_reference = storage_category == StorageCategory::Reference;
70 constexpr static bool is_trivially_destructible = is_reference || storage_category == StorageCategory::Trivial;
71 constexpr static bool is_trivially_copyable = is_reference || storage_category == StorageCategory::Trivial;
72 constexpr static bool is_trivially_moveable = is_trivially_copyable;
73
74 constexpr static bool is_moveable = !is_trivially_moveable && storage_category != StorageCategory::Immovable;
75 constexpr static bool is_copyable = storage_category == StorageCategory::Copyable;
76
77 template<typename T>
78 using RemoveConstructQualifiers = meta::Conditional<is_reference, T, meta::RemoveCVRef<T>>;
79
80 public:
81 template<typename U, typename VU = RemoveConstructQualifiers<U>>
84 constexpr static auto create(U&& value) {
87
88 auto result = R {};
89 Storage::create(in_place_type<Type>, result, in_place_type<VU>, util::forward<U>(value));
90 if (result) {
91 result->m_vtable = VTable::template create_for<Storage, VU>();
92 }
93 return R(util::move(result));
94 } else {
95 return Type(in_place_type<VU>, util::forward<U>(value));
96 }
97 }
98
99 template<typename T, typename... Args, concepts::Impl<Interface> VT = RemoveConstructQualifiers<T>>
101 constexpr static auto create(InPlaceType<T>, Args&&... args) {
104
105 auto result = R {};
106 Storage::create(in_place_type<Type>, result, in_place_type<VT>, util::forward<Args>(args)...);
107 if (result) {
108 result->m_vtable = VTable::template create_for<Storage, VT>();
109 }
110 return result;
111 } else {
112 return Type(in_place_type<VT>, util::forward<Args>(args)...);
113 }
114 }
115
116 template<typename T, typename U, typename... Args, concepts::Impl<Interface> VT = RemoveConstructQualifiers<T>>
119 constexpr static auto create(InPlaceType<T>, std::initializer_list<U> list, Args&&... args) {
122
123 auto result = R {};
124 Storage::create(in_place_type<Type>, result, in_place_type<VT>, list, util::forward<Args>(args)...);
125 if (result) {
126 result->m_vtable = VTable::template create_for<Storage, VT>();
127 }
128 return result;
129 } else {
130 return Type(in_place_type<VT>, list, util::forward<Args>(args)...);
131 }
132 }
133
135 requires(!is_reference)
136 = default;
137
138 Type(Type const&)
139 requires(is_trivially_copyable)
140 = default;
141
142 constexpr Type(Type const& other)
143 requires(is_copyable)
144 : Storage(), m_vtable(other.m_vtable) {
145 Storage::copy_construct(other.m_vtable, this, util::addressof(other));
146 }
147
149 requires(is_trivially_moveable)
150 = default;
151
152 constexpr Type(Type&& other)
153 requires(is_moveable)
154 : m_vtable(di::move(other.m_vtable)) {
155 Storage::move_construct(other.m_vtable, this, util::addressof(other));
156 }
157
158 template<typename U, typename VU = RemoveConstructQualifiers<U>>
162 constexpr Type(U&& value) {
163 this->emplace(in_place_type<VU>, util::forward<U>(value));
164 }
165
166 template<typename T, typename... Args, concepts::Impl<Interface> VT = RemoveConstructQualifiers<T>>
168 constexpr Type(InPlaceType<T>, Args&&... args) {
169 this->emplace(in_place_type<VT>, util::forward<Args>(args)...);
170 }
171
172 template<typename T, typename U, typename... Args, concepts::Impl<Interface> VT = RemoveConstructQualifiers<T>>
175 constexpr Type(InPlaceType<T>, std::initializer_list<U> list, Args&&... args) {
176 this->emplace(in_place_type<VT>, list, util::forward<Args>(args)...);
177 }
178
180 requires(is_trivially_destructible)
181 = default;
182
183 constexpr ~Type()
184 requires(!is_trivially_destructible)
185 {
186 Storage::destroy(m_vtable, this);
187 }
188
189 auto operator=(Type const&) -> Type& requires(is_trivially_copyable) = default;
190
191 auto operator=(Type&&) -> Type& requires(is_trivially_moveable) = default;
192
193 constexpr auto operator=(Type const& other) -> Type& requires(is_copyable) {
194 if (this != di::addressof(other)) {
195 Storage::copy_assign(m_vtable, this, other.m_vtable, util::addressof(other));
196 }
197 return *this;
198 }
199
200 constexpr auto operator=(Type&& other) -> Type& requires(is_moveable) {
201 if (this != di::addressof(other)) {
202 Storage::move_assign(m_vtable, this, other.m_vtable, util::addressof(other));
203 }
204 return *this;
205 }
206
207 template<typename U, concepts::Impl<Interface> VU = RemoveConstructQualifiers<U>>
211 constexpr auto operator=(U&& value) -> Type& {
212 if constexpr (!is_trivially_destructible) {
213 Storage::destroy(m_vtable, this);
214 }
215 m_vtable = VTable::template create_for<Storage, VU>();
216 Storage::init(this, in_place_type<VU>, util::forward<U>(value));
217 return *this;
218 }
219
220 constexpr auto has_value() const -> bool
221 requires(!is_reference)
222 {
223 return !m_vtable.empty();
224 }
225
226 template<typename U, concepts::Impl<Interface> VU = RemoveConstructQualifiers<U>>
229 constexpr auto emplace(U&& value) {
230 if constexpr (!is_reference) {
231 reset();
232 }
234 return Storage::init(this, in_place_type<VU>, util::forward<U>(value)) % [&] {
235 m_vtable = VTable::template create_for<Storage, VU>();
236 };
237 } else {
238 Storage::init(this, in_place_type<VU>, util::forward<U>(value));
239 m_vtable = VTable::template create_for<Storage, VU>();
240 }
241 }
242
243 template<typename T, typename... Args, concepts::Impl<Interface> VT = RemoveConstructQualifiers<T>>
245 constexpr auto emplace(InPlaceType<T>, Args&&... args) {
246 if constexpr (!is_reference) {
247 reset();
248 }
250 return Storage::init(this, in_place_type<VT>, util::forward<Args>(args)...) % [&] {
251 m_vtable = VTable::template create_for<Storage, VT>();
252 };
253 } else {
254 (void) Storage::init(this, in_place_type<VT>, util::forward<Args>(args)...);
255 m_vtable = VTable::template create_for<Storage, VT>();
256 }
257 }
258
259 template<typename T, typename U, typename... Args, concepts::Impl<Interface> VT = RemoveConstructQualifiers<T>>
262 constexpr auto emplace(InPlaceType<T>, std::initializer_list<U> list, Args&&... args) {
263 if constexpr (!is_reference) {
264 reset();
265 }
267 return Storage::init(this, in_place_type<VT>, list, util::forward<Args>(args)...) % [&] {
268 m_vtable = VTable::template create_for<Storage, VT>();
269 };
270 } else {
271 Storage::init(this, in_place_type<VT>, list, util::forward<Args>(args)...);
272 m_vtable = VTable::template create_for<Storage, VT>();
273 }
274 }
275
276 constexpr void reset()
277 requires(!is_reference)
278 {
279 if constexpr (!is_trivially_destructible) {
280 if (has_value()) {
281 Storage::destroy(m_vtable, this);
282 }
283 }
284 m_vtable.reset();
285 }
286
287 private:
288 VTable m_vtable {};
289 };
290};
291
292template<concepts::Interface UserInterface, concepts::AnyStorage Storage = HybridStorage<>,
293 typename VTablePolicy = MaybeInlineVTable<3>>
295}
296
297namespace di {
298using any::Any;
299}
Definition any.h:54
constexpr Type(Type const &other)
Definition any.h:142
constexpr void reset()
Definition any.h:276
constexpr Type(Type &&other)
Definition any.h:152
constexpr auto emplace(U &&value)
Definition any.h:229
constexpr ~Type()
Definition any.h:183
constexpr Type(InPlaceType< T >, std::initializer_list< U > list, Args &&... args)
Definition any.h:175
meta::MergeInterfaces< UserInterface, typename Storage::Interface > Interface
Definition any.h:60
meta::Invoke< VTablePolicy, Interface > VTable
Definition any.h:61
Type(Type &&)=default
auto operator=(Type &&) -> Type &requires(is_trivially_moveable)=default
constexpr auto operator=(Type &&other) -> Type &requires(is_moveable)
Definition any.h:200
constexpr auto operator=(Type const &other) -> Type &requires(is_copyable)
Definition any.h:193
Storage AnyStorage
Definition any.h:59
static constexpr auto create(InPlaceType< T >, Args &&... args)
Definition any.h:101
constexpr auto has_value() const -> bool requires(!is_reference)
Definition any.h:220
auto operator=(Type const &) -> Type &requires(is_trivially_copyable)=default
static constexpr auto create(InPlaceType< T >, std::initializer_list< U > list, Args &&... args)
Definition any.h:119
constexpr Type(InPlaceType< T >, Args &&... args)
Definition any.h:168
constexpr auto emplace(InPlaceType< T >, Args &&... args)
Definition any.h:245
constexpr auto emplace(InPlaceType< T >, std::initializer_list< U > list, Args &&... args)
Definition any.h:262
Type(Type const &)=default
static constexpr auto create(U &&value)
Definition any.h:84
constexpr Type(U &&value)
Definition any.h:162
Definition any_storable_infallibly.h:11
Definition any_storable.h:11
Definition operations.h:11
Definition operations.h:114
Definition impl.h:17
Definition core.h:139
Definition vtable_for.h:17
Definition any.h:19
meta::Type< MethodImplT< E, S, Interface > > MethodImpl
Definition any.h:26
Definition any.h:18
@ Immovable
Definition storage_category.h:8
@ Reference
Definition storage_category.h:5
@ Trivial
Definition storage_category.h:6
@ Copyable
Definition storage_category.h:10
meta::Type< AnyT< UserInterface, Storage, VTablePolicy > > Any
Definition any.h:294
Definition merge_interfaces.h:6
detail::ConditionalHelper< value, T, U >::Type Conditional
Definition core.h:88
T::Type Type
Definition core.h:26
Type< detail::LikeHelper< T, U > > Like
Definition language.h:468
meta::Unique< meta::Concat< meta::Transform< Interfaces, meta::Quote< meta::Type > >... > > MergeInterfaces
Definition merge_interfaces.h:8
Type< detail::LikeExpectedHelper< T, U > > LikeExpected
Definition vocab.h:60
Type< Defer< Fun::template Invoke, Args... > > Invoke
Definition function.h:43
di::meta::Decay< decltype(T)> Tag
Definition tag_invoke.h:28
constexpr auto voidify
Definition voidify.h:13
Definition zstring_parser.h:9
constexpr auto in_place_type
Definition in_place_type.h:12
Definition any.h:51
Definition any.h:21
constexpr friend auto tag_invoke(Tag, X &&self_in, BArgs... bargs) -> R
Definition any.h:38
static constexpr auto storage(E const &self) -> S const &
Definition any.h:34
static constexpr auto vtable(auto &&self) -> decltype(auto)
Definition any.h:32
Definition in_place_type.h:5
Definition method.h:7