28template <
typename T,
typename E = FormattableError>
53 static_assert(std::is_base_of_v<Error, E>,
"ChainableResult error type E must be derived from Error");
54 error_chain_.push_back(std::make_unique<E>(
error));
69 template <
typename CauseT,
typename CauseE>
71 : result_{std::unexpected{
error}}
73 static_assert(std::is_base_of_v<Error, E>,
"ChainableResult error type E must be derived from Error");
74 error_chain_.push_back(std::make_unique<E>(result_.error()));
89 template <
typename CauseT,
typename CauseE>
92 static_assert(std::is_base_of_v<Error, E>,
"ChainableResult error type E must be derived from Error");
93 error_chain_.push_back(std::make_unique<E>(result_.error()));
113 template <
typename OtherT,
typename OtherE>
119 for (
const std::unique_ptr<Error> &err : cause_result.
chain()) {
120 error_chain_.push_back(err->clone());
129 return result_.has_value();
141 return result_.value();
151 [[nodiscard]]
const T &
value() const &
153 return result_.value();
166 return std::move(result_).value();
176 [[nodiscard]]
const E &
error()
const
178 return result_.error();
189 [[nodiscard]]
const std::vector<std::unique_ptr<Error>> &
chain()
const
199 std::expected<T, E> result_;
200 std::vector<std::unique_ptr<Error>> error_chain_;
252 template <
typename CauseT,
typename CauseE>
268 template <
typename CauseT,
typename CauseE>
303 std::move(*this).Base::value();
326#define PT_TRY_ASSIGN_CHAIN_ERR(var, expr, return_type, ...) \
327 auto var##_result = (expr); \
328 if (!var##_result.has_value()) { \
329 return ChainableResult<return_type>{FormattableError{__VA_ARGS__}, var##_result}; \
331 auto var = std::move(var##_result).value();
349#define PT_TRY_ASSIGN_PASS_ERR(var, expr, return_type) \
350 auto var##_result = (expr); \
351 if (!var##_result.has_value()) { \
352 return ChainableResult<return_type>{FormattableError{}, var##_result}; \
354 auto var = std::move(var##_result).value();
369#define PT_TRY_ASSIGN_PASS_SAME_ERR(var, expr) \
370 auto var##_result = (expr); \
371 if (!var##_result.has_value()) { \
372 return var##_result; \
374 auto var = std::move(var##_result).value();
377#define PT_DETAIL_TRY_CALL_CHAIN_ERR_EXPAND(expr, return_type, counter, ...) \
378 auto pt_try_call_result_##counter = (expr); \
379 if (!pt_try_call_result_##counter.has_value()) { \
380 return ChainableResult<return_type>{FormattableError{__VA_ARGS__}, pt_try_call_result_##counter}; \
384#define PT_DETAIL_TRY_CALL_CHAIN_ERR_IMPL(expr, return_type, counter, ...) \
385 PT_DETAIL_TRY_CALL_CHAIN_ERR_EXPAND(expr, return_type, counter, __VA_ARGS__)
409#define PT_TRY_CALL_CHAIN_ERR(expr, return_type, ...) \
410 PT_DETAIL_TRY_CALL_CHAIN_ERR_IMPL(expr, return_type, __LINE__, __VA_ARGS__)
413#define PT_DETAIL_TRY_CALL_PASS_ERR_EXPAND(expr, return_type, counter) \
414 auto pt_try_call_result_##counter = (expr); \
415 if (!pt_try_call_result_##counter.has_value()) { \
416 return ChainableResult<return_type>{FormattableError{}, pt_try_call_result_##counter}; \
420#define PT_DETAIL_TRY_CALL_PASS_ERR_IMPL(expr, return_type, counter) \
421 PT_DETAIL_TRY_CALL_PASS_ERR_EXPAND(expr, return_type, counter)
442#define PT_TRY_CALL_PASS_ERR(expr, return_type) PT_DETAIL_TRY_CALL_PASS_ERR_IMPL(expr, return_type, __LINE__)
445#define PT_DETAIL_TRY_CALL_PASS_SAME_ERR_EXPAND(expr, counter) \
446 auto pt_try_call_result_##counter = (expr); \
447 if (!pt_try_call_result_##counter.has_value()) { \
448 return pt_try_call_result_##counter; \
452#define PT_DETAIL_TRY_CALL_PASS_SAME_ERR_IMPL(expr, counter) PT_DETAIL_TRY_CALL_PASS_SAME_ERR_EXPAND(expr, counter)
472#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.