7 #include "arg_router/algorithm.hpp"
8 #include "arg_router/policy/no_result_value.hpp"
9 #include "arg_router/policy/policy.hpp"
10 #include "arg_router/utility/compile_time_optional.hpp"
11 #include "arg_router/utility/tree_recursor.hpp"
12 #include "arg_router/utility/tuple_iterator.hpp"
21 template <
typename... AliasedPolicies>
29 constexpr
static auto priority = std::size_t{100};
35 constexpr
explicit alias_t([[maybe_unused]]
const AliasedPolicies&... policies) {}
59 template <
typename ProcessedTarget,
typename... Parents>
64 const Parents&... parents)
const
66 using node_type = boost::mp11::mp_first<std::tuple<Parents...>>;
67 static_assert(!node_type::template any_phases_v<
typename node_type::value_type,
71 "Alias owning node cannot have policies that support parse, "
72 "validation, or routing phases");
76 using mode_type =
typename mode_data::type;
77 static_assert(!std::is_void_v<mode_type>,
"Cannot find parent mode");
80 constexpr
auto count = node_fixed_count<node_type>();
82 using targets =
typename alias_targets<aliased_policies_type, mode_type>::type;
83 static_assert(cyclic_dependency_checker<targets, mode_type>::value,
84 "Cyclic dependency detected");
87 check_target_counts<count, targets>();
91 if ((count + 1) > tokens.
size()) {
93 parsing::node_token_type<node_type>()};
104 auto alias_label = *tokens.
begin();
111 if (!parsing::match<node_type>(alias_label)) {
121 const auto visitor = [&](
const auto& current, [[maybe_unused]]
const auto&... parents) {
122 using policies_type =
typename std::decay_t<decltype(current)>::policies_type;
125 boost::mp11::mp_set_intersection<aliased_policies_type, policies_type>;
127 if constexpr ((std::tuple_size_v<intersection>) > 0) {
129 target_tokens.reserve(count);
131 auto value_it = tokens.
begin();
132 for (
auto j = 0u; j < count; ++j) {
134 target_tokens.push_back(*(++value_it));
143 std::get<mode_data::index::value>(std::tuple{std::cref(parents)...}).get();
157 template <
typename T>
158 struct policy_checker {
159 constexpr
static auto value =
160 traits::has_long_name_method_v<T> || traits::has_short_name_method_v<T>;
163 static_assert((
sizeof...(AliasedPolicies) > 0),
"At least one name needed for alias");
164 static_assert(policy::is_all_policies_v<aliased_policies_type>,
165 "All parameters must be policies");
166 static_assert(boost::mp11::mp_all_of<aliased_policies_type, policy_checker>::value,
167 "All parameters must provide a long and/or short form name");
169 template <
typename NodeType>
170 [[nodiscard]] constexpr
static std::size_t node_fixed_count() noexcept
172 static_assert(traits::has_minimum_count_method_v<NodeType> &&
173 traits::has_maximum_count_method_v<NodeType>,
174 "Aliased nodes must have minimum and maximum count methods");
175 static_assert(NodeType::minimum_count() == NodeType::maximum_count(),
176 "Aliased nodes must have a fixed count");
178 return NodeType::minimum_count();
183 template <
typename AliasPoliciesTuple,
typename ModeType>
184 struct alias_targets {
185 template <
typename Current,
typename... Parents>
190 using type = boost::mp11::mp_eval_if_c<
191 !(boost::mp11::mp_contains<AliasPoliciesTuple, Current>::value &&
192 (
sizeof...(Parents) > 0)),
195 std::tuple<Parents...>,
200 boost::mp11::mp_remove_if<utility::tree_type_recursor_collector_t<visitor, ModeType>,
203 static_assert(std::tuple_size_v<type> == std::tuple_size_v<AliasPoliciesTuple>,
204 "Number of found modes must match alias policy count");
205 static_assert(std::tuple_size_v<boost::mp11::mp_unique<type>> == std::tuple_size_v<type>,
206 "Node alias list must be unique, do you have short and long "
207 "names from the same node?");
210 template <
typename AliasNodesTuple,
typename ModeType>
211 struct cyclic_dependency_checker {
214 template <std::
size_t I,
typename Nodes>
215 [[nodiscard]] constexpr
static bool check() noexcept
217 if constexpr (I >= std::tuple_size_v<Nodes>) {
220 using aliased_type = std::tuple_element_t<I, Nodes>;
223 typename aliased_type::policies_type>) {
224 if constexpr (boost::mp11::mp_contains<
typename aliased_type::policies_type,
229 typename alias_targets<
typename aliased_type::aliased_policies_type,
232 return check<I + 1, boost::mp11::mp_append<Nodes, targets>>();
236 return check<I + 1, Nodes>();
240 constexpr
static bool value = check<0, AliasNodesTuple>();
243 template <std::
size_t Count,
typename TargetsTuple>
244 constexpr
static void check_target_counts() noexcept
246 utility::tuple_type_iterator<TargetsTuple>([](
auto i) {
247 using target_type = std::tuple_element_t<i, TargetsTuple>;
249 static_assert(node_fixed_count<target_type>() == Count,
250 "All alias targets must have a count that matches the owner");
262 template <
typename... AliasedPolicies>
263 [[nodiscard]] constexpr
auto alias(AliasedPolicies... policies) noexcept
265 return alias_t{std::move(policies)...};
268 template <
typename... AliasedPolicies>
269 struct is_policy<alias_t<AliasedPolicies...>> : std::true_type {
void transfer(iterator it)
vector< value_type > & processed()
void add_sub_target(parse_target target)
parsing::pre_parse_result pre_parse_phase(parsing::dynamic_token_adapter &tokens, [[maybe_unused]] utility::compile_time_optional< ProcessedTarget > processed_target, parsing::parse_target &target, const Parents &... parents) const
std::tuple< std::decay_t< AliasedPolicies >... > aliased_policies_type
constexpr static auto priority
constexpr alias_t([[maybe_unused]] const AliasedPolicies &... policies)
constexpr auto has_specialisation_v
@ skip_node_but_use_sub_targets
token_type get_token_type(std::string_view token)
constexpr auto alias(AliasedPolicies... policies) noexcept
std::integral_constant< decltype(Value), Value > integral_constant
constexpr void tree_recursor(Visitor visitor, const Root &root)
std::vector< T, config::allocator< T > > vector
@ too_few_values_for_alias
constexpr auto mode(Params... params)