CeresEngine 0.2.0
A game development framework
Loading...
Searching...
No Matches
MetaArgument.hpp
Go to the documentation of this file.
1//
2// CeresEngine - A game development framework
3//
4// Created by Rogiel Sulzbach.
5// Copyright (c) 2018-2022 Rogiel Sulzbach. All rights reserved.
6//
7
8#pragma once
9
10#include "Box.hpp"
11#include "Type.hpp"
12
13namespace CeresEngine {
14
16 public:
23
27 MetaArgument(T&& value) noexcept;
28
29 [[nodiscard]] bool empty() const noexcept { return mValue.empty(); }
30 template<typename T> [[nodiscard]] T getValue() const;
31
32 private:
33 [[nodiscard]] bool isMetaValue() const { return Type{mValue.getTypeID()}.getDecayTypeID() == getTypeID<Box>(); }
34
35 // rvalue reference
36 template<typename T> [[nodiscard]] T getValue(std::integral_constant<int, 0>) const;
37
38 // lvalue const reference
39 template<typename T> [[nodiscard]] T getValue(std::integral_constant<int, 1>) const;
40
41 // lvalue reference
42 template<typename T> [[nodiscard]] T getValue(std::integral_constant<int, 2>) const;
43
44 // no reference
45 template<typename T> [[nodiscard]] T getValue(std::integral_constant<int, 3>) const;
46
48 mutable Box mValue;
49 mutable Box mDummy;
50 };
51
52 MetaArgument::MetaArgument(const Box& value) noexcept : mRvalue(false), mValue(value) {}
53 MetaArgument::MetaArgument(Box&& value) noexcept : mRvalue(false), mValue(std::move(value)) {}
54 template<typename T> requires(!std::is_same_v<std::decay_t<T>, MetaArgument> && !std::is_same_v<std::decay_t<T>, Box> && !std::is_same_v<std::decay_t<T>, Box>)
55 MetaArgument::MetaArgument(T&& value) noexcept : mRvalue(!std::is_reference_v<T>), mValue{std::ref(value)} {}
56
57 // rvalue reference
58 template<typename T> T MetaArgument::getValue(std::integral_constant<int, 0>) const {
59 using namespace std::literals;
60 using Decay = std::decay_t<T>;
61
62 if(!mRvalue)
63 throw BadMetaValueCast("Incompatible argument cast from LValue to RValue reference");
64
65 auto* value = &mValue;
66 if(isMetaValue())
67 value = &mValue.ref<Box>();
68
69#if defined(DEBUG)
70 auto fromType = Type{value->getTypeID()};
71 auto toType = metaType<Decay>();
72#endif
73
74 if(auto* data = value->data<Decay>())
75 return std::move(*data);
76
77 mDummy = value->to<Decay>();
78 auto* ptr = mDummy.data();
79 return std::move(*static_cast<Decay*>(const_cast<void*>(ptr)));
80 }
81
82 // lvalue const reference
83 template<typename T> T MetaArgument::getValue(std::integral_constant<int, 1>) const {
84 using Decay = std::decay_t<T>;
85
86 const auto* value = &mValue;
87 if(isMetaValue())
88 value = &mValue.cref<Box>();
89
90#if defined(DEBUG)
91 auto fromType = Type{value->getTypeID()};
92 auto toType = metaType<Decay>();
93#endif
94 if(auto* data = value->data<Decay>())
95 return *data;
96
97 mDummy = value->to<Decay>();
98 auto* ptr = mDummy.data();
99 return *static_cast<const Decay*>(ptr);
100 }
101
102 // lvalue reference
103 template<typename T> T MetaArgument::getValue(std::integral_constant<int, 2>) const {
104 using namespace std::literals;
105 using Decay = std::decay_t<T>;
106
107 if(mRvalue)
108 throw BadMetaValueCast("Incompatible argument cast from RValue to non cost LValue reference");
109
110 auto* value = &mValue;
111 if(isMetaValue())
112 value = &mValue.ref<Box>();
113
114#if defined(DEBUG)
115 auto fromType = Type{value->getTypeID()};
116 auto toType = metaType<Decay>();
117#endif
118
119 return value->ref<Decay>();
120 }
121
122 // no reference
123 template<typename T> T MetaArgument::getValue(std::integral_constant<int, 3>) const {
124 using namespace std::literals;
125 using Decay = std::decay_t<T>;
126
127 const auto* value = &mValue;
128 if(isMetaValue())
129 value = &mValue.cref<Box>();
130
131#if defined(DEBUG)
132 auto fromType = Type{value->getTypeID()};
133 auto toType = metaType<Decay>();
134#endif
135
136 return value->to<Decay>();
137 }
138
139 template<typename T> T MetaArgument::getValue() const {
140 using tag_t = std::conditional_t<std::is_rvalue_reference_v<T>, std::integral_constant<int, 0>,
141 std::conditional_t<is_lvalue_const_reference<T>, std::integral_constant<int, 1>,
142 std::conditional_t<std::is_lvalue_reference_v<T>, std::integral_constant<int, 2>, std::integral_constant<int, 3>>>>;
143
144 if(empty()) {
145 throw BadArgumentCast("Empty argument");
146 }
147 return getValue<T>(tag_t{});
148 }
149
150} // namespace CeresEngine
Definition MetaError.hpp:21
Definition MetaError.hpp:22
A value type that can hold any alongside it's type information.
Definition Box.hpp:40
void * data() noexcept
Returns pointer to decayed type.
Definition Box.hpp:260
TypeID getTypeID() const noexcept
Gets the ID of the type held by the variant.
Definition Box.hpp:171
bool empty() const noexcept
Checks if the variant is empty (i.e. holds no value).
Box cref() const &
Gets a reference to the meta value.
T to() const &
Gets the value of the variant as a T.
Definition Box.hpp:332
Box ref() const &
Gets a reference to the meta value.
Definition MetaArgument.hpp:15
Box mDummy
Definition MetaArgument.hpp:49
bool empty() const noexcept
Definition MetaArgument.hpp:29
MetaArgument() noexcept=default
Box mValue
Definition MetaArgument.hpp:48
bool isMetaValue() const
Definition MetaArgument.hpp:33
T getValue() const
Definition MetaArgument.hpp:139
bool mRvalue
Definition MetaArgument.hpp:47
Represents a reflected C++ type. Can be used to get metadata from a C++ type.
Definition Type.hpp:32
TypeID getTypeID() const noexcept
Gets the type ID.
Definition Application.hpp:19
constexpr size_t hash(const T &v)
Generates a hash for the provided type.
Definition Hash.hpp:25
Definition Span.hpp:668