EyeAI
Loading...
Searching...
No Matches
Errors.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <format>
4#include <string>
5#include <tl/expected.hpp>
6#include <variant>
7
8namespace tl {
9// when using std::make_format_args, std::forward should not be used
10// NOLINTBEGIN(cppcoreguidelines-missing-std-forward)
11
13template<typename... Args>
14[[nodiscard]] unexpected<std::string>
15unexpected_fmt(const std::format_string<Args...> fmt, Args&&... args) {
16 return unexpected(std::vformat(fmt.get(), std::make_format_args(args...)));
17}
18
19// NOLINTEND(cppcoreguidelines-missing-std-forward)
20} // namespace tl
21
22template<typename T>
23concept HasEqualTo = requires(const T& a, const T& b) {
24 { a.operator==(b) } -> std::same_as<bool>;
25};
26
28template<typename E>
29concept Error = requires(E error) { error.to_string(); } && HasEqualTo<E>;
30
31template<typename... Ts>
32struct Overloads : Ts... {
33 using Ts::operator()...;
34};
35
36template<typename... Ts>
37Overloads(Ts...) -> Overloads<Ts...>;
38
40template<Error... Ts>
41struct [[nodiscard]] CombinedError : public std::variant<Ts...> {
42 using std::variant<Ts...>::variant;
43 using std::variant<Ts...>::operator=;
44 using std::variant<Ts...>::swap;
45
47 [[nodiscard]] std::string to_string() const {
48 return std::visit(
49 [](const auto& ts) -> std::string { return ts.to_string(); }, *this
50 );
51 }
52
54 template<typename... Fs>
55 auto match(Fs&&... fs) const& {
56 const auto visitor = Overloads(std::forward<Fs>(fs)...);
57
58 return std::visit(visitor, *this);
59 }
60
62 template<typename... Fs>
63 auto match(Fs&&... fs) & {
64 const auto visitor = Overloads(std::forward<Fs>(fs)...);
65
66 return std::visit(visitor, *this);
67 }
68
70 template<typename... Fs>
71 auto match(Fs&&... fs) && {
72 const auto visitor = Overloads(std::forward<Fs>(fs)...);
73
74 return std::visit(visitor, std::move(*this));
75 }
76
77 constexpr bool operator==(const CombinedError& other) const {
78 return static_cast<const std::variant<Ts...>&>(*this) ==
79 static_cast<const std::variant<Ts...>&>(other);
80 }
81
82 constexpr bool operator!=(const CombinedError& other) const {
83 return static_cast<const std::variant<Ts...>&>(*this) !=
84 static_cast<const std::variant<Ts...>&>(other);
85 }
86};
87
88#define COMBINED_ERROR(name, ...) \
89 struct [[nodiscard]] name : public CombinedError<__VA_ARGS__> { \
90 using CombinedError::CombinedError; \
91 using CombinedError::operator=; \
92 using CombinedError::operator==; \
93 using CombinedError::operator!=; \
94 using CombinedError::swap; \
95 using CombinedError::match; \
96 using CombinedError::to_string; \
97 }
Overloads(Ts...) -> Overloads< Ts... >
An error is simply a value that can be formatted by calling to_string()
Definition Errors.hpp:29
Definition Errors.hpp:23
Definition Errors.hpp:8
unexpected< std::string > unexpected_fmt(const std::format_string< Args... > fmt, Args &&... args)
same as tl::unexpected, but with formatted error using std::format
Definition Errors.hpp:15
Rust Enum style errors as values helper class, see Error concept.
Definition Errors.hpp:41
auto match(Fs &&... fs) &&
Match on every underlying Error variant.
Definition Errors.hpp:71
constexpr bool operator!=(const CombinedError &other) const
Definition Errors.hpp:82
auto match(Fs &&... fs) const &
Match on every underlying Error variant.
Definition Errors.hpp:55
std::string to_string() const
Formats every underlying Error variant.
Definition Errors.hpp:47
constexpr bool operator==(const CombinedError &other) const
Definition Errors.hpp:77
auto match(Fs &&... fs) &
Match on every underlying Error variant.
Definition Errors.hpp:63
Definition Errors.hpp:32