diff --git a/include/continuable/continuable-compositions.hpp b/include/continuable/continuable-compositions.hpp index 99e3d00..a60fa6e 100644 --- a/include/continuable/continuable-compositions.hpp +++ b/include/continuable/continuable-compositions.hpp @@ -59,6 +59,74 @@ auto when_all(Continuables&&... continuables) { &&, std::forward(continuables)...); } +/// Connects the given arguments with a sequential logic. +/// All continuables contained inside the given nested pack are +/// invoked one after one. On completion the final handler is called +/// with the aggregated result of all continuables. +/// +/// \param args Arbitrary arguments which are connected. +/// Every type is allowed as arguments, continuables may be +/// contained inside tuple like types (`std::tuple`) +/// or in homogeneous containers such as `std::vector`. +/// Non continuable arguments are preserved and passed +/// to the final result as shown below: +/// ```cpp +/// cti::when_seq( +/// 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) { +/// // ... +/// }); +/// ``` +/// +/// \see continuable_base::operator>> for details. +/// +/// \since 1.1.0 +template +auto when_seq(Args&&... args) { + return detail::composition::apply_composition( + detail::composition::composition_strategy_seq_tag{}, + std::forward(args)...); +} + +/// Connects the given arguments with a sequential logic. +/// The content of the iterator is moved out and converted +/// to a temporary `std::vector` which is then passed to when_seq. +/// +/// ```cpp +/// std::vector> v{cti::make_ready_continuable(0), +/// cti::make_ready_continuable(1)}; +/// +/// cti::when_seq(v.begin(), v.end()) +/// .then([](std::vector r01) { +/// // ... +/// }); +/// ``` +/// +/// \param begin The begin iterator to the range which will be moved out +/// and used as the arguments to the sequential connection +/// +/// \param end The end iterator to the range which will be moved out +/// and used as the arguments to the sequential connection +/// +/// \see when_seq for details. +/// +/// \attention Prefer to invoke when_seq with the whole container the +/// iterators were taken from, since this saves us +/// the creation of a temporary storage. +/// +/// \since 3.0.0 +template < + typename Iterator, + std::enable_if_t::value>* = nullptr> +auto when_seq(Iterator begin, Iterator end) { + return when_seq(detail::range::persist_range(begin, end)); +} + /// Connects the given continuables with an *any* logic. /// /// \param continuables The continuable_base objects to connect. @@ -74,33 +142,6 @@ auto when_any(Continuables&&... continuables) { return CONTINUABLE_FOLD_EXPRESSION( ||, std::forward(continuables)...); } - -/// Connects the given continuables with a *seq* logic. -/// -/// \param args The continuable_base objects to connect. -/// Requires at least 2 objects to connect. -/// -/// \see continuable_base::operator>> for details. -/// -/// \since 1.1.0 -template -auto when_seq(Args&&... args) { - return detail::composition::apply_composition( - detail::composition::composition_strategy_seq_tag{}, - std::forward(args)...); -} - -/// bla -/// -/// \copydetail when_seq -/// -/// \since 3.0.0 -template < - typename Iterator, - std::enable_if_t::value>* = nullptr> -auto when_seq(Iterator begin, Iterator end) { - return when_seq(detail::range::persist_range(begin, end)); -} } // namespace cti #endif // CONTINUABLE_COMPOSITIONS_HPP_INCLUDED diff --git a/include/continuable/detail/composition-remapping.hpp b/include/continuable/detail/composition-remapping.hpp index 345c1a8..76c3fb8 100644 --- a/include/continuable/detail/composition-remapping.hpp +++ b/include/continuable/detail/composition-remapping.hpp @@ -167,6 +167,9 @@ struct result_relocator_mapper { std::decay_t(*index))>>{}, &std::get(*index), &std::get(*result)), 0)...}; + + (void)index; + (void)result; } /// Traverse tuple like container diff --git a/include/continuable/detail/range.hpp b/include/continuable/detail/range.hpp index cc65090..271d7be 100644 --- a/include/continuable/detail/range.hpp +++ b/include/continuable/detail/range.hpp @@ -48,7 +48,7 @@ struct is_iterator::value_type>> : std::true_type {}; -/// Moves to content of the given iterators to a persistent storage +/// Moves the content of the given iterators to a persistent storage template auto persist_range(Iterator begin, Iterator end) { std::vector::value_type> storage; diff --git a/test/playground/test-playground.cpp b/test/playground/test-playground.cpp index 4f65ffe..28b598b 100644 --- a/test/playground/test-playground.cpp +++ b/test/playground/test-playground.cpp @@ -125,13 +125,14 @@ int main(int, char**) { using namespace cti::detail; cti::when_seq( - cti::make_ready_continuable(0, 1), 2, - std::vector>{cti::make_ready_continuable(8), - cti::make_ready_continuable(9)}, - std::make_tuple(std::make_tuple(cti::make_ready_continuable(7)))) - .then([](int a0, int a1, int a2, auto o1, auto o2) { + 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(a0, a1, a2, o1, o2); + util::unused(r0, r1, r2, r34, r5); }); std::vector> v{cti::make_ready_continuable(8), @@ -141,4 +142,12 @@ int main(int, char**) { // ... util::unused(o2); }); + + cti::when_seq() + .then([] { + // ... + }) + .fail([](auto) { + // ... + }); }