arg_router  1.4.0
C++ command line argument parsing and routing
algorithm.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/traits.hpp"
8 
9 #include <boost/mp11/bind.hpp>
10 
11 #include <algorithm>
12 #include <string_view>
13 
16 {
28 template <template <typename...> typename T, typename Tuple>
30 {
31  template <typename U>
33 
34 public:
37  constexpr static std::size_t value = boost::mp11::mp_find_if<Tuple, fn>::value;
38 };
39 
45 template <template <typename...> typename T, typename Tuple>
47 
60 template <template <typename...> typename T, typename Tuple>
62 {
63  template <typename U>
65 
66 public:
67  constexpr static std::size_t value = boost::mp11::mp_count_if<Tuple, fn>::value;
68 };
69 
75 template <template <typename...> typename T, typename Tuple>
77 
84 template <typename T, typename Tuple>
86 {
87  template <typename U>
89 
90 public:
91  constexpr static std::size_t value = boost::mp11::mp_count_if<Tuple, fn>::value;
92 };
93 
99 template <typename T, typename Tuple>
101 
112 template <template <typename...> typename T, typename Tuple>
115  constexpr static bool value = find_specialisation_v<T, Tuple> < std::tuple_size_v<Tuple>;
116 };
117 
123 template <template <typename...> typename T, typename Tuple>
125 
134 template <typename First, typename Second>
135 class zip
136 {
137  static_assert((std::tuple_size_v<First> == std::tuple_size_v<Second>),
138  "First and Second tuples must contain the same number of elements");
139 
140  template <std::size_t... N>
141  [[nodiscard]] constexpr static auto zip_impl_t(
142  std::integer_sequence<std::size_t, N...>) noexcept
143  -> std::tuple<
144  std::pair<std::tuple_element_t<N, First>, std::tuple_element_t<N, Second>>...>;
145 
146 public:
148  using type =
149  decltype(zip_impl_t(std::declval<std::make_index_sequence<std::tuple_size_v<First>>>()));
150 };
151 
157 template <typename First, typename Second>
159 
164 template <typename T>
165 struct unzip {
167  using first_type = boost::mp11::mp_transform<boost::mp11::mp_first, T>;
168 
170  using second_type = boost::mp11::mp_transform<boost::mp11::mp_second, T>;
171 };
172 
173 namespace detail
174 {
175 template <typename U, typename... I>
176 [[nodiscard]] constexpr auto tuple_filter_and_construct_impl(
177  U&& input,
178  [[maybe_unused]] std::tuple<I...> Is) noexcept
179 {
180  return std::tuple{std::get<I::value>(std::forward<U>(input))...};
181 }
182 } // namespace detail
183 
195 template <template <typename...> typename Fn, typename U>
196 [[nodiscard]] constexpr auto tuple_filter_and_construct(U&& input) noexcept
197 {
198  // Zip together an index-sequence of U and the elements of it
199  using zipped =
201 
202  // Filter out types not approved by Fn, we need to wrap Fn so that it only operates on the
203  // second type in the pair (the type from U)
204  using wrapped_fn =
205  boost::mp11::mp_bind<Fn, boost::mp11::mp_bind<boost::mp11::mp_second, boost::mp11::_1>>;
206  using filtered = boost::mp11::mp_filter_q<wrapped_fn, zipped>;
207 
208  // Fold construct the return value using the zip indices as accessors to input
209  return detail::tuple_filter_and_construct_impl(input, typename unzip<filtered>::first_type{});
210 }
211 
212 namespace detail
213 {
214 template <template <typename...> typename Tuple,
215  typename Insert,
216  typename... Args,
217  std::size_t... I>
218 [[nodiscard]] constexpr auto tuple_push_back_impl(
219  Tuple<Args...> tuple,
220  Insert insert,
221  [[maybe_unused]] std::integer_sequence<std::size_t, I...> Is) noexcept
222 {
223  return Tuple{std::move(std::get<I>(tuple))..., std::move(insert)};
224 }
225 
226 // Empty tuple specialisation
227 template <template <typename...> typename Tuple, typename Insert>
228 [[nodiscard]] constexpr auto tuple_push_back_impl(
229  [[maybe_unused]] Tuple<> t,
230  Insert insert,
231  [[maybe_unused]] std::integer_sequence<std::size_t> Is) noexcept
232 {
233  return Tuple{std::move(insert)};
234 }
235 } // namespace detail
236 
245 template <typename Tuple, typename Insert>
246 [[nodiscard]] constexpr auto tuple_push_back(Tuple tuple, Insert insert) noexcept
247 {
248  // Cannot use std::tuple_cat as it causes infinite compiler loops in MSVC
249  return detail::tuple_push_back_impl(std::move(tuple),
250  std::move(insert),
251  std::make_index_sequence<std::tuple_size_v<Tuple>>{});
252 }
253 
254 namespace detail
255 {
256 template <std::size_t Count, typename U, std::size_t... I>
257 [[nodiscard]] constexpr auto tuple_drop_impl(
258  U&& input,
259  // NOLINTNEXTLINE(*-named-parameter)
260  [[maybe_unused]] std::integer_sequence<std::size_t, I...>) noexcept
261 {
262  return std::tuple{std::get<I + Count>(std::forward<U>(input))...};
263 }
264 } // namespace detail
265 
271 template <std::size_t Count, typename Tuple>
272 [[nodiscard]] constexpr auto tuple_drop(Tuple&& input)
273 {
274  return detail::tuple_drop_impl<Count>(
275  std::forward<Tuple>(input),
276  std::make_index_sequence<std::tuple_size_v<Tuple> - Count>{});
277 }
278 
287 template <std::size_t I, typename... T>
288 [[nodiscard]] constexpr auto& pack_element(const T&... pack) noexcept
289 {
290  static_assert(I < sizeof...(pack), "Index out of bounds for pack");
291  return std::get<I>(std::tuple{std::cref(pack)...}).get();
292 }
293 } // namespace arg_router::algorithm
constexpr static std::size_t value
Definition: algorithm.hpp:37
decltype(zip_impl_t(std::declval< std::make_index_sequence< std::tuple_size_v< First > >>())) type
Definition: algorithm.hpp:149
constexpr auto tuple_drop(Tuple &&input)
Definition: algorithm.hpp:272
constexpr auto count_despecialised_v
Definition: algorithm.hpp:100
constexpr auto count_specialisation_v
Definition: algorithm.hpp:76
constexpr auto find_specialisation_v
Definition: algorithm.hpp:46
constexpr auto has_specialisation_v
Definition: algorithm.hpp:124
constexpr auto & pack_element(const T &... pack) noexcept
Definition: algorithm.hpp:288
typename zip< First, Second >::type zip_t
Definition: algorithm.hpp:158
constexpr auto tuple_push_back(Tuple tuple, Insert insert) noexcept
Definition: algorithm.hpp:246
constexpr auto tuple_filter_and_construct(U &&input) noexcept
Definition: algorithm.hpp:196
boost::mp11::mp_transform< boost::mp11::mp_second, T > second_type
Definition: algorithm.hpp:170
boost::mp11::mp_transform< boost::mp11::mp_first, T > first_type
Definition: algorithm.hpp:167