arg_router  1.4.0
C++ command line argument parsing and routing
list.hpp
1 // Copyright (C) 2022-2023 by Camden Mannett.
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See accompanying file LICENSE or copy at https://www.boost.org/LICENSE_1_0.txt)
4 
5 #pragma once
6 
7 #include "arg_router/algorithm.hpp"
8 #include "arg_router/tree_node_fwd.hpp"
9 
10 #include <tuple>
11 
12 namespace arg_router
13 {
20 template <typename... Children>
21 class list
22 {
23 public:
25  using children_type = std::tuple<std::decay_t<Children>...>;
26 
27  static_assert(boost::mp11::mp_all_of<children_type, is_tree_node>::value,
28  "All list children must be tree_nodes (i.e. not policies)");
29 
34  constexpr explicit list(Children... children) noexcept : children_{std::move(children)...} {}
35 
40  [[nodiscard]] children_type& children() noexcept { return children_; }
41 
46  [[nodiscard]] const children_type& children() const noexcept { return children_; }
47 
48 private:
49  children_type children_;
50 };
51 
52 namespace detail
53 {
54 // Forward declared
55 template <typename Result, typename Next, typename... Others>
56 constexpr auto list_expander_impl(Result r, Next n, Others... others) noexcept;
57 
58 template <typename Result, typename ListChildren, std::size_t... I>
59 [[nodiscard]] constexpr auto list_expander_unpacker(
60  Result result,
61  ListChildren list_children,
62  [[maybe_unused]] std::integer_sequence<std::size_t, I...> Is) noexcept
63 {
64  return list_expander_impl(std::move(result), std::move(std::get<I>(list_children))...);
65 }
66 
67 // Recursion end condition
68 template <typename Result>
69 [[nodiscard]] constexpr auto list_expander_impl(Result result) noexcept
70 {
71  return result;
72 }
73 
74 template <typename Result, typename Next, typename... Others>
75 [[nodiscard]] constexpr auto list_expander_impl(Result result, Next next, Others... others) noexcept
76 {
77  if constexpr (traits::is_specialisation_of_v<std::decay_t<Next>, list>) {
78  return list_expander_impl(
79  list_expander_unpacker(
80  std::move(result),
81  next.children(),
82  std::make_index_sequence<std::tuple_size_v<typename Next::children_type>>{}),
83  std::move(others)...);
84  } else {
85  return list_expander_impl(algorithm::tuple_push_back(std::move(result), std::move(next)),
86  std::move(others)...);
87  }
88 }
89 } // namespace detail
90 
97 template <typename... Params>
98 [[nodiscard]] constexpr auto list_expander(Params... params) noexcept
99 {
100  return detail::list_expander_impl(std::tuple{}, std::move(params)...);
101 }
102 
109 template <typename... Params>
110 [[nodiscard]] constexpr auto list_expander(std::tuple<Params...> params) noexcept
111 {
112  return std::apply(
113  [](auto&... args) {
114  return detail::list_expander_impl(std::tuple{}, std::forward<decltype(args)>(args)...);
115  },
116  params);
117 }
118 } // namespace arg_router
std::tuple< std::decay_t< Children >... > children_type
Definition: list.hpp:25
constexpr list(Children... children) noexcept
Definition: list.hpp:34
const children_type & children() const noexcept
Definition: list.hpp:46
children_type & children() noexcept
Definition: list.hpp:40
constexpr auto tuple_push_back(Tuple tuple, Insert insert) noexcept
Definition: algorithm.hpp:246
constexpr bool is_specialisation_of_v
Definition: traits.hpp:175
constexpr auto list_expander(Params... params) noexcept
Definition: list.hpp:98