@@ -214,6 +214,11 @@ concept IsResult = is_result_v<T>;
214214template <traits::HasSentinel T, traits::IsResultError... Errs>
215215 requires (sizeof ...(Errs) > 0 )
216216class Result {
217+ private:
218+ // helper type
219+ template <typename Self, typename F>
220+ using and_then_return_t = std::invoke_result_t <F, decltype ((std::declval<Self>().m_value))>;
221+
217222 public:
218223 // instead of wrapping the variant in std::optional, we can use std::monostate
219224 std::variant<std::monostate, Errs...> error;
@@ -288,28 +293,26 @@ class Result {
288293 /* *
289294 * @brief and_then monadic function
290295 *
291- * The callable must be able to return any error passed to it.
292- * The callable must return a Result.
296+ * The callable must be able to take the perfectly-forwarded value of this Result instance as an
297+ * argument. The callable must be able to return any error passed to it. The callable must
298+ * return a Result.
293299 *
294300 * @tparam Self deduced self type
295301 * @tparam F the type of the callable
296302 * @param self the current Result instance
297303 * @param f the callable
298304 * @return return type of callable
299305 */
300- template <typename Self, std::invocable<Self> F>
306+ template <typename Self, typename F>
301307 constexpr auto and_then (this Self&& self, F&& f)
302- requires traits::is_result_v<
303- std::invoke_result_t<F, decltype(std::forward<Self>(self).m_value)>>
304- && traits::contains_all_v<
305- std::invoke_result_t<F, decltype(std::forward<Self>(self).m_value)>,
306- typename Self::error_types>
308+ requires std::invocable<F, decltype(std::forward<Self>(self).m_value)>
309+ && traits::is_result_v<and_then_return_t<Self, F>>
310+ && traits::contains_all_v<and_then_return_t<Self, F>, typename Self::error_types>
307311 {
308- using ReturnType = std::invoke_result_t <F, decltype (std::forward<Self>(self).m_value )>;
309312 // if there is an error, return said error immediately
310313 if (self.has_error ()) {
311- return std::visit ([](auto && var) {
312- return ReturnType ( std::forward<decltype (var)>(var) );
314+ return std::visit ([](auto && var) -> and_then_return_t <Self, F> {
315+ return std::forward<decltype (var)>(var);
313316 }, std::forward<Self>(self));
314317 }
315318 // otherwise, invoke the callable and return the result
@@ -359,6 +362,11 @@ operator==(const Result<LhsT, LhsErrs...>& lhs, const Result<RhsT, RhsErrs...>&
359362template <traits::IsResultError... Errs>
360363 requires (sizeof ...(Errs) > 0 )
361364class Result <void , Errs...> {
365+ private:
366+ // helper type
367+ template <typename Self, typename F>
368+ using and_then_return_t = std::invoke_result_t <F, decltype ((std::declval<Self>().m_value))>;
369+
362370 public:
363371 /* *
364372 * @brief Construct a Result with an error.
@@ -407,28 +415,26 @@ class Result<void, Errs...> {
407415 /* *
408416 * @brief and_then monadic function
409417 *
410- * The callable must be able to return any error passed to it.
411- * The callable must return a Result.
418+ * The callable must be able to take the perfectly-forwarded value of this Result instance as an
419+ * argument. The callable must be able to return any error passed to it. The callable must
420+ * return a Result.
412421 *
413422 * @tparam Self deduced self type
414423 * @tparam F the type of the callable
415424 * @param self the current Result instance
416425 * @param f the callable
417426 * @return return type of callable
418427 */
419- template <typename Self, std::invocable<Self> F>
428+ template <typename Self, typename F>
420429 constexpr auto and_then (this Self&& self, F&& f)
421- requires traits::is_result_v<
422- std::invoke_result_t<F, decltype(std::forward<Self>(self).m_value)>>
423- && traits::contains_all_v<
424- std::invoke_result_t<F, decltype(std::forward<Self>(self).m_value)>,
425- typename Self::error_types>
430+ requires std::invocable<F, decltype(std::forward<Self>(self).m_value)>
431+ && traits::is_result_v<and_then_return_t<Self, F>>
432+ && traits::contains_all_v<and_then_return_t<Self, F>, typename Self::error_types>
426433 {
427- using ReturnType = std::invoke_result_t <F, decltype (std::forward<Self>(self).m_value )>;
428434 // if there is an error, return said error immediately
429435 if (self.has_error ()) {
430- return std::visit ([](auto && var) {
431- return ReturnType ( std::forward<decltype (var)>(var) );
436+ return std::visit ([](auto && var) -> and_then_return_t <Self, F> {
437+ return std::forward<decltype (var)>(var);
432438 }, std::forward<Self>(self));
433439 }
434440 // otherwise, invoke the callable and return the result
0 commit comments