From 7730b85b24ea27978e74023ea0aa49abec918460 Mon Sep 17 00:00:00 2001 From: Denis Blank Date: Wed, 21 Feb 2018 04:02:18 +0100 Subject: [PATCH] Make it possible to supply the async traversal pack directly from the visitor --- include/continuable/detail/traverse-async.hpp | 68 ++++++++++++++----- 1 file changed, 51 insertions(+), 17 deletions(-) diff --git a/include/continuable/detail/traverse-async.hpp b/include/continuable/detail/traverse-async.hpp index 08fb1f9..6f8998d 100644 --- a/include/continuable/detail/traverse-async.hpp +++ b/include/continuable/detail/traverse-async.hpp @@ -105,11 +105,56 @@ auto make_resume_traversal_callable(Frame&& frame, State&& state) std::forward(frame), std::forward(state)); } -/// Stores the visitor and the arguments to traverse +template +struct has_head : std::false_type {}; +template +struct has_head().head())>> + : std::true_type {}; + template -class async_traversal_frame : public Visitor { +class async_traversal_frame_data : public Visitor { + std::tuple args_; +public: + explicit async_traversal_frame_data(Visitor visitor, Args... args) + : Visitor(std::move(visitor)), + args_(std::make_tuple(std::move(args)...)) { + } + template + explicit async_traversal_frame_data(async_traverse_in_place_tag, + MapperArg&& mapper_arg, Args... args) + : Visitor(std::forward(mapper_arg)), + args_(std::make_tuple(std::move(args)...)) { + } + + /// Returns the arguments of the frame + std::tuple& head() noexcept { + return args_; + } +}; +template +class async_traversal_frame_no_data : public Visitor { +public: + explicit async_traversal_frame_no_data(Visitor visitor) + : Visitor(std::move(visitor)) { + } + template + explicit async_traversal_frame_no_data(async_traverse_in_place_tag, + MapperArg&& mapper_arg) + : Visitor(std::forward(mapper_arg)) { + } +}; + +template +using data_layout_t = + std::conditional_t::value, + async_traversal_frame_no_data, + async_traversal_frame_data>; + +/// Stores the visitor and the arguments to traverse +template +class async_traversal_frame : public data_layout_t { #ifndef _NDEBUG std::atomic finished_; #endif // _NDEBUG @@ -123,8 +168,9 @@ class async_traversal_frame : public Visitor { } public: - explicit async_traversal_frame(Visitor visitor, Args... args) - : Visitor(std::move(visitor)), args_(std::make_tuple(std::move(args)...)) + template + explicit async_traversal_frame(T&&... args) + : data_layout_t(std::forward(args)...) #ifndef _NDEBUG , finished_(false) @@ -135,18 +181,6 @@ public: /// We require a virtual base virtual ~async_traversal_frame() override = default; - template - explicit async_traversal_frame(async_traverse_in_place_tag, - MapperArg&& mapper_arg, Args... args) - : Visitor(std::forward(mapper_arg)), - args_(std::make_tuple(std::move(args)...)), finished_(false) { - } - - /// Returns the arguments of the frame - std::tuple& head() noexcept { - return args_; - } - /// Calls the visitor with the given element template auto traverse(T&& value) -> decltype(visitor()(async_traverse_visit_tag{}, @@ -184,7 +218,7 @@ public: } #endif // _NDEBUG - visitor()(async_traverse_complete_tag{}, std::move(args_)); + visitor()(async_traverse_complete_tag{}, std::move(this->head())); } };