diff --git a/Readme.md b/Readme.md index 340a03b..c2c9be9 100644 --- a/Readme.md +++ b/Readme.md @@ -265,10 +265,10 @@ Although the library has progressed very far there are still some candies missin ``` -- [ ] The **sequential/pipe operator** which invokes continuables sequentially and calls the callback with all results: +- [x] The **sequential operator** which invokes continuables sequentially and calls the callback with all results: ```c++ - (http_request("github.com") | http_request("travis-ci.org") | http_request("atom.io")) + (http_request("github.com") >> http_request("travis-ci.org") >> http_request("atom.io")) .then([](std::string github, std::string travis, std::string atom) { // The requests are done sequentially and the callback is called // with the response of github, travis and atom as soon as atom has responded. diff --git a/cmake/compiler/msvc.cmake b/cmake/compiler/msvc.cmake index 85dff5d..4e17756 100644 --- a/cmake/compiler/msvc.cmake +++ b/cmake/compiler/msvc.cmake @@ -14,8 +14,7 @@ if (PLATFORM EQUAL 64) add_definitions("-D_WIN64") endif() -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /MP") -set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /bigobj") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /MP /bigobj") if (TESTS_NO_EXCEPTIONS) add_definitions(-D_HAS_EXCEPTIONS=0) diff --git a/include/continuable/continuable-base.hpp b/include/continuable/continuable-base.hpp index 4bbebfb..a45ce6a 100644 --- a/include/continuable/continuable-base.hpp +++ b/include/continuable/continuable-base.hpp @@ -422,6 +422,13 @@ inline auto or_folding() { std::forward(right); }; } +/// Returns a folding function using operator `>>`. +inline auto seq_folding() { + return [](auto&& left, auto&& right) { + return std::forward(left) >> + std::forward(right); + }; +} /// Deduces to a std::false_type template @@ -927,7 +934,7 @@ auto wrap_continuation(Continuation&& continuation) { } // end namespace base /// The namespace `compose` offers methods to chain continuations together -/// with `all` and `any` logic. +/// with `all`, `any` or `seq` logic. namespace compose { struct strategy_all_tag {}; struct strategy_any_tag {}; @@ -1262,6 +1269,24 @@ auto finalize_composition(strategy_any_tag, Composition&& composition) { }, signature); } + +/// Connects the left and the right continuable to a sequence +/// +/// \note This is implemented in an eager way because we would not gain +/// any profit from chaining sequences lazily. +template +auto sequential_connect(Left&& left, Right&& right) { + return std::forward(left).then([right = std::forward(right)]( + auto&&... args) mutable { + return std::move(right).then([previous = std::make_tuple( + std::forward(args)...)]( + auto&&... args) mutable { + return util::merge( + std::move(previous), + std::make_tuple(std::forward(args)...)); + }); + }); +} } // end namespace compose /// Provides helper functions to transform continuations to other types @@ -1405,6 +1430,13 @@ public: std::move(*this), std::move(right)); } + template + auto operator>>(continuable_base&& right) && { + right.assert_owning(); + return detail::compose::sequential_connect(std::move(*this), + std::move(right)); + } + auto futurize() && { return detail::transforms::as_future(std::move(*this).materialize()); } @@ -1573,6 +1605,22 @@ auto any_of(Continuables&&... continuables) { std::forward(continuables)...); } +/// Connects the given continuables with a *seq* logic. +/// +/// \param continuables The continuable_base objects to connect. +/// Requires at least 2 objects to connect. +/// +/// \see continuable_base::operator>> for details. +/// +/// \since version 1.0.0 +template +auto seq_of(Continuables&&... continuables) { + static_assert(sizeof...(continuables) >= 2, + "Requires at least 2 continuables!"); + return detail::util::fold(detail::util::seq_folding(), + std::forward(continuables)...); +} + template