30template <
typename T,
typename E = FormattableError>
59 static_assert(std::is_base_of_v<Error, E>,
"ChainableResult error type E must be derived from Error");
60 error_chain_.push_back(std::make_unique<E>(
error));
77 template <
typename CauseT,
typename CauseE>
79 : result_{std::unexpected{
error}}
81 static_assert(std::is_base_of_v<Error, E>,
"ChainableResult error type E must be derived from Error");
82 error_chain_.push_back(std::make_unique<E>(result_.error()));
99 template <
typename CauseT,
typename CauseE>
102 static_assert(std::is_base_of_v<Error, E>,
"ChainableResult error type E must be derived from Error");
103 error_chain_.push_back(std::make_unique<E>(result_.error()));
127 template <
typename OtherT,
typename OtherE>
133 for (
const std::unique_ptr<Error> &err : cause_result.
chain()) {
134 error_chain_.push_back(err->clone());
145 return result_.has_value();
159 return result_.value();
171 [[nodiscard]]
const T &
value() const &
173 return result_.value();
188 return std::move(result_).value();
200 [[nodiscard]]
const E &
error()
const
202 return result_.error();
215 [[nodiscard]]
const std::vector<std::unique_ptr<Error>> &
chain()
const
225 std::expected<T, E> result_;
226 std::vector<std::unique_ptr<Error>> error_chain_;
286 template <
typename CauseT,
typename CauseE>
304 template <
typename CauseT,
typename CauseE>
345 std::move(*this).Base::value();
370#define PT_TRY_ASSIGN_CHAIN_ERR(var, expr, return_type, ...) \
371 auto var##_result = (expr); \
372 if (!var##_result.has_value()) { \
373 return ChainableResult<return_type>{FormattableError{__VA_ARGS__}, var##_result}; \
375 auto var = std::move(var##_result).value();
395#define PT_TRY_ASSIGN_PASS_ERR(var, expr, return_type) \
396 auto var##_result = (expr); \
397 if (!var##_result.has_value()) { \
398 return ChainableResult<return_type>{FormattableError{}, var##_result}; \
400 auto var = std::move(var##_result).value();
417#define PT_TRY_ASSIGN_PASS_SAME_ERR(var, expr) \
418 auto var##_result = (expr); \
419 if (!var##_result.has_value()) { \
420 return var##_result; \
422 auto var = std::move(var##_result).value();
425#define PT_DETAIL_TRY_CALL_CHAIN_ERR_EXPAND(expr, return_type, counter, ...) \
426 auto pt_try_call_result_##counter = (expr); \
427 if (!pt_try_call_result_##counter.has_value()) { \
428 return ChainableResult<return_type>{FormattableError{__VA_ARGS__}, pt_try_call_result_##counter}; \
432#define PT_DETAIL_TRY_CALL_CHAIN_ERR_IMPL(expr, return_type, counter, ...) \
433 PT_DETAIL_TRY_CALL_CHAIN_ERR_EXPAND(expr, return_type, counter, __VA_ARGS__)
459#define PT_TRY_CALL_CHAIN_ERR(expr, return_type, ...) \
460 PT_DETAIL_TRY_CALL_CHAIN_ERR_IMPL(expr, return_type, __LINE__, __VA_ARGS__)
463#define PT_DETAIL_TRY_CALL_PASS_ERR_EXPAND(expr, return_type, counter) \
464 auto pt_try_call_result_##counter = (expr); \
465 if (!pt_try_call_result_##counter.has_value()) { \
466 return ChainableResult<return_type>{FormattableError{}, pt_try_call_result_##counter}; \
470#define PT_DETAIL_TRY_CALL_PASS_ERR_IMPL(expr, return_type, counter) \
471 PT_DETAIL_TRY_CALL_PASS_ERR_EXPAND(expr, return_type, counter)
494#define PT_TRY_CALL_PASS_ERR(expr, return_type) PT_DETAIL_TRY_CALL_PASS_ERR_IMPL(expr, return_type, __LINE__)
497#define PT_DETAIL_TRY_CALL_PASS_SAME_ERR_EXPAND(expr, counter) \
498 auto pt_try_call_result_##counter = (expr); \
499 if (!pt_try_call_result_##counter.has_value()) { \
500 return pt_try_call_result_##counter; \
504#define PT_DETAIL_TRY_CALL_PASS_SAME_ERR_IMPL(expr, counter) PT_DETAIL_TRY_CALL_PASS_SAME_ERR_EXPAND(expr, counter)
526#define PT_TRY_CALL_PASS_SAME_ERR(expr) PT_DETAIL_TRY_CALL_PASS_SAME_ERR_IMPL(expr, __LINE__)
ChainableResult(const ChainableResult< CauseT, CauseE > &cause_result)
Constructs a ChainableResult by chaining an existing error chain with a default-constructed error.
void value() &&
Accesses the void success value (rvalue version).
ChainableResult()
Default constructor creating a successful void result.
void value() &
Accesses the void success value.
ChainableResult(const E &error, const ChainableResult< CauseT, CauseE > &cause_result)
Constructs a ChainableResult by chaining a new error with an existing error chain.
void value() const &
Accesses the void success value (const version).
ChainableResult(const E &error)
Constructs a ChainableResult from an error value.
A result type that maintains a chainable sequence of errors for debugging and error reporting.
ChainableResult(ChainableResult &&)=default
ChainableResult & operator=(const ChainableResult &)=delete
const std::vector< std::unique_ptr< Error > > & chain() const
Returns the complete error chain.
ChainableResult & operator=(ChainableResult &&)=default
const T & value() const &
Returns a const reference to the contained success value.
ChainableResult(const ChainableResult< CauseT, CauseE > &cause_result)
Constructs a ChainableResult by chaining an existing error chain with a default-constructed error.
T & value() &
Returns a reference to the contained success value.
ChainableResult(const E &error)
Constructs a ChainableResult from an error value.
T && value() &&
Returns an rvalue reference to the contained success value.
ChainableResult(T value)
Constructs a ChainableResult from a success value.
bool has_value() const
Checks whether the result contains a success value.
ChainableResult(const ChainableResult &)=delete
ChainableResult()=default
void add_cause(const ChainableResult< OtherT, OtherE > &cause_result)
Adds all errors from another ChainableResult's chain to this result's chain.
const E & error() const
Returns a const reference to the immediate error.
ChainableResult(const E &error, const ChainableResult< CauseT, CauseE > &cause_result)
Constructs a ChainableResult by chaining a new error with an existing error chain.
void assert_or_panic(bool condition, const StringViewSourceLoc &s)
Conditionally panics if the given condition is false.