@@ -234,7 +234,7 @@ class Result {
234234 * @param value Value to initialize the result with.
235235 */
236236 template <typename U>
237- requires std::convertible_to<T, U> && (!traits::IsResultError<U >)
237+ requires std::convertible_to<T, U> && (!traits::is_in_pack_v<U, std::monostate, Errs... >)
238238 constexpr Result (U&& value)
239239 : error(std::monostate()),
240240 value(std::forward<U>(value)) {}
@@ -245,7 +245,7 @@ class Result {
245245 * @param error Error to store.
246246 * @note Requires T to have a defined sentinel value (via SentinelValue<T>).
247247 */
248- template <traits::IsResultError E>
248+ template <typename E>
249249 requires traits::is_in_pack_v<E, Errs...>
250250 constexpr Result (E&& error)
251251 : error(std::forward<E>(error)),
@@ -308,15 +308,14 @@ class Result {
308308 constexpr auto and_then (this Self&& self, F&& f)
309309 requires std::invocable<F, decltype(std::forward<Self>(self).value)>
310310 && traits::is_result_v<and_then_return_t<Self, F>>
311- && traits::contains_all_v<
312- typename and_then_return_t<Self, F>::error_types,
313- typename Self::error_types>
311+ && traits::
312+ contains_all_v<typename and_then_return_t<Self, F>::error_types, error_types>
314313 {
315314 // if there is an error, return said error immediately
316315 if (self.has_error ()) {
317316 return std::visit ([](auto && var) -> and_then_return_t <Self, F> {
318317 return std::forward<decltype (var)>(var);
319- }, std::forward<Self>(self));
318+ }, std::forward<Self>(self). error );
320319 }
321320 // otherwise, invoke the callable and return the result
322321 return std::invoke (f, std::forward<Self>(self).value );
@@ -377,8 +376,8 @@ class Result<void, Errs...> {
377376 * @tparam E Error type (must be in Errs).
378377 * @param error Error to store.
379378 */
380- template <traits::IsResultError E>
381- requires traits::is_in_pack_v<E, Errs...>
379+ template <typename E>
380+ requires traits::is_in_pack_v<E, std::monostate, Errs...>
382381 constexpr Result (E&& error)
383382 : error(std::forward<E>(error)) {}
384383
@@ -396,11 +395,11 @@ class Result<void, Errs...> {
396395 * @param self the self object
397396 * @return the error type, wrapped in std::optional
398397 */
399- template <typename Self, traits::IsResultError E>
398+ template <traits::IsResultError E, typename Self >
400399 requires traits::is_in_pack_v<E, Errs...>
401- constexpr auto && get_error(this Self&& self) {
400+ constexpr auto get_error (this Self&& self) {
402401 if (std::holds_alternative<E>(self.error )) {
403- return std::optional (std::holds_alternative <E>(std::forward<Self>(self).error ));
402+ return std::optional<E> (std::get <E>(std::forward<Self>(self).error ));
404403 } else {
405404 return std::optional<E>();
406405 }
@@ -429,103 +428,21 @@ class Result<void, Errs...> {
429428 * @param f the callable
430429 * @return return type of callable
431430 */
432- template <typename Self , typename F >
431+ template <std::invocable F , typename Self >
433432 constexpr auto and_then (this Self&& self, F&& f)
434- requires std::invocable<F, void> && traits::is_result_v<std::invoke_result_t<F, void >>
433+ requires traits::is_result_v<std::invoke_result_t<F>>
435434 && traits::
436- contains_all_v<std::invoke_result_t<F, void>, typename Self:: error_types>
435+ contains_all_v<typename std::invoke_result_t<F>::error_types, error_types>
437436 {
438437 // if there is an error, return said error immediately
439438 if (self.has_error ()) {
440- return std::visit ([](auto && var) -> std::invoke_result_t <F, void > {
439+ return std::visit ([](auto && var) -> std::invoke_result_t <F> {
441440 return std::forward<decltype (var)>(var);
442- }, std::forward<Self>(self));
441+ }, std::forward<Self>(self). error );
443442 }
444443 // otherwise, invoke the callable and return the result
445- return std::invoke (f, std::forward<Self>(self). value );
444+ return std::invoke (f);
446445 }
447446};
448447
449- } // namespace zest
450-
451- namespace zest ::test {
452-
453- // Custom error types
454- struct ErrorA : protected ResultError {};
455-
456- struct ErrorB : protected ResultError {};
457-
458- // Test callables for non-void Results
459- constexpr auto return_rvalue = [](int && x) -> Result<int , ErrorA, ErrorB> {
460- return x * 2 ;
461- };
462- constexpr auto return_lvalue = [](int & x) -> Result<int , ErrorA, ErrorB> {
463- return x * 2 ;
464- };
465- constexpr auto return_const = [](const int & x) -> Result<int , ErrorA, ErrorB> {
466- return x * 2 ;
467- };
468-
469- // Test callables for void Results
470- constexpr auto void_success = []() -> Result<void , ErrorA, ErrorB> {
471- return {};
472- };
473- constexpr auto void_failure = []() -> Result<void , ErrorA, ErrorB> {
474- return ErrorA{};
475- };
476-
477- // Compile-time test runner
478- constexpr bool run_tests () {
479- // Non-void Result tests
480- {
481- // Test lvalue forwarding
482- Result<int , ErrorA, ErrorB> res{42 };
483- auto new_res = res.and_then (return_lvalue);
484- if (new_res.has_error () || new_res.get_value () != 84 )
485- return false ;
486-
487- // Test const lvalue forwarding
488- const Result<int , ErrorA, ErrorB> cres{42 };
489- auto cnew_res = cres.and_then (return_const);
490- if (cnew_res.has_error () || cnew_res.get_value () != 84 )
491- return false ;
492-
493- // Test rvalue forwarding
494- auto rnew_res = Result<int , ErrorA, ErrorB>{42 }.and_then (return_rvalue);
495- if (rnew_res.has_error () || rnew_res.get_value () != 84 )
496- return false ;
497-
498- // Test error propagation
499- Result<int , ErrorA, ErrorB> err_res{ErrorA{}};
500- auto err_new_res = err_res.and_then (return_lvalue);
501- if (!err_new_res.has_error () || !err_new_res.get_error <ErrorA>())
502- return false ;
503- }
504-
505- // Void Result tests
506- {
507- // Test successful chain
508- Result<void , ErrorA, ErrorB> vres;
509- auto vnew_res = vres.and_then (void_success);
510- if (vnew_res.has_error ())
511- return false ;
512-
513- // Test error propagation
514- Result<void , ErrorA, ErrorB> verr_res{ErrorA{}};
515- auto verr_new_res = verr_res.and_then (void_success);
516- if (!verr_new_res.has_error () || !verr_new_res.get_error <ErrorA>())
517- return false ;
518-
519- // Test new error in callback
520- auto vfail_res = Result<void , ErrorA, ErrorB>{}.and_then (void_failure);
521- if (!vfail_res.has_error () || !vfail_res.get_error <ErrorA>())
522- return false ;
523- }
524-
525- return true ;
526- }
527-
528- // Compile-time test execution
529- static_assert (run_tests(), " All tests passed" );
530-
531- } // namespace zest::test
448+ } // namespace zest
0 commit comments