// // boost/process/v2/bind_launcher.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2022 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_PROCESS_V2_BIND_LAUNCHER_HPP #define BOOST_PROCESS_V2_BIND_LAUNCHER_HPP #include #include BOOST_PROCESS_V2_BEGIN_NAMESPACE namespace detail { template struct index_sequence { }; template struct make_index_sequence_impl; template struct make_index_sequence_impl> { constexpr make_index_sequence_impl() {} using type = typename make_index_sequence_impl>::type; }; template struct make_index_sequence_impl<0u, index_sequence> { constexpr make_index_sequence_impl() {} using type = index_sequence; }; template struct make_index_sequence { using type = typename make_index_sequence_impl>::type; }; template using make_index_sequence_t = typename make_index_sequence::type; } /** @brief Utility class to bind initializers to a launcher * @tparam Launcher The inner launcher to be used * @tparam ...Init The initializers to be prepended. * * This can be used when multiple processes shared some settings, * e.g. * */ template struct bound_launcher { template bound_launcher(Launcher_ && l, Init_ && ... init) : launcher_(std::forward(l)), init_(std::forward(init)...) { } template auto operator()(ExecutionContext & context, const typename std::enable_if::value, filesystem::path >::type & executable, Args && args, Inits && ... inits) -> basic_process { return invoke(detail::make_index_sequence_t{}, context, executable, std::forward(args), std::forward(inits)...); } template auto operator()(ExecutionContext & context, error_code & ec, const typename std::enable_if::value, filesystem::path >::type & executable, Args && args, Inits && ... inits ) -> basic_process { return invoke(detail::make_index_sequence_t{}, context, ec, executable, std::forward(args), std::forward(inits)...); } template auto operator()(Executor exec, const typename std::enable_if< BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor::value || BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor::value, filesystem::path >::type & executable, Args && args, Inits && ... inits ) -> basic_process { return invoke(detail::make_index_sequence_t{}, std::move(exec), executable, std::forward(args), std::forward(inits)...); } template auto operator()(Executor exec, error_code & ec, const typename std::enable_if< BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor::value || BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor::value, filesystem::path >::type & executable, Args && args, Inits && ... inits ) -> basic_process { return invoke(detail::make_index_sequence_t{}, std::move(exec), ec, executable, std::forward(args), std::forward(inits)...); } private: template auto invoke(detail::index_sequence, ExecutionContext & context, const typename std::enable_if::value, filesystem::path >::type & executable, Args && args, Inits && ... inits) -> basic_process { return launcher_(context, executable, std::forward(args), std::get(init_)..., std::forward(inits)...); } template auto invoke(detail::index_sequence, ExecutionContext & context, error_code & ec, const typename std::enable_if::value, filesystem::path >::type & executable, Args && args, Inits && ... inits ) -> basic_process { return launcher_(context, ec, executable, std::forward(args), std::get(init_)..., std::forward(inits)...); } template auto invoke(detail::index_sequence, Executor exec, const typename std::enable_if< BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor::value || BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor::value, filesystem::path >::type & executable, Args && args, Inits && ... inits ) -> basic_process { return launcher_(std::move(exec), executable, std::forward(args), std::get(init_)..., std::forward(inits)...); } template auto invoke(detail::index_sequence, Executor exec, error_code & ec, const typename std::enable_if< BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor::value || BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor::value, filesystem::path >::type & executable, Args && args, Inits && ... inits ) -> basic_process { return launcher_(std::move(exec), ec, executable, std::forward(args), std::get(init_)..., std::forward(inits)...); } Launcher launcher_; std::tuple init_; }; template auto bind_launcher(Launcher && launcher, Init && ... init) -> bound_launcher::type, typename std::decay::type...> { return bound_launcher::type, typename std::decay::type...>( std::forward(launcher), std::forward(init)...); } /// @brief @overload bind_launcher(Launcher && launcher, Init && init) /// @tparam ...Init The initializer types to bind to the default_launcher. /// @param ...init The initializers types to bind to the default_launcher. /// @return The new default_launcher. template auto bind_default_launcher(Init && ... init) -> bound_launcher::type...> { return bound_launcher::type...>( default_process_launcher(), std::forward(init)...); } BOOST_PROCESS_V2_END_NAMESPACE #endif // BOOST_PROCESS_V2_BIND_LAUNCHER_HPP