arg_router  1.4.0
C++ command line argument parsing and routing
validator_rule_utilities.hpp
1 // Copyright (C) 2022 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/policy/validator.hpp"
8 
9 namespace arg_router::policy::validation::utility
10 {
11 namespace detail
12 {
13 // This can't be done inside add_to_rule_types due to a g++-11 bug that prevents deduction guides
14 // being declared inside class scope
15 template <template <typename...> typename T,
16  template <template <typename...> typename...>
17  typename U,
18  template <typename...>
19  typename... V>
20 struct appender_t {
21  using type = U<V..., T>;
22 
23  explicit appender_t([[maybe_unused]] U<V...> rule_type) {}
24 };
25 
26 template <template <typename...> typename T,
27  template <template <typename...> typename...>
28  typename U,
29  template <typename...>
30  typename... V>
31 auto appender(U<V...>&& rule_type)
32 {
33  return appender_t<T, U, V...>{std::forward<U<V...>>(rule_type)};
34 }
35 } // namespace detail
36 
38 using default_rules = typename decltype(default_validator)::rules_type;
39 
46 template <typename RuleType, typename Rules>
47 constexpr std::size_t find_index_of_rule_type() noexcept
48 {
49  return boost::mp11::mp_find_if_q<
50  Rules,
51  boost::mp11::mp_bind<std::is_same,
52  RuleType,
53  boost::mp11::mp_bind<boost::mp11::mp_first, boost::mp11::_1>>>::value;
54 }
55 
62 template <std::size_t I, typename Rule, typename Rules>
63 struct insert_rule {
64  static_assert(I <= std::tuple_size_v<Rules>, "I must be less than or equal Rules size");
65 
67  using type = boost::mp11::mp_insert_c<Rules, I, Rule>;
68 };
69 
76 template <std::size_t I, typename Rule, typename Rules>
77 using insert_rule_t = typename insert_rule<I, Rule, Rules>::type;
78 
84 template <std::size_t I, typename Rules>
85 struct remove_rule {
86  static_assert(I < std::tuple_size_v<Rules>, "I must be less than Rules size");
87 
89  using type = boost::mp11::mp_erase_c<Rules, I, I + 1>;
90 };
91 
97 template <std::size_t I, typename Rules>
98 using remove_rule_t = typename remove_rule<I, Rules>::type;
99 
106 template <typename RuleType, typename Rules>
108 {
109  constexpr static auto I = find_index_of_rule_type<RuleType, Rules>();
110  constexpr static auto found = I < std::tuple_size_v<Rules>;
111 
112 public:
114  using type = boost::mp11::mp_eval_if_c<!found,
115  Rules,
116  boost::mp11::mp_erase, // Can't use remove_rule_t here
117  Rules, // due to the NTTPs...
120 };
121 
127 template <typename RuleType, typename Rules>
128 using remove_rule_by_type_t = typename remove_rule_by_type<RuleType, Rules>::type;
129 
136 template <std::size_t I, typename Rule, typename Rules>
137 struct update_rule {
138  static_assert(I < std::tuple_size_v<Rules>, "I must be less than Rules size");
139 
141  using type = boost::mp11::mp_replace_at_c<Rules, I, Rule>;
142 };
143 
150 template <std::size_t I, typename Rule, typename Rules>
151 using update_rule_t = typename update_rule<I, Rule, Rules>::type;
152 
159 template <typename RuleType, typename Rule, typename Rules>
161 {
162  constexpr static auto I = find_index_of_rule_type<RuleType, Rules>();
163  static_assert(I < std::tuple_size_v<Rules>, "RuleType cannot be found");
164 
165 public:
167  using type = update_rule_t<I, Rule, Rules>;
168 };
169 
176 template <typename RuleType, typename Rule, typename Rules>
177 using update_rule_by_type_t = typename update_rule_by_type<RuleType, Rule, Rules>::type;
178 
201 template <std::size_t I, template <typename...> typename T, typename Rules>
203 {
204  static_assert(I < std::tuple_size_v<Rules>, "I must be less than Rules size");
205 
206  using rule = std::tuple_element_t<I, Rules>;
207  using rule_type = std::tuple_element_t<0, rule>;
208  using new_rule_type = typename decltype(detail::appender<T>(std::declval<rule_type>()))::type;
209  using new_rule = boost::mp11::mp_replace_at_c<rule, 0, new_rule_type>;
210 
211 public:
213  using type = boost::mp11::mp_replace_at_c<Rules, I, new_rule>;
214 };
215 
222 template <std::size_t I, template <typename...> typename T, typename Rules>
223 using add_to_rule_types_t = typename add_to_rule_types<I, T, Rules>::type;
224 
231 template <typename RuleType, template <typename...> typename T, typename Rules>
233 {
234  constexpr static auto I = find_index_of_rule_type<RuleType, Rules>();
235  static_assert(I < std::tuple_size_v<Rules>, "RuleType cannot be found");
236 
237 public:
239  using type = add_to_rule_types_t<I, T, Rules>;
240 };
241 
248 template <typename RuleType, template <typename...> typename T, typename Rules>
249 using add_to_rule_types_by_rule_t = typename add_to_rule_types_by_rule<RuleType, T, Rules>::type;
250 } // namespace arg_router::policy::validation::utility
boost::mp11::mp_replace_at_c< Rules, I, new_rule > type
boost::mp11::mp_eval_if_c<!found, Rules, boost::mp11::mp_erase, Rules, traits::integral_constant< I >, traits::integral_constant< I+1 > > type
constexpr auto default_validator
Definition: validator.hpp:617
std::integral_constant< decltype(Value), Value > integral_constant
Definition: traits.hpp:210
boost::mp11::mp_replace_at_c< Rules, I, Rule > type