arg_router  1.4.0
C++ command line argument parsing and routing
tree_recursor.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/tree_node.hpp"
8 #include "arg_router/utility/tuple_iterator.hpp"
9 
10 namespace arg_router::utility
11 {
12 namespace detail
13 {
14 struct always_false {
15  template <typename...>
16  [[nodiscard]] constexpr static bool fn() noexcept
17  {
18  return false;
19  }
20 };
21 
22 template <typename Visitor, typename Current, typename... Parents>
23 constexpr void tree_recursor_impl(Visitor& visitor,
24  const Current& current,
25  const Parents&... parents)
26 {
27  visitor(current, parents...);
28 
30  [&](auto /*i*/, const auto& child) {
31  tree_recursor_impl(visitor, child, current, parents...);
32  },
33  current.children());
34 }
35 
36 template <typename Visitor, typename SkipFn, typename Current, typename... Parents>
37 constexpr void tree_type_recursor_impl()
38 {
39  if constexpr (!SkipFn::template fn<Current, Parents...>()) {
40  Visitor::template fn<Current, Parents...>();
41 
42  if constexpr (is_tree_node_v<Current>) {
43  using policies_and_children_tuple =
44  boost::mp11::mp_append<typename Current::policies_type,
45  typename Current::children_type>;
46 
47  tuple_type_iterator<policies_and_children_tuple>([](auto i) {
48  using next_type = std::tuple_element_t<i, policies_and_children_tuple>;
49  tree_type_recursor_impl<Visitor, SkipFn, next_type, Current, Parents...>();
50  });
51  }
52  }
53 }
54 
55 template <template <typename...> typename Visitor, typename Current, typename... Parents>
56 struct tree_type_recursor_collector_impl {
57  template <typename ChildOrPolicy>
58  using recurse =
59  typename tree_type_recursor_collector_impl<Visitor, ChildOrPolicy, Current, Parents...>::
60  type;
61 
62  template <typename T>
63  using get_children_type = typename T::children_type;
64  template <typename T>
65  using get_policies_type = typename T::policies_type;
66 
67  using children_type = boost::mp11::
68  mp_eval_if_c<!is_tree_node_v<Current>, std::tuple<>, get_children_type, Current>;
69  using policies_type = boost::mp11::
70  mp_eval_if_c<!is_tree_node_v<Current>, std::tuple<>, get_policies_type, Current>;
71 
72  using type =
73  boost::mp11::mp_eval_if_c<!is_tree_node_v<Current>,
74  std::tuple<typename Visitor<Current, Parents...>::type>,
75  boost::mp11::mp_push_back,
76  boost::mp11::mp_flatten<boost::mp11::mp_transform<
77  recurse,
78  boost::mp11::mp_append<children_type, policies_type>>>,
79  typename Visitor<Current, Parents...>::type>;
80 };
81 } // namespace detail
82 
101 template <typename Visitor, typename Root>
102 constexpr void tree_recursor(Visitor visitor, const Root& root)
103 {
104  detail::tree_recursor_impl(visitor, root);
105 }
106 
144 template <typename Visitor, typename SkipFn, typename Root>
145 constexpr void tree_type_recursor()
146 {
147  detail::tree_type_recursor_impl<Visitor, SkipFn, Root>();
148 }
149 
155 template <typename Visitor, typename Root>
156 constexpr void tree_type_recursor()
157 {
158  detail::tree_type_recursor_impl<Visitor, detail::always_false, Root>();
159 }
160 
176 template <template <typename...> typename Visitor, typename Root>
179  using type = typename detail::tree_type_recursor_collector_impl<Visitor, Root>::type;
180 };
181 
187 template <template <typename...> typename Visitor, typename Root>
189 } // namespace arg_router::utility
constexpr void tree_recursor(Visitor visitor, const Root &root)
constexpr void tree_type_recursor()
typename tree_type_recursor_collector< Visitor, Root >::type tree_type_recursor_collector_t
constexpr std::enable_if_t< traits::is_tuple_like_v< std::decay_t< Tuple > > > tuple_iterator(F &&f, Tuple &&tuple)
constexpr auto root(Params... params) noexcept
Definition: root.hpp:295
typename detail::tree_type_recursor_collector_impl< Visitor, Root >::type type