diff --git a/include/continuable/continuable-base.hpp b/include/continuable/continuable-base.hpp index e80e117..c950c60 100644 --- a/include/continuable/continuable-base.hpp +++ b/include/continuable/continuable-base.hpp @@ -800,15 +800,15 @@ constexpr auto make_ready_continuable(FirstResult&& first_result, /// Returns a continuable with the parameterized result which instantly /// resolves the promise with the given error type. /// -/// \tparam FirstArg The first result of the fake signature of the -/// returned continuable. -/// \tparam Rest The rest of the result of the fake signature of the -/// returned continuable. +/// \tparam Signature The fake signature of the returned continuable. /// -/// \since 3.0.0 -template +/// \since 3.0.0 +template constexpr auto make_exceptional_continuable(Exception&& exception) { - return make_continuable( // ... + static_assert(sizeof...(Signature) > 0, + "Requires at least one type for the fake signature!"); + + return make_continuable( // ... [exception = std::forward(exception)](auto&& promise) mutable { std::forward(promise).set_exception( std::move(exception)); diff --git a/include/continuable/continuable-compositions.hpp b/include/continuable/continuable-compositions.hpp index a60fa6e..2ba00bf 100644 --- a/include/continuable/continuable-compositions.hpp +++ b/include/continuable/continuable-compositions.hpp @@ -77,10 +77,10 @@ auto when_all(Continuables&&... continuables) { /// std::vector>{cti::make_ready_continuable(3), /// cti::make_ready_continuable(4)}, /// std::make_tuple(std::make_tuple(cti::make_ready_continuable(5)))) -/// .then([](int r0, int r1, int r2, std::vector r34, -/// std::tuple> r5) { -/// // ... -/// }); +/// .then([](int r0, int r1, int r2, std::vector r34, +/// std::tuple> r5) { +/// // ... +/// }); /// ``` /// /// \see continuable_base::operator>> for details. diff --git a/include/continuable/detail/composition-seq.hpp b/include/continuable/detail/composition-seq.hpp index a40872a..fbf832d 100644 --- a/include/continuable/detail/composition-seq.hpp +++ b/include/continuable/detail/composition-seq.hpp @@ -182,18 +182,33 @@ public: // Continue the asynchronous sequential traversal next(); }) + .fail([me = this->shared_from_this()](types::error_type exception) { + // Abort the traversal when an error occurred + std::move(me->data_.callback)(types::dispatch_error_tag{}, + std::move(exception)); + }) .done(); } + void finalize(traits::identity) { + std::move(data_.callback)(); + } template - void operator()(async_traverse_complete_tag, T&& /*pack*/) { - // Remove void result guard tags + void finalize(traits::identity) { auto cleaned = map_pack(remapping::unpack_result_guards{}, std::move(data_.result)); // Call the final callback with the cleaned result traits::unpack(std::move(cleaned), std::move(data_.callback)); } + + template + void operator()(async_traverse_complete_tag, T&& /*pack*/) { + // Guard the final result against void + using result_t = decltype( + map_pack(remapping::unpack_result_guards{}, std::move(data_.result))); + finalize(traits::identity{}); + } }; } // namespace seq diff --git a/test/playground/test-playground.cpp b/test/playground/test-playground.cpp index 28b598b..656599a 100644 --- a/test/playground/test-playground.cpp +++ b/test/playground/test-playground.cpp @@ -143,11 +143,30 @@ int main(int, char**) { util::unused(o2); }); - cti::when_seq() + cti::when_seq(cti::make_ready_continuable()) // ... .then([] { // ... - }) + }); + + cti::when_seq() // ... + .then([] { + // ... + }); + + cti::when_seq(cti::make_exceptional_continuable(std::error_condition{})) .fail([](auto) { // ... }); + + /*composition::apply_composition( + composition::composition_strategy_all_tag{}, + cti::make_ready_continuable(0, 1), 2, //< See this plain value + std::vector>{cti::make_ready_continuable(3), + cti::make_ready_continuable(4)}, + std::make_tuple(std::make_tuple(cti::make_ready_continuable(5)))) + .then([](int r0, int r1, int r2, std::vector r34, + std::tuple> r5) { + // ... + util::unused(r0, r1, r2, r34, r5); + });*/ }