Skip to content

Commit c0408dc

Browse files
committed
use doxygen documentation in result.hpp
1 parent 953874f commit c0408dc

File tree

1 file changed

+111
-58
lines changed

1 file changed

+111
-58
lines changed

include/common/result.hpp

Lines changed: 111 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -9,41 +9,53 @@
99

1010
namespace zest {
1111

12-
// custom error types inherit from the ResultError class, which enforces that custom error types
13-
// have some shared functionality.
12+
/**
13+
* @brief Base class for custom error types used in the Result class.
14+
* @details Enforces stacktrace and timestamp functionality for derived error types.
15+
*/
1416
class ResultError {
1517
public:
16-
// since this constructor has no arguments, it'll be called implicitly by the constructor of any
17-
// child class.
18+
/**
19+
* @brief Construct a new ResultError object.
20+
* @details Captures the current stacktrace and system time automatically.
21+
*/
1822
ResultError()
1923
: stacktrace(std::stacktrace::current()),
2024
time(std::chrono::system_clock::now()) {}
2125

22-
std::stacktrace stacktrace;
23-
std::chrono::time_point<std::chrono::system_clock> time;
26+
std::stacktrace stacktrace; ///< Captured stacktrace at error creation.
27+
std::chrono::time_point<std::chrono::system_clock> time; ///< Timestamp of error creation.
2428
};
2529

26-
// Some primitive types such as float, double, etc may have a standardized "sentinel" value.
27-
// For example, a function that returns a float may return INFINITY if an error occurs.
28-
// Usually the maximum value of the type is returned if there is an error.
29-
// This trait helps simplify DX.
30-
// This trait can also be specialized for custom types (e.g unitized types)
30+
/**
31+
* @brief Trait to define a "sentinel" value for types indicating an error state.
32+
* @tparam T Type to provide a sentinel value for.
33+
* @note Specialize this template for custom types if needed.
34+
*/
3135
template<typename T>
3236
class SentinelValue;
3337

34-
// concept which can be used to determine if a type has a sentinel value
38+
/**
39+
* @brief Concept to check if a type has a defined sentinel value.
40+
* @tparam T Type to check.
41+
*/
3542
template<typename T>
3643
concept Sentinel = requires(const T& val) { SentinelValue<T>::value; };
3744

38-
// templated variable which can be used to simplify usage of HasSentinel
45+
/**
46+
* @brief Helper variable to simplify access to a type's sentinel value.
47+
* @tparam T Type with a defined sentinel (must satisfy Sentinel concept).
48+
*/
3949
template<Sentinel T>
4050
constexpr T sentinel_v = SentinelValue<T>::value;
4151

42-
// partial specialization for HasSentinel.
43-
// any integral type (e.g double, int, uint8, etc) has a sentinel value equal to its maximum value.
44-
// floating-point numbers with infinity support have sentinel values equal to infinity.
52+
/**
53+
* @brief Partial specialization of SentinelValue for integral and floating-point types.
54+
* @tparam T Integral or floating-point type.
55+
* @details Uses infinity for floating-point types if available; otherwise uses max value.
56+
*/
4557
template<typename T>
46-
requires (std::integral<T> || std::floating_point<T>)
58+
requires(std::integral<T> || std::floating_point<T>)
4759
class SentinelValue<T> {
4860
public:
4961
static constexpr T get() {
@@ -54,49 +66,60 @@ class SentinelValue<T> {
5466
}
5567
}
5668

57-
static constexpr T value = get();
69+
static constexpr T value = get(); ///< Precomputed sentinel value for type T.
5870
};
5971

60-
// Result class.
61-
// An alternative to std::expected, where an expected value can be contained alongside an unexpected
62-
// error value.
63-
// This means that Result will always contain an expected value.
64-
// Therefore, if the user does not check if a function returned an error, an exception will NOT be
65-
// thrown, and therefore the thread won't crash.
66-
// Constraint: requires at least 1 possible Error type
67-
// Constraint: Error types must inherit from ResultError
72+
/**
73+
* @brief Result class for expected value or error handling (similar to std::expected).
74+
* @tparam T Type of the expected value.
75+
* @tparam Errs List of possible error types (must inherit from ResultError).
76+
* @note Errors are stored in a variant, and the value is always initialized.
77+
*/
6878
template<typename T, typename... Errs>
6979
requires(sizeof...(Errs) > 0) && (std::derived_from<Errs, ResultError> && ...)
7080
class Result {
7181
public:
72-
// Construct a Result with a value and no error value.
73-
// Constraint: type T can be constructed from type U
82+
/**
83+
* @brief Construct a Result with a normal value (no error).
84+
* @tparam U Type convertible to T.
85+
* @param value Value to initialize the result with.
86+
*/
7487
template<typename U>
7588
requires std::constructible_from<T, U>
7689
constexpr Result(U&& value)
7790
: error(std::monostate()),
7891
value(std::forward<U>(value)) {}
7992

80-
// Construct a Result with a value and an error value.
81-
// Constraint: type T can be constructed from type U
82-
// Constraint: E in Errs
93+
/**
94+
* @brief Construct a Result with a value and an error.
95+
* @tparam U Type convertible to T.
96+
* @tparam E Error type (must be in Errs).
97+
* @param value Value to store.
98+
* @param error Error to store.
99+
*/
83100
template<typename U, typename E>
84101
requires std::constructible_from<T, U> && (std::same_as<std::remove_cvref<E>, Errs> || ...)
85102
constexpr Result(U&& value, E&& error)
86103
: value(std::forward<U>(value)),
87104
error(std::forward<E>(error)) {}
88105

89-
// Construct a Result with an error, initializing the normal value to its sentinel value.
90-
// Constraint: type T has a sentinel value
91-
// Constraint: E in Errs
106+
/**
107+
* @brief Construct a Result with an error, initializing the value to its sentinel.
108+
* @tparam E Error type (must be in Errs).
109+
* @param error Error to store.
110+
* @note Requires T to have a defined sentinel value (via SentinelValue<T>).
111+
*/
92112
template<typename E>
93113
requires Sentinel<T> && (std::same_as<std::remove_cvref<E>, Errs> || ...)
94114
constexpr Result(E&& error)
95115
: error(std::forward<E>(error)),
96116
value(sentinel_v<T>) {}
97117

98-
// Get the given error type, if it exists
99-
// Constraint: E in Errs
118+
/**
119+
* @brief Get an error of type E if present (const-qualified overload).
120+
* @tparam E Error type to retrieve.
121+
* @return std::optional<E> Contains the error if present; otherwise nullopt.
122+
*/
100123
template<typename E>
101124
requires(std::same_as<E, Errs> || ...)
102125
constexpr std::optional<E> get() const& {
@@ -107,8 +130,11 @@ class Result {
107130
}
108131
}
109132

110-
// Get the given error type, if it exists
111-
// Constraint: E in Errs
133+
/**
134+
* @brief Get an error of type E if present (rvalue overload).
135+
* @tparam E Error type to retrieve.
136+
* @return std::optional<E> Contains the error if present; otherwise nullopt.
137+
*/
112138
template<typename E>
113139
requires(std::same_as<E, Errs> || ...)
114140
constexpr std::optional<E> get() && {
@@ -119,63 +145,86 @@ class Result {
119145
}
120146
}
121147

122-
// get the normal value
148+
/**
149+
* @brief Get the stored value (const-qualified overload).
150+
* @return T Copy of the stored value.
151+
*/
123152
template<typename U = T>
124153
requires std::same_as<U, T>
125154
constexpr T get() const& {
126155
return value;
127156
}
128157

129-
// get the normal value
158+
/**
159+
* @brief Get the stored value (rvalue overload).
160+
* @return T Moved value.
161+
*/
130162
template<typename U = T>
131163
requires std::same_as<U, T>
132164
constexpr T get() && {
133165
return std::move(value);
134166
}
135167

136-
// implicit conversion operator
168+
/**
169+
* @brief Implicit conversion to the stored value (const-qualified).
170+
*/
137171
constexpr operator T() const& {
138172
return value;
139173
};
140174

141-
// implicit conversion operator
175+
/**
176+
* @brief Implicit conversion to the stored value (rvalue).
177+
*/
142178
constexpr operator T() && {
143179
return std::move(value);
144180
}
145181

146-
// comparison operator overload
182+
/**
183+
* @brief Equality comparison operator.
184+
* @tparam U Type of the other result's value.
185+
* @tparam Es Other result's error types.
186+
* @param other Result to compare with.
187+
* @return true If values are equal.
188+
*/
147189
template<typename U, typename... Es>
148190
requires std::equality_comparable_with<T, U>
149191
constexpr bool operator==(const Result<U, Es...>& other) {
150192
return value == other.value;
151193
}
152194

153-
// a variant that could contain any of the specified error types
154-
std::variant<std::monostate, Errs...> error;
155-
// the normal value
156-
T value;
195+
std::variant<std::monostate, Errs...> error; ///< Variant holding an error or monostate.
196+
T value; ///< The stored value (always initialized).
157197
};
158198

159-
// Result specialization for a value of type void, which would otherwise be impossible.
160-
// This specialization simply does not hold a "normal" value
161-
// Constraint: requires at least 1 possible Error type
162-
// Constraint: Error types must inherit from ResultError
199+
/**
200+
* @brief Result specialization for void value type (no stored value).
201+
* @tparam Errs List of possible error types (must inherit from ResultError).
202+
*/
163203
template<typename... Errs>
164204
requires(sizeof...(Errs) > 0) && (std::derived_from<Errs, ResultError> && ...)
165205
class Result<void, Errs...> {
166206
public:
167-
// construct with an error value
207+
/**
208+
* @brief Construct a Result with an error.
209+
* @tparam E Error type (must be in Errs).
210+
* @param error Error to store.
211+
*/
168212
template<typename E>
169213
requires(std::same_as<std::remove_cvref<E>, Errs> || ...)
170214
constexpr Result(E&& error)
171215
: error(std::forward<E>(error)) {}
172216

173-
// construct with no error value
217+
/**
218+
* @brief Construct a Result with no error (success state).
219+
*/
174220
constexpr Result()
175221
: error(std::monostate()) {}
176222

177-
// Get the given error type, if it exists
178-
// Constraint: E in Errs
223+
/**
224+
* @brief Get an error of type E if present (const-qualified overload).
225+
* @tparam E Error type to retrieve.
226+
* @return std::optional<E> Contains the error if present; otherwise nullopt.
227+
*/
179228
template<typename E>
180229
requires(std::same_as<E, Errs> || ...)
181230
constexpr std::optional<E> get() const& {
@@ -186,8 +235,11 @@ class Result<void, Errs...> {
186235
}
187236
}
188237

189-
// Get the given error type, if it exists
190-
// Constraint: E in Errs
238+
/**
239+
* @brief Get an error of type E if present (rvalue overload).
240+
* @tparam E Error type to retrieve.
241+
* @return std::optional<E> Contains the error if present; otherwise nullopt.
242+
*/
191243
template<typename E>
192244
requires(std::same_as<E, Errs> || ...)
193245
constexpr std::optional<E> get() && {
@@ -198,6 +250,7 @@ class Result<void, Errs...> {
198250
}
199251
}
200252

201-
std::variant<std::monostate, Errs...> error;
253+
std::variant<std::monostate, Errs...> error; ///< Variant holding an error or monostate.
202254
};
255+
203256
} // namespace zest

0 commit comments

Comments
 (0)