LeviLamina
Loading...
Searching...
No Matches
EventVariantImpl.h
1#pragma once
2
3#include "mc/_HeaderOutputPredefine.h"
4#include <type_traits>
5#include <variant>
6
7namespace Details {
8template <typename T>
9class ValueOrRef {
10public:
11 ValueOrRef(std::reference_wrapper<T> ref) : is_pointer_(true), variant_(&ref.get()) {}
12
13 ~ValueOrRef() {
14 if (!is_pointer_) {
15 variant_.value.~T();
16 }
17 }
18
19 ValueOrRef(const ValueOrRef& other) = delete;
20
21 ValueOrRef(ValueOrRef&& other) noexcept
22 : is_pointer_(other.is_pointer_),
23 variant_(other.is_pointer_ ? Variant(other.variant_.pointer) : Variant(std::move(other.variant_.value))) {}
24
25 T& value() noexcept { return is_pointer_ ? *variant_.pointer : variant_.value; }
26
27 const T& value() const noexcept { return is_pointer_ ? *variant_.pointer : variant_.value; }
28
29private:
30 ValueOrRef(T value) : is_pointer_(false), variant_(std::move(value)) {}
31
32 union Variant {
33 Variant() : pointer(nullptr) {}
34 Variant(T* ptr) : pointer(ptr) {}
35 Variant(T&& val) : value(std::move(val)) {}
36 ~Variant() {}
37 T* pointer;
38 T value;
39 };
40 Variant variant_;
41 const bool is_pointer_;
42};
43} // namespace Details
44
45template <typename... Xs>
47 using variant_t = std::variant<Details::ValueOrRef<Xs>...>;
48
49public:
50 template <typename T>
51 EventVariantImpl(std::reference_wrapper<T> event) : variant_{std::in_place_type<Details::ValueOrRef<T>>, event} {}
52
54 : variant_(const_cast<EventVariantImpl&>(other).visit([](auto&& arg) -> variant_t {
55 using T = std::remove_reference_t<decltype(arg.value())>;
56 if constexpr (std::is_const_v<T>) {
57 return variant_t{std::in_place_type<Details::ValueOrRef<T>>, std::cref(arg.value())};
58 } else {
59 return variant_t{std::in_place_type<Details::ValueOrRef<T>>, std::ref(arg.value())};
60 }
61 })) {}
62
63 template <typename F>
64 auto visit(F&& visitor) {
65 return std::visit(std::forward<F>(visitor), variant_);
66 }
67
68 template <typename F>
69 auto visit(F&& visitor) const {
70 return std::visit(std::forward<F>(visitor), variant_);
71 }
72
73private:
74 variant_t variant_;
75};
76
77template <typename... Events>
79
80template <typename... Events>
81using MutableEventVariant = EventVariantImpl<Events...>;
Definition EventVariantImpl.h:9
Definition EventVariantImpl.h:46