From 20cd0191fcac3526afceba5712ef8f7f593f6014 Mon Sep 17 00:00:00 2001 From: Denis Blank Date: Mon, 14 Jan 2019 21:10:17 +0100 Subject: [PATCH] For loops provide loop_result loop_break and loop_continue for better readability --- include/continuable/detail/core/types.hpp | 5 ++ include/continuable/operations/loop.hpp | 51 ++++++++++++++++++- .../test-continuable-operations-loop.cpp | 20 +++++++- 3 files changed, 73 insertions(+), 3 deletions(-) diff --git a/include/continuable/detail/core/types.hpp b/include/continuable/detail/core/types.hpp index 0ec8737..395188d 100644 --- a/include/continuable/detail/core/types.hpp +++ b/include/continuable/detail/core/types.hpp @@ -31,6 +31,7 @@ #ifndef CONTINUABLE_DETAIL_TYPES_HPP_INCLUDED #define CONTINUABLE_DETAIL_TYPES_HPP_INCLUDED +#include #include #include #include @@ -84,6 +85,10 @@ class plain_tag { T value_; public: + template >::value>* = nullptr> + /* implicit */ plain_tag(O&& value) : value_(std::forward(value)) { + } explicit plain_tag(T value) : value_(std::move(value)) { } diff --git a/include/continuable/operations/loop.hpp b/include/continuable/operations/loop.hpp index dd4f569..a2f9142 100644 --- a/include/continuable/operations/loop.hpp +++ b/include/continuable/operations/loop.hpp @@ -32,6 +32,7 @@ #define CONTINUABLE_OPERATIONS_LOOP_HPP_INCLUDED #include +#include #include #include @@ -42,11 +43,30 @@ namespace cti { /// Can be used to create an asynchronous loop. /// /// The callable will be called repeatedly until it returns a -/// cti::continuable_base which then resolves to present cti::result. +/// cti::continuable_base which then resolves to a present cti::result. +/// +/// For better readability cti::loop_result, cti::loop_break and +/// cti::loop_continue are provided which can be used as following: +/// ```cpp +/// auto while_answer_not_yes() { +/// return loop([] { +/// return ask_something().then([](std::string answer) -> loop_result<> { +/// if (answer == "yes") { +/// return loop_break(); +/// } else { +/// return loop_continue(); +/// } +/// }); +/// }); +/// } +/// ``` /// /// \param callable The callable type which must return a cti::continuable_base /// which then resolves to a cti::result of arbitrary values. /// +/// \param args The arguments that are passed to the callable upon +/// each invocation. +/// /// \since 4.0.0 /// template @@ -55,6 +75,34 @@ auto loop(Callable&& callable, Args&&... args) { std::forward(args)...); } +/// Can be used to indicate a specific result inside an asynchronous loop. +/// +/// See cti::loop for details. +/// +/// \since 4.0.0 +template +using loop_result = plain_t>; + +/// Can be used to create a loop_result which causes the loop to be +/// cancelled and resolved with the given arguments. +/// +/// See cti::loop for details. +/// +/// \since 4.0.0 +template +auto loop_break(T&&... args) { + return make_plain(make_result(std::forward(args)...)); +} + +/// Can be used to create a loop_result which causes the loop to be repeated. +/// +/// See cti::loop for details. +/// +/// \since 4.0.0 +inline auto loop_continue() noexcept { + return empty_result{}; +} + /// /// \since 4.0.0 /// @@ -64,6 +112,7 @@ auto range_loop(Callable&& callable, Iterator begin, Iterator end) { detail::operations::make_range_looper(std::forward(callable), begin, end)); } + /// \} } // namespace cti diff --git a/test/unit-test/multi/test-continuable-operations-loop.cpp b/test/unit-test/multi/test-continuable-operations-loop.cpp index 40d7a90..ace6d18 100644 --- a/test/unit-test/multi/test-continuable-operations-loop.cpp +++ b/test/unit-test/multi/test-continuable-operations-loop.cpp @@ -52,6 +52,22 @@ TYPED_TEST(single_dimension_tests, operations_loop_completion) { CANARY, 2, CANARY); } +TYPED_TEST(single_dimension_tests, operations_loop_until) { + int i = 0; + + ASSERT_ASYNC_COMPLETION(loop([&i] { + return make_ready_continuable(++i).then([](int i) -> loop_result<> { + if (i == 3) { + return loop_break(); + } else { + return loop_continue(); + } + }); + })); + + ASSERT_EQ(i, 3); +} + TYPED_TEST(single_dimension_tests, operations_loop_looping) { int i = 0; @@ -61,7 +77,7 @@ TYPED_TEST(single_dimension_tests, operations_loop_looping) { ++i; return make_ready_continuable(); }, - 0, 10)); + 0, 3)); - ASSERT_EQ(i, 10); + ASSERT_EQ(i, 3); }