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()));
106 template <
typename OtherT,
typename OtherE>
112 for (
const std::unique_ptr<Error> &err : cause_result.
chain()) {
113 error_chain_.push_back(err->clone());
124 return result_.has_value();
138 return result_.value();
150 [[nodiscard]]
const T &
value() const &
152 return result_.value();
167 return std::move(result_).value();
179 [[nodiscard]]
const E &
error()
const
181 return result_.error();
194 [[nodiscard]]
const std::vector<std::unique_ptr<Error>> &
chain()
const
204 std::expected<T, E> result_;
205 std::vector<std::unique_ptr<Error>> error_chain_;
265 template <
typename CauseT,
typename CauseE>
307 std::move(*this).Base::value();
331#define PT_TRY_ASSIGN_CHAIN_ERR(var, expr, msg, return_type) \
332 auto var##_result = (expr); \
333 if (!var##_result.has_value()) { \
334 return ChainableResult<return_type>{FormattableError{msg}, var##_result}; \
336 auto var = std::move(var##_result).value();
356#define PT_TRY_ASSIGN_PASS_ERR(var, expr, return_type) \
357 auto var##_result = (expr); \
358 if (!var##_result.has_value()) { \
359 return ChainableResult<return_type>{FormattableError{}, var##_result}; \
361 auto var = std::move(var##_result).value();
378#define PT_TRY_ASSIGN_PASS_SAME_ERR(var, expr) \
379 auto var##_result = (expr); \
380 if (!var##_result.has_value()) { \
381 return var##_result; \
383 auto var = std::move(var##_result).value();
386#define PT_DETAIL_TRY_CALL_CHAIN_ERR_EXPAND(expr, msg, return_type, counter) \
387 auto pt_try_call_result_##counter = (expr); \
388 if (!pt_try_call_result_##counter.has_value()) { \
389 return ChainableResult<return_type>{FormattableError{msg}, pt_try_call_result_##counter}; \
393#define PT_DETAIL_TRY_CALL_CHAIN_ERR_IMPL(expr, msg, return_type, counter) \
394 PT_DETAIL_TRY_CALL_CHAIN_ERR_EXPAND(expr, msg, return_type, counter)
413#define PT_TRY_CALL_CHAIN_ERR(expr, msg, return_type) \
414 PT_DETAIL_TRY_CALL_CHAIN_ERR_IMPL(expr, msg, return_type, __COUNTER__)
417#define PT_DETAIL_TRY_CALL_PASS_ERR_EXPAND(expr, return_type, counter) \
418 auto pt_try_call_result_##counter = (expr); \
419 if (!pt_try_call_result_##counter.has_value()) { \
420 return ChainableResult<return_type>{FormattableError{}, pt_try_call_result_##counter}; \
424#define PT_DETAIL_TRY_CALL_PASS_ERR_IMPL(expr, return_type, counter) \
425 PT_DETAIL_TRY_CALL_PASS_ERR_EXPAND(expr, return_type, counter)
446#define PT_TRY_CALL_PASS_ERR(expr, return_type) PT_DETAIL_TRY_CALL_PASS_ERR_IMPL(expr, return_type, __COUNTER__)
449#define PT_DETAIL_TRY_CALL_PASS_SAME_ERR_EXPAND(expr, counter) \
450 auto pt_try_call_result_##counter = (expr); \
451 if (!pt_try_call_result_##counter.has_value()) { \
452 return pt_try_call_result_##counter; \
456#define PT_DETAIL_TRY_CALL_PASS_SAME_ERR_IMPL(expr, counter) PT_DETAIL_TRY_CALL_PASS_SAME_ERR_EXPAND(expr, counter)
476#define PT_TRY_CALL_PASS_SAME_ERR(expr) PT_DETAIL_TRY_CALL_PASS_SAME_ERR_IMPL(expr, __COUNTER__)
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() &&
Accesses the void success value (rvalue version).
ChainableResult()
Default constructor creating a successful void result.
ChainableResult(const E &error)
Constructs a ChainableResult from an error value.
void value() &
Accesses the void success value.
void value() const &
Accesses the void success value (const version).
A result type that maintains a chainable sequence of errors for debugging and error reporting.
ChainableResult(ChainableResult &&)=default
ChainableResult(const ChainableResult &)=delete
void add_cause(const ChainableResult< OtherT, OtherE > &cause_result)
Adds all errors from another ChainableResult's chain to this result's chain.
const std::vector< std::unique_ptr< Error > > & chain() const
Returns the complete error chain.
ChainableResult()=default
const E & error() const
Returns a const reference to the immediate error.
ChainableResult(const E &error)
Constructs a ChainableResult from an error value.
ChainableResult(T value)
Constructs a ChainableResult from a success value.
ChainableResult & operator=(ChainableResult &&)=default
const T & value() const &
Returns a const reference to the contained success value.
bool has_value() const
Checks whether the result contains a 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.
T && value() &&
Returns an rvalue reference to the contained success value.
ChainableResult & operator=(const ChainableResult &)=delete
T & value() &
Returns a reference to the contained success value.
void assert_or_panic(const bool condition, const StringViewSourceLoc &s)
Conditionally panics if the given condition is false.