11#pragma once
22
3+ #include " common/result.hpp"
34#define I_WANT_RESULT_IMPL
45#include " common/result_impl.hpp"
56#undef I_WANT_RESULT_IMPL
@@ -165,8 +166,7 @@ class Result<T, Errs...> {
165166
166167 return std::visit ([&f](auto && arg) -> ReturnType {
167168 // even though this condition is impossible, it's necessary. Otherwise the
168- // compiler will compile a branch where f is invoked with an unsupported argument
169- // type
169+ // compiler will compile a branch where f is invoked with std::monostate
170170 if constexpr (std::same_as<std::monostate, std::remove_cvref_t <decltype (arg)>>) {
171171 throw std::logic_error (" This exception is unreachable" );
172172 } else {
@@ -175,6 +175,39 @@ class Result<T, Errs...> {
175175 }, std::forward<Self>(self).error );
176176 }
177177
178+ /* *
179+ * @brief invoke a callable with the error, if present
180+ *
181+ * constraints:
182+ * - Callable must be invocable with at least 1 of the possible error types
183+ * - Callable must return void, if invocable
184+ *
185+ * @tparam Self deduced self type
186+ * @tparam F the type of the callable
187+ * @param self the current Result instance
188+ * @param f the callable
189+ */
190+ template <typename Self, typename F>
191+ requires traits::AnyInvocable<Self, F, Errs...>
192+ && traits::AllVoid<traits::inspect_error_return_t <Self, F, Errs>...>
193+ constexpr void inspect_error (this Self&& self, F&& f) {
194+ // if there's no error contained, return
195+ if (!self.has_error ()) {
196+ return ;
197+ }
198+ // otherwise, invoke the callable
199+ std::visit ([&f](auto && arg) {
200+ // even though this condition is impossible, it's necessary. Otherwise the
201+ // compiler will compile a branch where f is invoked with an unsupported argument type
202+ if constexpr (std::same_as<std::monostate, std::remove_cvref_t <decltype (arg)>>
203+ || !traits::Invocable<Self, F, std::remove_cvref_t <decltype (arg)>>) {
204+ throw std::logic_error (" This exception is unreachable" );
205+ } else {
206+ std::invoke (f, std::forward<decltype (arg)>(arg));
207+ }
208+ }, std::forward<Self>(self).error );
209+ }
210+
178211 constexpr operator T&() & {
179212 return value;
180213 }
@@ -336,14 +369,46 @@ class Result<void, Errs...> {
336369
337370 return std::visit ([&f](auto && arg) -> ReturnType {
338371 // even though this condition is impossible, it's necessary. Otherwise the
339- // compiler will compile a branch where f is invoked with an unsupported argument
340- // type
372+ // compiler will compile a branch where f is invoked with std::monostate
341373 if constexpr (std::same_as<std::monostate, std::remove_cvref_t <decltype (arg)>>) {
342374 throw std::logic_error (" This exception is unreachable" );
343375 } else {
344376 return std::invoke (f, std::forward<decltype (arg)>(arg));
345377 }
346378 }, std::forward<Self>(self).error );
347379 }
380+
381+ /* *
382+ * @brief invoke a callable with the error, if present
383+ *
384+ * constraints:
385+ * - Callable must be invocable with at least 1 of the possible error types
386+ * - Callable must return void, if invocable
387+ *
388+ * @tparam Self deduced self type
389+ * @tparam F the type of the callable
390+ * @param self the current Result instance
391+ * @param f the callable
392+ */
393+ template <typename Self, typename F>
394+ requires traits::AnyInvocable<Self, F, Errs...>
395+ && traits::AllVoid<traits::inspect_error_return_t <Self, F, Errs>...>
396+ constexpr void inspect_error (this Self&& self, F&& f) {
397+ // if there's no error contained, return
398+ if (!self.has_error ()) {
399+ return ;
400+ }
401+ // otherwise, invoke the callable
402+ std::visit ([&f](auto && arg) {
403+ // even though this condition is impossible, it's necessary. Otherwise the
404+ // compiler will compile a branch where f is invoked with an unsupported argument type
405+ if constexpr (std::same_as<std::monostate, std::remove_cvref_t <decltype (arg)>>
406+ || !traits::Invocable<Self, F, std::remove_cvref_t <decltype (arg)>>) {
407+ throw std::logic_error (" This exception is unreachable" );
408+ } else {
409+ std::invoke (f, std::forward<decltype (arg)>(arg));
410+ }
411+ }, std::forward<Self>(self).error );
412+ }
348413};
349414} // namespace zest
0 commit comments