8#ifndef SEN_CORE_BASE_RESULT_H
9#define SEN_CORE_BASE_RESULT_H
35 explicit Ok(T theVal)
noexcept(std::is_nothrow_move_constructible_v<T>): val(std::move(theVal)) {}
37 ~Ok() noexcept = default;
38 SEN_COPY_CONSTRUCT(Ok) = default;
39 SEN_MOVE_CONSTRUCT(Ok) = default;
40 SEN_COPY_ASSIGN(Ok) = default;
41 SEN_MOVE_ASSIGN(Ok) = default;
58 explicit Err(E theVal)
noexcept(std::is_nothrow_move_constructible_v<E>): val(std::move(theVal)) {}
60 ~Err() noexcept = default;
61 SEN_COPY_CONSTRUCT(Err) = default;
62 SEN_MOVE_CONSTRUCT(Err) = default;
63 SEN_COPY_ASSIGN(Err) = default;
64 SEN_MOVE_ASSIGN(Err) = default;
77using NonVoidT = std::enable_if_t<!std::is_void_v<U>, U>;
80void resultExpect(
bool value, std::string_view errorMsg = {})
noexcept;
133template <
typename T,
typename E>
136 static_assert(!::std::is_void_v<E>,
"void error type is not allowed");
145 Result(impl::Ok<T>&& ok)
noexcept: value_(std::in_place_type<T>, std::move(ok.val)) {}
149 Result(impl::Err<E>&& err)
noexcept: value_(std::in_place_type<E>, std::move(err.val)) {}
152 SEN_MOVE_CONSTRUCT(
Result) =
default;
153 SEN_COPY_CONSTRUCT(
Result) =
default;
154 SEN_MOVE_ASSIGN(
Result) =
default;
155 SEN_COPY_ASSIGN(
Result) =
default;
160 template <
typename U,
162 std::enable_if_t<std::conjunction_v<std::is_constructible<T, const U&>, std::is_constructible<E, const G&>>,
167 [](const
Result<U, G>& other)
171 return decltype(value_)(std::in_place_type<T>, other.getValue());
174 return decltype(value_)(std::in_place_type<E>, other.
getError());
180 template <
typename U,
182 std::enable_if_t<std::conjunction_v<std::is_constructible<T, U>, std::is_constructible<E, G>>,
bool> =
true>
190 return decltype(value_)(std::in_place_type<T>, std::move(other).getValue());
193 return decltype(value_)(std::in_place_type<E>, std::move(other).getError());
207 [[nodiscard]]
bool isOk() const noexcept {
return std::holds_alternative<T>(value_); }
213 [[nodiscard]]
bool isError() const noexcept {
return std::holds_alternative<E>(value_); }
219 explicit operator bool() const noexcept {
return isOk(); }
226 template <
typename U = T>
227 [[nodiscard]]
const impl::NonVoidT<U>&
getValueOr(
const U& defaultVal)
const noexcept;
236 template <
typename U = T>
237 [[nodiscard]]
const impl::NonVoidT<U>&
getValue() const&
239 impl::resultExpect(
isOk());
240 return std::get<T>(value_);
250 template <
typename U = T>
253 impl::resultExpect(
isOk());
254 return std::get<T>(std::move(value_));
267 return std::get<E>(value_);
272 template <
typename U = T>
276 [[nodiscard]]
const impl::NonVoidT<U>&
expect(std::string_view errorMsg = {})
const noexcept
278 impl::resultExpect(isOk(), errorMsg);
279 return std::get<T>(value_);
283 std::variant<E, T> value_;
294template <
typename T,
typename CleanT = std::decay_t<T>>
295impl::Ok<CleanT>
Ok(T&& val)
noexcept;
298template <
typename E,
typename CleanE = std::decay_t<E>>
299impl::Err<CleanE>
Err(E&& val)
noexcept;
302impl::Ok<void>
Ok() noexcept;
305impl::
Err<
void>
Err() noexcept;
313template <typename T, typename E>
315inline const impl::NonVoidT<U>&
Result<T, E>::
getValueOr(const U& defaultVal) const noexcept
317 if (
const auto* maybeVal = std::get_if<T>(&value_))
329 static_assert(!::std::is_void_v<E>,
"void error type is not allowed");
336 Result(impl::Ok<void>&& arg)
noexcept: ok_(
true)
341 template <
typename T>
348 : ok_(
false), error_(std::move(err.val))
360 bool operator==(const
Result& other) const noexcept {
return ok_ == other.ok_ && error_ == other.error_; }
365 [[nodiscard]]
bool isOk() const noexcept {
return ok_; }
369 explicit operator bool() const noexcept {
return isOk(); }
392 Result(impl::Ok<void>&& arg)
noexcept: ok_(
true)
397 Result(impl::Err<void>&& arg)
noexcept: ok_(
false)
410 bool operator==(const
Result& other) const noexcept {
return ok_ == other.ok_; }
415 [[nodiscard]]
bool isOk() const noexcept {
return ok_; }
419 explicit operator bool() const noexcept {
return isOk(); }
425template <
typename T,
typename CleanT>
426inline impl::Ok<CleanT>
Ok(T&& val)
noexcept
428 return impl::Ok<CleanT>(std::forward<T>(val));
431template <
typename E,
typename CleanE>
432inline impl::Err<CleanE>
Err(E&& val)
noexcept
434 return impl::Err<CleanE>(std::forward<E>(val));
437[[nodiscard]]
inline impl::Ok<void>
Ok() noexcept
442[[nodiscard]]
inline impl::Err<void>
Err() noexcept
Here we define a set of template meta-programming helpers to let the compiler take some decisions bas...
Result(impl::Ok< void > &&arg) noexcept
Definition result.h:336
Result(Result< T, E > &&other) noexcept
Definition result.h:342
void ValueType
Definition result.h:332
const E & getError() const noexcept
Definition result.h:371
Result(Result &&other) noexcept=default
bool operator!=(const Result &other) const noexcept
Definition result.h:362
Result(const Result &other) noexcept=default
E ErrorType
Definition result.h:333
~Result() noexcept=default
bool isError() const noexcept
Definition result.h:367
Result(impl::Err< E > &&err) noexcept
Definition result.h:347
bool isOk() const noexcept
Definition result.h:365
Result(const Result &other) noexcept=default
bool isError() const noexcept
Definition result.h:417
std::monostate ErrorType
Definition result.h:389
bool isOk() const noexcept
Definition result.h:415
Result(impl::Err< void > &&arg) noexcept
Definition result.h:397
bool operator!=(const Result &other) const noexcept
Definition result.h:412
Result(Result &&other) noexcept=default
void ValueType
Definition result.h:388
~Result() noexcept=default
Result(impl::Ok< void > &&arg) noexcept
Definition result.h:392
Result<T, E> is a template type that can be used to return and propagate errors. The intent is to rep...
Definition result.h:135
bool operator!=(const Result &other) const
Definition result.h:200
const impl::NonVoidT< U > & expect(std::string_view errorMsg={}) const noexcept
Extracts the value of the correct result, or terminates the program with a given error message.
Definition result.h:276
bool operator==(const Result &other) const
Definition result.h:199
bool isOk() const noexcept
Used to determine if the result is not an error.
Definition result.h:207
Result(Result< U, G > &&other)
Do a conversion construction from a compatible Result.
Definition result.h:184
const impl::NonVoidT< U > & getValueOr(const U &defaultVal) const noexcept
Used to determine the return value. If the result indicates an error this method will return defaultV...
Definition result.h:315
impl::NonVoidT< U > && getValue() &&
Used to move out the success value, given that there is no error.
Definition result.h:251
const impl::NonVoidT< U > & getValue() const &
Used to determine the success value, given that there is no error.
Definition result.h:237
T ValueType
Definition result.h:139
Result(impl::Ok< T > &&ok) noexcept
Construct a Result that indicates success and that carries a valid return value.
Definition result.h:145
Result(impl::Err< E > &&err) noexcept
Construct a Result that indicates failure and that carries an error value.
Definition result.h:149
E ErrorType
Definition result.h:140
Result(const Result< U, G > &other)
Do a conversion construction from a compatible Result.
Definition result.h:165
const E & getError() const
Used to determine the error value, given that there is an error.
Definition result.h:264
bool isError() const noexcept
Used to determine if the result is an error.
Definition result.h:213
impl::Err< CleanE > Err(E &&val) noexcept
Helper (syntactic sugar) to create Results that indicate error.
Definition result.h:432
impl::Err< void > Err() noexcept
If E is void, use the void specialization of Err.
Definition result.h:442
impl::Ok< void > Ok() noexcept
If T is void, use the void specialization of Ok.
Definition result.h:437
Result< void, std::monostate > BoolResult
True or false result.
Definition result.h:287