#ifndef ALSK_ALSK_IMPL_BONE_SERIAL_H #define ALSK_ALSK_IMPL_BONE_SERIAL_H #include "../boneimplbase.h" #include "../../skeleton/bone/serial.h" namespace alsk { /** * @brief Serial implementation for any execution */ template struct Impl, Tag, Executor, State>: BoneImplBase, Tag, Executor, State> { using This = Impl; using Results = tmp::Repack>; typename This::Skeleton skeleton; typename This::Executor executor; typename This::StateRef state; Results results; constexpr Impl() = default; template constexpr Impl(S&& skeleton, O&& executor, State& state): skeleton{std::forward(skeleton)}, executor{std::forward(executor)}, state{state} {} // out-of-class definition to silence -Winline ~Impl() noexcept; // TODO: what happens with rvalue references? constexpr typename This::Return operator()(Args... args) { return serial(std::forward_as_tuple(args...)); } private: template constexpr decltype(auto) serial(TupleP&& p) { serial<0, typename This::Skeleton::Links>(skeleton.tasks, p); return ArgGet::get(std::tuple<>{}, std::move(results), std::tuple<>{}); } /** * execute */ template< std::size_t I, typename LinksPack, typename TupleTasks, typename TupleP, std::enable_if_t<(I < std::tuple_size>::value)>* = nullptr > constexpr void serial(TupleTasks& tasks, TupleP& p) { using Task = Execute>; std::get(results) = executor.template execute( *this, std::get(tasks), p, results ); serial>(tasks, p); } /** * recursion terminaison */ template< std::size_t I, typename LinksPack, typename TupleTasks, typename TupleP, std::enable_if_t<(I == std::tuple_size>::value)>* = nullptr > constexpr void serial(TupleTasks&&, TupleP&&) noexcept {} }; // out-of-class definition to silence -Winline template Impl, Tag, Executor, State>::~Impl() noexcept {} } #endif