11 template <
typename... Types>
26 template <
typename... DeclaredTypes>
35 template <
typename... Args>
36 explicit CoriError(
const std::string& message, Args&&... args) {
37 static_assert(
sizeof...(Args) == 2 *
sizeof...(DeclaredTypes),
"Incorrect number of arguments provided. Expected a description and a value for each declared type.");
39 m_Payloads.reserve(
sizeof...(DeclaredTypes));
44 if constexpr (
sizeof...(Args) > 0) {
45 ss <<
" | Additional data: (";
46 ProcessArgs<DeclaredTypes...>(ss, std::forward<Args>(args)...);
59 CoriError(
const CoriError& other) noexcept : m_Payloads(other.m_Payloads), m_Message(other.m_Message), m_Seen(other.m_Seen) {
63 CoriError(
CoriError&& other) noexcept : m_Payloads(std::move(other.m_Payloads)), m_Message(std::move(other.m_Message)), m_Seen(other.m_Seen) {
74 const char*
what() const noexcept
override {
78 return m_Message.c_str();
95 static_assert(
Utility::IsInPack<T, DeclaredTypes...>,
"Error: Attempting to Get<T> a type T that was not declared in the CoriError<TypeIsAnalogInPacks...> specialization.");
96 for (
const auto& payload : m_Payloads) {
97 if (payload.type() ==
typeid(T)) {
98 return std::any_cast<T>(payload);
102 throw std::runtime_error(
"Type was declared for CoriError but not provided in this specific error instance.");
110 template <
typename... Types>
requires (
sizeof...(Types) > 1)
111 std::tuple<Types...>
Get()
const {
116 static_assert(!
Utility::HasDuplicates<DeclaredTypes...>,
"CoriError cannot be instantiated with duplicate types in its template parameter list. Each retrievable type must be unique.");
118 mutable std::vector<std::any> m_Payloads;
119 mutable std::string m_Message;
120 mutable bool m_Seen{
false };
123 void ProcessArgs([[maybe_unused]] std::stringstream& ss) {}
125 template <
typename...>
127 void ProcessArgs([[maybe_unused]] std::stringstream& ss) {}
129 template <
typename DeclaredT,
typename... RestT,
typename ValT,
typename... RestArgs>
130 void ProcessArgs(std::stringstream& ss,
const std::string& description, ValT&& value, RestArgs&&... restArgs) {
131 static_assert(std::is_constructible_v<DeclaredT, ValT>,
"A declared error type cannot be constructed from its provided value.");
133 if constexpr (Utility::IsStreamable<DeclaredT>) {
136 ss << description <<
" (" <<
CORI_CLEAN_TYPE_NAME(DeclaredT) <<
"): 'Type is not streamable, you can retrieve it with Get<T>()'";
139 if constexpr (
sizeof...(RestArgs) > 0) {
143 m_Payloads.emplace_back(DeclaredT(std::forward<ValT>(value)));
145 if constexpr (
sizeof...(RestT) > 0) {
146 ProcessArgs<RestT...>(ss, std::forward<RestArgs>(restArgs)...);
158 template <
typename E>
requires(std::is_same_v<std::decay_t<E>, Exceptions> || ...)
162 if (!m_ErrorHandled) {
163 std::visit([](
const auto& e) {
170 other.m_ErrorHandled =
true;
174 other.m_ErrorHandled =
true;
184 [[nodiscard]]
const std::exception*
GetRaw()
const {
185 m_ErrorHandled =
true;
186 return std::visit([](
const auto& e) ->
const std::exception* {
196 template <
typename Visitor>
197 void Visit(Visitor&& visitor)
const & {
198 m_ErrorHandled =
true;
199 std::visit(std::forward<Visitor>(visitor), m_Variant);
206 template <
typename Visitor>
207 void Visit(Visitor&& visitor)
const && {
208 m_ErrorHandled =
true;
209 std::visit(std::forward<Visitor>(visitor), std::move(m_Variant));
218 template <
typename SpecificException,
typename Func>
220 auto* e = std::get_if<SpecificException>(&m_Variant);
223 m_ErrorHandled =
true;
234 template <
typename SpecificException,
typename Func>
236 auto* e = std::get_if<SpecificException>(&m_Variant);
239 m_ErrorHandled =
true;
241 return std::move(*
this);
254 std::variant<Exceptions...> m_Variant;
255 mutable bool m_ErrorHandled{
false };
#define CORI_CLEAN_TYPE_NAME(tn)
#define CORI_CORE_ERROR_TAGGED(...)
CoriError & operator=(CoriError &&other) noexcept=delete
CoriError(const std::string &message, Args &&... args)
Constructs CoriError object and formats the final error message.
CoriError(CoriError &&other) noexcept
void Ignore() const
Explicitly sets the CoriError object into 'seen' state.
CoriError & operator=(const CoriError &other)=delete
std::tuple< Types... > Get() const
The overload of Get method for use with structured bindings.
CoriError(const CoriError &other) noexcept
const char * what() const noexcept override
Returns the formated message and if called the CoriError is considered 'seen'.
T Get() const
Retrieves the value of the type requested from the CoriError object.
PossibleErrors & On(Func &&handler) &
Handles the exception with a callable if it is a specific exception type.
PossibleErrors(PossibleErrors &&other) noexcept
PossibleErrors && On(Func &&handler) &&
Handles the exception with a callable if it is a specific exception type.
const char * GetWhat() const
Simply returns the formated error message held inside the execution object.
PossibleErrors(const PossibleErrors &other) noexcept
void Visit(Visitor &&visitor) const &&
Visits the variant inside of the object with a callable.
const std::exception * GetRaw() const
Returns a pointer to the exception held inside of the object.
void Visit(Visitor &&visitor) const &
Visits the variant inside of the object with a callable.
PossibleErrors & operator=(PossibleErrors &&other) noexcept=delete
PossibleErrors & operator=(const PossibleErrors &other)=delete
All types from Types pack are std::exception or derived from it.
Checks if Types pack has duplicated types.
Checks if T is present in Types pack.
Core systems of the engine are here.