Iros
 
Loading...
Searching...
No Matches
function.h
Go to the documentation of this file.
1#pragma once
2
9#include "di/meta/algorithm.h"
10#include "di/meta/constexpr.h"
11#include "di/meta/language.h"
12#include "di/meta/util.h"
13#include "di/platform/prelude.h"
14#include "di/types/prelude.h"
15#include "di/util/addressof.h"
17#include "di/util/destroy_at.h"
18#include "di/util/exchange.h"
20#include "di/util/std_new.h"
21#include "di/util/voidify.h"
26
27namespace di::function {
28namespace function_ns {
29 template<typename Function>
31
32 template<typename R, typename... Args>
33 struct SignatureInfo<R(Args...)> {
34 using Type = R(Args...);
35
36 template<typename... Fs>
37 constexpr static bool is_invocable = concepts::InvocableR<R, Fs..., Args...>;
38
39 constexpr static bool is_noexcept = false;
40
41 template<typename T>
42 using CVQualified = T;
43
44 template<typename T>
45 using RefQualified = T;
46 };
47
48 template<typename R, typename... Args>
49 struct SignatureInfo<R(Args...) const> {
50 using Type = R(Args...);
51
52 template<typename... Fs>
53 constexpr static bool is_invocable = concepts::InvocableR<R, Fs..., Args...>;
54
55 constexpr static bool is_noexcept = false;
56
57 template<typename T>
58 using CVQualified = T const;
59
60 template<typename T>
61 using RefQualified = T;
62 };
63
64 template<typename R, typename... Args>
65 struct SignatureInfo<R(Args...)&> {
66 using Type = R(Args...);
67
68 template<typename... Fs>
69 constexpr static bool is_invocable = concepts::InvocableR<R, Fs..., Args...>;
70
71 constexpr static bool is_noexcept = false;
72
73 template<typename T>
74 using CVQualified = T;
75
76 template<typename T>
77 using RefQualified = T&;
78 };
79
80 template<typename R, typename... Args>
81 struct SignatureInfo<R(Args...) const&> {
82 using Type = R(Args...);
83
84 template<typename... Fs>
85 constexpr static bool is_invocable = concepts::InvocableR<R, Fs..., Args...>;
86
87 constexpr static bool is_noexcept = false;
88
89 template<typename T>
90 using CVQualified = T const;
91
92 template<typename T>
93 using RefQualified = T&;
94 };
95
96 template<typename R, typename... Args>
97 struct SignatureInfo<R(Args...) &&> {
98 using Type = R(Args...);
99
100 template<typename... Fs>
101 constexpr static bool is_invocable = concepts::InvocableR<R, Fs..., Args...>;
102
103 constexpr static bool is_noexcept = false;
104
105 template<typename T>
106 using CVQualified = T;
107
108 template<typename T>
109 using RefQualified = T&&;
110 };
111
112 template<typename R, typename... Args>
113 struct SignatureInfo<R(Args...) const&&> {
114 using Type = R(Args...);
115
116 template<typename... Fs>
117 constexpr static bool is_invocable = concepts::InvocableR<R, Fs..., Args...>;
118
119 constexpr static bool is_noexcept = false;
120
121 template<typename T>
122 using CVQualified = T const;
123
124 template<typename T>
125 using RefQualified = T&&;
126 };
127
128 template<typename R, typename... Args>
129 struct SignatureInfo<R(Args...) noexcept> {
130 using Type = R(Args...);
131
132 template<typename... Fs>
133 constexpr static bool is_invocable = concepts::InvocableR<R, Fs..., Args...>;
134
135 constexpr static bool is_noexcept = true;
136
137 template<typename T>
138 using CVQualified = T;
139
140 template<typename T>
141 using RefQualified = T;
142 };
143
144 template<typename R, typename... Args>
145 struct SignatureInfo<R(Args...) const noexcept> {
146 using Type = R(Args...);
147
148 template<typename... Fs>
149 constexpr static bool is_invocable = concepts::InvocableR<R, Fs..., Args...>;
150
151 constexpr static bool is_noexcept = true;
152
153 template<typename T>
154 using CVQualified = T const;
155
156 template<typename T>
157 using RefQualified = T;
158 };
159
160 template<typename R, typename... Args>
161 struct SignatureInfo<R(Args...) & noexcept> {
162 using Type = R(Args...);
163
164 template<typename... Fs>
165 constexpr static bool is_invocable = concepts::InvocableR<R, Fs..., Args...>;
166
167 constexpr static bool is_noexcept = true;
168
169 template<typename T>
170 using CVQualified = T;
171
172 template<typename T>
173 using RefQualified = T&;
174 };
175
176 template<typename R, typename... Args>
177 struct SignatureInfo<R(Args...) const & noexcept> {
178 using Type = R(Args...);
179
180 template<typename... Fs>
181 constexpr static bool is_invocable = concepts::InvocableR<R, Fs..., Args...>;
182
183 constexpr static bool is_noexcept = true;
184
185 template<typename T>
186 using CVQualified = T const;
187
188 template<typename T>
189 using RefQualified = T&;
190 };
191
192 template<typename R, typename... Args>
193 struct SignatureInfo<R(Args...) && noexcept> {
194 using Type = R(Args...);
195
196 template<typename... Fs>
197 constexpr static bool is_invocable = concepts::InvocableR<R, Fs..., Args...>;
198
199 constexpr static bool is_noexcept = true;
200
201 template<typename T>
202 using CVQualified = T;
203
204 template<typename T>
205 using RefQualified = T&&;
206 };
207
208 template<typename R, typename... Args>
209 struct SignatureInfo<R(Args...) const && noexcept> {
210 using Type = R(Args...);
211
212 template<typename... Fs>
213 constexpr static bool is_invocable = concepts::InvocableR<R, Fs..., Args...>;
214
215 constexpr static bool is_noexcept = true;
216
217 template<typename T>
218 using CVQualified = T const;
219
220 template<typename T>
221 using RefQualified = T&&;
222 };
223
225 union {
226 void* pointer;
227 alignas(2 * sizeof(void*)) di::Array<di::Byte, 2 * sizeof(void*)> byte_storage;
228 };
229
230 auto address() -> void* { return util::addressof(byte_storage[0]); }
231 auto address() const -> void const* { return util::addressof(byte_storage[0]); }
232 };
233
234 template<typename F>
235 concept StoredInline =
236 sizeof(F) <= sizeof(ErasedStorage) && alignof(F) <= alignof(ErasedStorage) && concepts::MoveConstructible<F>;
237
238 template<concepts::Allocator Alloc>
240 private:
241 using ThunkFunction = void (*)(ErasedStorage*, ErasedStorage*, Alloc&);
242
243 template<typename T>
244 constexpr static void concrete_thunk(ErasedStorage* a, ErasedStorage* b, Alloc& allocator) {
245 if consteval {
246 if (b) {
247 // Move from b into a.
248 a->pointer = util::exchange(b->pointer, nullptr);
249 } else {
250 // Just destroy a.
251 auto* a_value = static_cast<T*>(a->pointer);
252 util::destroy_at(a_value);
253 di::deallocate_one<T>(allocator, a_value);
254 }
255 return;
256 }
257 if constexpr (StoredInline<T>) {
258 if (b) {
259 // Move from b into a.
260 auto* b_value = static_cast<T*>(b->address());
261 util::construct_at(static_cast<T*>(a->address()), util::move(*b_value));
262 util::destroy_at(b_value);
263 } else {
264 // Just destroy a.
265 util::destroy_at(static_cast<T*>(a->address()));
266 }
267 } else {
268 if (b) {
269 // Move from b into a.
270 a->pointer = util::exchange(b->pointer, nullptr);
271 } else {
272 // Just destroy a.
273 auto* a_value = static_cast<T*>(a->pointer);
274 util::destroy_at(a_value);
275 di::deallocate_one<T>(allocator, a_value);
276 }
277 }
278 }
279
280 public:
281 ErasedObject() = default;
282
283 ErasedObject(ErasedObject const&) = delete;
284 constexpr ErasedObject(ErasedObject&& other) {
285 m_thunk = util::exchange(other.m_thunk, nullptr);
286 if (m_thunk) {
287 m_thunk(util::addressof(m_storage), util::addressof(other.m_storage), m_allocator);
288 }
289 }
290
291 constexpr ~ErasedObject() { reset(); }
292
293 auto operator=(ErasedObject const&) -> ErasedObject& = delete;
294 constexpr auto operator=(ErasedObject&& other) -> ErasedObject& {
295 reset();
296 m_thunk = util::exchange(other.m_thunk, nullptr);
297 if (m_thunk) {
298 m_thunk(util::addressof(m_storage), util::addressof(other.m_storage), m_allocator);
299 }
300 return *this;
301 }
302
303 constexpr auto empty() const -> bool { return m_thunk != nullptr; }
304 constexpr void reset() {
305 if (auto* old_thunk = util::exchange(m_thunk, nullptr)) {
306 old_thunk(util::addressof(m_storage), nullptr, m_allocator);
307 }
308 }
309
310 template<typename T>
311 constexpr auto down_cast() -> T* {
312 if consteval {
313 return static_cast<T*>(m_storage.pointer);
314 }
315 if constexpr (StoredInline<T>) {
316 return static_cast<T*>(m_storage.address());
317 } else {
318 return static_cast<T*>(m_storage.pointer);
319 }
320 }
321
322 template<typename T>
323 constexpr auto down_cast() const -> T* {
324 if consteval {
325 return static_cast<T*>(m_storage.pointer);
326 }
327 if constexpr (StoredInline<T>) {
328 return static_cast<T*>(m_storage.address());
329 } else {
330 return static_cast<T*>(m_storage.pointer);
331 }
332 }
333
334 template<typename T, typename... Args>
335 requires(StoredInline<T>)
336 constexpr void init_inline(Args&&... args) {
337 if consteval {
338 (void) this->init_out_of_line<T>(di::forward<Args>(args)...);
339 return;
340 }
341 m_thunk = &concrete_thunk<T>;
342 util::construct_at(this->down_cast<T>(), util::forward<Args>(args)...);
343 }
344
345 template<typename T, typename... Args>
346 constexpr auto init_out_of_line(Args&&... args) {
347 return vocab::as_fallible(di::allocate_one<T>(m_allocator)) % [&](T* storage) {
348 m_thunk = &concrete_thunk<T>;
349 m_storage.pointer = di::voidify(storage);
350 util::construct_at(storage, util::forward<Args>(args)...);
352 }
353
354 private:
355 ThunkFunction m_thunk { nullptr };
356 ErasedStorage m_storage;
357 [[no_unique_address]] Alloc m_allocator {};
358 };
359
360 template<typename T, concepts::Allocator = platform::DefaultAllocator>
361 struct MakeFunction;
362
363 template<typename Sig, concepts::Allocator Alloc = platform::DefaultAllocator,
365 class Function;
366
367 template<typename Sig, concepts::Allocator Alloc, typename R, typename... Args>
368 class Function<Sig, Alloc, R(Args...)> {
369 private:
370 template<typename, concepts::Allocator>
371 friend struct MakeFunction;
372
373 using ErasedObject = function_ns::ErasedObject<Alloc>;
374
375 using Info = SignatureInfo<Sig>;
376
377 template<typename... Fs>
378 constexpr static bool is_invocable = Info::template is_invocable<Fs...>;
379
380 constexpr static bool is_noexcept = Info::is_noexcept;
381
382 template<typename T>
383 using CVQualified = Info::template CVQualified<T>;
384
385 template<typename T>
386 using RefQualified = Info::template RefQualified<T>;
387
388 template<typename T>
389 using Qualified = RefQualified<CVQualified<T>>;
390
391 constexpr static bool is_const = concepts::SameAs<CVQualified<int>, int const>;
392 constexpr static bool is_lvalue = concepts::SameAs<RefQualified<int>, int&>;
393 constexpr static bool is_rvalue = concepts::SameAs<RefQualified<int>, int&&>;
394
395 template<typename T>
396 using InvQualifed = meta::Conditional<is_lvalue || is_rvalue, Qualified<T>, CVQualified<T>&>;
397
398 template<typename VT>
399 constexpr static bool is_callable_from = is_invocable<Qualified<VT>> && is_invocable<InvQualifed<VT>>;
400
401 template<auto f, typename VT>
402 constexpr static bool is_callable_as_if_from = is_invocable<decltype(f), InvQualifed<VT>>;
403
404 using ErasedFunctionPointer = R (*)(meta::MaybeConst<is_const, ErasedObject>*, Args&&...) noexcept(is_noexcept);
405
406 template<typename T>
407 constexpr static auto concrete_impl(meta::MaybeConst<is_const, ErasedObject>* object,
408 Args&&... args) noexcept(is_noexcept) -> R {
409 using CV = CVQualified<T>;
410 using Inv = InvQualifed<T>;
411 return function::invoke_r<R>(util::forward<Inv>(*object->template down_cast<CV>()),
412 util::forward<Args>(args)...);
413 }
414
415 template<auto f>
416 constexpr static auto concrete_impl_for_constexpr(meta::MaybeConst<is_const, ErasedObject>*,
417 Args&&... args) noexcept(is_noexcept) -> R {
418 return function::invoke_r<R>(f, util::forward<Args>(args)...);
419 }
420
421 template<auto f, typename T>
422 constexpr static auto concrete_impl_for_bound_constexpr(meta::MaybeConst<is_const, ErasedObject>* object,
423 Args&&... args) -> R {
424 using CV = CVQualified<T>;
425 using Inv = InvQualifed<T>;
426 return function::invoke_r<R>(f, util::forward<Inv>(*object->template down_cast<CV>()),
427 util::forward<Args>(args)...);
428 }
429
430 public:
431 Function() = default;
432 constexpr Function(nullptr_t) : Function() {}
433
434 Function(Function const&) = delete;
435 constexpr Function(Function&& other)
436 : m_object(util::move(other.m_object)), m_impl(util::exchange(other.m_impl, nullptr)) {}
437
438 template<auto f>
439 requires(is_invocable<decltype(f)>)
441 m_impl = &concrete_impl_for_constexpr<f>;
442 }
443
444 template<typename F, typename VT = meta::Decay<F>>
447 constexpr Function(F&& object) {
448 if constexpr (concepts::MemberPointer<VT> ||
450 if (object == nullptr) {
451 return;
452 }
453 }
454 m_object.template init_inline<VT>(util::forward<F>(object));
455 m_impl = &concrete_impl<VT>;
456 }
457
458 template<auto f, typename T, typename VT = meta::Decay<T>>
459 requires(concepts::ConstructibleFrom<VT, T> && is_callable_as_if_from<f, VT> && StoredInline<VT>)
460 constexpr Function(Constexpr<f>, T&& object) {
461 m_object.template init_inline<VT>(util::forward<T>(object));
462 m_impl = &concrete_impl_for_bound_constexpr<f, VT>;
463 }
464
465 template<typename T, typename... Ts, typename VT = meta::Decay<T>>
466 requires(concepts::ConstructibleFrom<T, Ts...> && is_callable_from<VT> && StoredInline<VT>)
467 constexpr explicit Function(InPlaceType<T>, Ts&&... args) {
468 m_object.template init_inline<VT>(util::forward<Ts>(args)...);
469 m_impl = &concrete_impl<VT>;
470 }
471
472 template<typename T, typename U, typename... Ts, typename VT = meta::Decay<T>>
473 requires(concepts::ConstructibleFrom<T, std::initializer_list<U>&, Ts...> && is_callable_from<VT> &&
475 constexpr explicit Function(InPlaceType<T>, std::initializer_list<U> list, Ts&&... args) {
476 m_object.template init_inline<VT>(list, util::forward<Ts>(args)...);
477 m_impl = &concrete_impl<VT>;
478 }
479
480 template<auto f, typename T, typename... Ts, typename VT = meta::Decay<T>>
481 requires(concepts::ConstructibleFrom<T, Ts...> && is_callable_from<VT> && StoredInline<VT>)
482 constexpr explicit Function(Constexpr<f>, InPlaceType<T>, Ts&&... args) {
483 m_object.template init_inline<VT>(util::forward<Ts>(args)...);
484 m_impl = &concrete_impl_for_bound_constexpr<f, VT>;
485 }
486
487 template<auto f, typename T, typename U, typename... Ts, typename VT = meta::Decay<T>>
488 requires(concepts::ConstructibleFrom<T, std::initializer_list<U>&, Ts...> && is_callable_from<VT> &&
490 constexpr explicit Function(Constexpr<f>, InPlaceType<T>, std::initializer_list<U> list, Ts&&... args) {
491 m_object.template init_inline<VT>(list, util::forward<Ts>(args)...);
492 m_impl = &concrete_impl_for_bound_constexpr<f, VT>;
493 }
494
495 ~Function() = default;
496
497 constexpr auto operator=(nullptr_t) -> Function& {
498 m_object.reset();
499 m_impl = nullptr;
500 return *this;
501 }
502 auto operator=(Function const&) -> Function& = delete;
503 constexpr auto operator=(Function&& other) -> Function& {
504 m_object = util::move(other.m_object);
505 m_impl = util::exchange(other.m_impl, nullptr);
506 return *this;
507 }
508
509 template<typename F>
511 constexpr auto operator=(F&& value) -> Function& {
512 auto new_value = Function(util::forward<F>(value));
513 util::swap(*this, new_value);
514 return *this;
515 }
516
517 constexpr auto operator()(Args... args) noexcept(is_noexcept) -> R
518 requires(!is_const && !is_lvalue && !is_rvalue)
519 {
520 DI_ASSERT(m_impl);
521 return m_impl(util::addressof(m_object), util::forward<Args>(args)...);
522 }
523
524 constexpr auto operator()(Args... args) const noexcept(is_noexcept) -> R
525 requires(is_const && !is_lvalue && !is_rvalue)
526 {
527 DI_ASSERT(m_impl);
528 return m_impl(util::addressof(m_object), util::forward<Args>(args)...);
529 }
530
531 constexpr auto operator()(Args... args) & noexcept(is_noexcept) -> R
532 requires(!is_const && is_lvalue)
533 {
534 DI_ASSERT(m_impl);
535 return m_impl(util::addressof(m_object), util::forward<Args>(args)...);
536 }
537
538 constexpr auto operator()(Args... args) const& noexcept(is_noexcept) -> R
539 requires(is_const && is_lvalue)
540 {
541 DI_ASSERT(m_impl);
542 return m_impl(util::addressof(m_object), util::forward<Args>(args)...);
543 }
544
545 constexpr auto operator()(Args... args) && noexcept(is_noexcept) -> R
546 requires(!is_const && is_rvalue)
547 {
548 DI_ASSERT(m_impl);
549 return m_impl(util::addressof(m_object), util::forward<Args>(args)...);
550 }
551
552 constexpr auto operator()(Args... args) const&& noexcept(is_noexcept) -> R
553 requires(is_const && is_rvalue)
554 {
555 DI_ASSERT(m_impl);
556 return m_impl(util::addressof(m_object), util::forward<Args>(args)...);
557 }
558
559 constexpr explicit operator bool() const { return m_impl != nullptr; }
560
561 private:
562 constexpr friend auto operator==(Function const& a, nullptr_t) -> bool { return !bool(a); }
563
564 ErasedObject m_object {};
565 ErasedFunctionPointer m_impl { nullptr };
566 };
567
568 template<typename Signature, concepts::Allocator Alloc>
570 private:
571 using Function = function_ns::Function<Signature>;
572
573 public:
574 template<typename F, typename VT = meta::Decay<F>>
575 requires(!concepts::SameAs<meta::RemoveCVRef<F>, Function> &&
576 !concepts::InstanceOf<meta::RemoveCVRef<F>, InPlaceType> && Function::template is_callable_from<VT>)
577 constexpr auto operator()(F&& object) const -> meta::AllocatorResult<Alloc, Function> {
578 Function result;
579 if constexpr (concepts::MemberPointer<VT> ||
581 if (object == nullptr) {
582 return result;
583 }
584 }
585 if constexpr (StoredInline<VT>) {
586 result.m_object.template init_inline<VT>(util::forward<F>(object));
587 } else if constexpr (concepts::FallibleAllocator<Alloc>) {
588 DI_TRY(result.m_object.template init_out_of_line<VT>(util::forward<F>(object)));
589 } else {
590 result.m_object.template init_out_of_line<VT>(util::forward<F>(object));
591 }
592 result.m_impl = &Function::template concrete_impl<VT>;
593 return result;
594 }
595
596 template<auto f, typename T, typename VT = meta::Decay<T>>
597 requires(concepts::ConstructibleFrom<VT, T> && Function::template is_callable_as_if_from<f, VT>)
598 constexpr auto operator()(Constexpr<f>, T&& object) const -> meta::AllocatorResult<Alloc, Function> {
599 Function result;
600 if constexpr (StoredInline<VT>) {
601 result.m_object.template init_inline<VT>(util::forward<T>(object));
602 } else if constexpr (concepts::FallibleAllocator<Alloc>) {
603 DI_TRY(result.m_object.template init_out_of_line_fallible<VT>(util::forward<T>(object)));
604 } else {
605 result.m_object.template init_out_of_line<VT>(util::forward<T>(object));
606 }
607 result.m_impl = &Function::template concrete_impl_for_bound_constexpr<f, VT>;
608 return result;
609 }
610
611 template<typename T, typename... Ts, typename VT = meta::Decay<T>>
612 requires(concepts::ConstructibleFrom<T, Ts...> && Function::template is_callable_from<VT>)
613 constexpr auto operator()(InPlaceType<T>, Ts&&... args) const -> meta::AllocatorResult<Alloc, Function> {
614 Function result;
615 if constexpr (StoredInline<VT>) {
616 result.m_object.template init_inline<VT>(util::forward<Ts>(args)...);
617 } else if constexpr (concepts::FallibleAllocator<Alloc>) {
618 DI_TRY(result.m_object.template init_out_of_line_fallible<VT>(util::forward<Ts>(args)...));
619 } else {
620 result.m_object.template init_out_of_line<VT>(util::forward<Ts>(args)...);
621 }
622 result.m_impl = &Function::template concrete_impl<VT>;
623 return result;
624 }
625
626 template<typename T, typename U, typename... Ts, typename VT = meta::Decay<T>>
628 Function::template is_callable_from<VT>)
629 constexpr auto operator()(InPlaceType<T>, std::initializer_list<U> list, Ts&&... args) const
631 Function result;
632 if constexpr (StoredInline<VT>) {
633 result.m_object.template init_inline<VT>(list, util::forward<Ts>(args)...);
634 } else if constexpr (concepts::FallibleAllocator<Alloc>) {
635 DI_TRY(result.m_object.template init_out_of_line_fallible<VT>(list, util::forward<Ts>(args)...));
636 } else {
637 result.m_object.template init_out_of_line<VT>(list, util::forward<Ts>(args)...);
638 }
639 result.m_impl = &Function::template concrete_impl<VT>;
640 return result;
641 }
642
643 template<auto f, typename T, typename... Ts, typename VT = meta::Decay<T>>
644 requires(concepts::ConstructibleFrom<T, Ts...> && Function::template is_callable_from<VT>)
645 constexpr auto operator()(Constexpr<f>, InPlaceType<T>, Ts&&... args) const
647 Function result;
648 if constexpr (StoredInline<VT>) {
649 result.m_object.template init_inline<VT>(util::forward<Ts>(args)...);
650 } else if constexpr (concepts::FallibleAllocator<Alloc>) {
651 DI_TRY(result.m_object.template init_out_of_line_fallible<VT>(util::forward<Ts>(args)...));
652 } else {
653 result.m_object.template init_out_of_line<VT>(util::forward<Ts>(args)...);
654 }
655 result.m_impl = &Function::template concrete_impl_for_bound_constexpr<f, VT>;
656 return result;
657 }
658
659 template<auto f, typename T, typename U, typename... Ts, typename VT = meta::Decay<T>>
661 Function::template is_callable_from<VT> && StoredInline<VT>)
662 constexpr auto operator()(Constexpr<f>, InPlaceType<T>, std::initializer_list<U> list, Ts&&... args) const
664 Function result;
665 if constexpr (StoredInline<VT>) {
666 result.m_object.template init_inline<VT>(list, util::forward<Ts>(args)...);
667 } else if constexpr (concepts::FallibleAllocator<Alloc>) {
668 DI_TRY(result.m_object.template init_out_of_line_fallible<VT>(list, util::forward<Ts>(args)...));
669 } else {
670 result.m_object.template init_out_of_line<VT>(list, util::forward<Ts>(args)...);
671 }
672 result.m_impl = &Function::template concrete_impl_for_bound_constexpr<f, VT>;
673 return result;
674 }
675 };
676}
677
678using function_ns::Function;
679
680template<concepts::LanguageFunction T, concepts::Allocator Alloc = platform::DefaultAllocator>
682}
683
684namespace di {
685using function::Function;
687}
#define DI_ASSERT(...)
Definition assert_bool.h:7
Definition function.h:365
constexpr Function(Constexpr< f >, T &&object)
Definition function.h:460
constexpr auto operator()(Args... args) noexcept(is_noexcept) -> R requires(!is_const &&!is_lvalue &&!is_rvalue)
Definition function.h:517
constexpr Function(Constexpr< f >, InPlaceType< T >, std::initializer_list< U > list, Ts &&... args)
Definition function.h:490
constexpr Function(nullptr_t)
Definition function.h:432
auto operator=(Function const &) -> Function &=delete
constexpr auto operator=(Function &&other) -> Function &
Definition function.h:503
constexpr Function(Constexpr< f >, InPlaceType< T >, Ts &&... args)
Definition function.h:482
constexpr Function(Function &&other)
Definition function.h:435
constexpr auto operator()(Args... args) &&noexcept(is_noexcept) -> R requires(!is_const &&is_rvalue)
Definition function.h:545
constexpr auto operator()(Args... args) const &&noexcept(is_noexcept) -> R requires(is_const &&is_rvalue)
Definition function.h:552
constexpr auto operator()(Args... args) const &noexcept(is_noexcept) -> R requires(is_const &&is_lvalue)
Definition function.h:538
constexpr Function(InPlaceType< T >, Ts &&... args)
Definition function.h:467
constexpr Function(InPlaceType< T >, std::initializer_list< U > list, Ts &&... args)
Definition function.h:475
constexpr friend auto operator==(Function const &a, nullptr_t) -> bool
Definition function.h:562
constexpr auto operator=(nullptr_t) -> Function &
Definition function.h:497
constexpr Function(F &&object)
Definition function.h:447
constexpr Function(Constexpr< f >)
Definition function.h:440
friend struct MakeFunction
Definition function.h:371
constexpr auto operator()(Args... args) &noexcept(is_noexcept) -> R requires(!is_const &&is_lvalue)
Definition function.h:531
constexpr auto operator()(Args... args) const noexcept(is_noexcept) -> R requires(is_const &&!is_lvalue &&!is_rvalue)
Definition function.h:524
Definition allocator.h:9
Definition operations.h:11
Definition allocator.h:20
Definition core.h:139
Definition invoke.h:73
Definition language.h:171
Definition operations.h:43
Definition core.h:114
#define DI_TRY(...)
Definition monad_try.h:13
Definition function.h:28
Definition as_bool.h:8
constexpr auto make_function
Definition function.h:681
constexpr auto invoke_r
Definition invoke.h:103
constexpr auto value
Definition value.h:34
detail::ConditionalHelper< value, T, U >::Type Conditional
Definition core.h:88
T::Type Type
Definition core.h:26
Conditional< concepts::LanguageArray< RemoveReference< T > >, RemoveExtent< RemoveReference< T > > *, Conditional< concepts::LanguageFunction< RemoveReference< T > >, AddPointer< RemoveReference< T > >, RemoveCVRef< T > > > Decay
Definition language.h:574
meta::LikeExpected< decltype(di::allocate(util::declval< Alloc & >(), 0, 0)), T > AllocatorResult
Definition allocator.h:25
Conditional< is_const, T const, T > MaybeConst
Definition util.h:9
container::InfallibleAllocator DefaultAllocator
Definition custom.h:39
std::byte Byte
Definition byte.h:63
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
constexpr struct di::util::SwapFunction swap
constexpr auto destroy_at
Definition destroy_at.h:24
constexpr auto construct_at
Definition construct_at.h:27
constexpr auto as_fallible
Definition as_fallible.h:26
constexpr auto try_infallible
Definition try_infallible.h:31
Definition zstring_parser.h:9
constexpr auto allocate_one
Definition allocate_one.h:29
constexpr auto exchange(T &object, U &&new_value) -> T
Definition exchange.h:8
constexpr auto voidify
Definition voidify.h:13
constexpr auto deallocate_one
Definition deallocate_one.h:27
constexpr auto down_cast() -> T *
Definition function.h:311
constexpr ErasedObject(ErasedObject &&other)
Definition function.h:284
ErasedObject(ErasedObject const &)=delete
constexpr auto down_cast() const -> T *
Definition function.h:323
constexpr void init_inline(Args &&... args)
Definition function.h:336
constexpr void reset()
Definition function.h:304
constexpr auto init_out_of_line(Args &&... args)
Definition function.h:346
constexpr ~ErasedObject()
Definition function.h:291
auto operator=(ErasedObject const &) -> ErasedObject &=delete
constexpr auto operator=(ErasedObject &&other) -> ErasedObject &
Definition function.h:294
constexpr auto empty() const -> bool
Definition function.h:303
di::Array< di::Byte, 2 *sizeof(void *)> byte_storage
Definition function.h:227
auto address() -> void *
Definition function.h:230
auto address() const -> void const *
Definition function.h:231
void * pointer
Definition function.h:226
static constexpr bool is_invocable
Definition function.h:165
static constexpr bool is_invocable
Definition function.h:117
static constexpr bool is_invocable
Definition function.h:69
static constexpr bool is_invocable
Definition function.h:53
static constexpr bool is_invocable
Definition function.h:197
static constexpr bool is_invocable
Definition function.h:37
static constexpr bool is_noexcept
Definition function.h:215
static constexpr bool is_noexcept
Definition function.h:87
static constexpr bool is_noexcept
Definition function.h:71
static constexpr bool is_invocable
Definition function.h:181
static constexpr bool is_noexcept
Definition function.h:135
static constexpr bool is_noexcept
Definition function.h:199
static constexpr bool is_noexcept
Definition function.h:39
static constexpr bool is_invocable
Definition function.h:213
static constexpr bool is_noexcept
Definition function.h:55
static constexpr bool is_noexcept
Definition function.h:167
static constexpr bool is_noexcept
Definition function.h:183
static constexpr bool is_invocable
Definition function.h:85
static constexpr bool is_noexcept
Definition function.h:103
static constexpr bool is_noexcept
Definition function.h:151
static constexpr bool is_noexcept
Definition function.h:119
static constexpr bool is_invocable
Definition function.h:149
static constexpr bool is_invocable
Definition function.h:133
static constexpr bool is_invocable
Definition function.h:101
A wrapper for a constexpr value.
Definition core.h:77
Definition in_place_type.h:5
Definition span_fixed_size.h:37