arg_router  1.4.0
C++ command line argument parsing and routing
traits.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_fwd.hpp"
8 
9 #include <boost/mp11/algorithm.hpp>
10 #include <boost/mp11/bind.hpp>
11 #include <boost/mp11/utility.hpp>
12 
13 #include <algorithm>
14 #include <functional>
15 #include <optional>
16 #include <ostream>
17 #include <tuple>
18 #include <type_traits>
19 
20 // Surprised this is not already done somewhere in mp11, without it using
21 // std::tuple and mp_list in generic situations doesn't work
22 namespace std
23 {
24 template <typename... T>
25 struct tuple_size<boost::mp11::mp_list<T...>> : std::integral_constant<std::size_t, sizeof...(T)> {
26 };
27 
28 template <std::size_t I, typename... T>
29 struct tuple_element<I, boost::mp11::mp_list<T...>> {
30  using type = boost::mp11::mp_at_c<boost::mp11::mp_list<T...>, I>;
31 };
32 } // namespace std
33 
35 namespace arg_router
36 {
37 class multi_lang_exception;
38 
40 namespace traits
41 {
46 template <typename... T>
47 struct always_false : std::false_type {
48 };
49 
54 template <typename... T>
55 constexpr bool always_false_v = always_false<T...>::value;
56 
61 template <typename T>
62 using get_type = typename T::type;
63 
68 template <typename T>
69 using get_value_type = typename T::value_type;
70 
75 template <typename T>
77  constexpr static bool value = boost::mp11::mp_valid<get_value_type, T>::value;
78 };
79 
84 template <typename T>
86 
91 template <typename T, typename Enable = void>
93  using type = T;
94 };
95 
96 template <typename T>
97 struct underlying_type<T, std::enable_if_t<std::is_enum_v<T>>> {
98  using type = std::underlying_type_t<T>;
99 };
100 
105 template <typename T>
106 using underlying_type_t = typename underlying_type<T>::type;
107 
114 template <typename T, typename = void>
115 struct is_tuple_like : std::false_type {
116 };
117 
118 template <typename T>
119 struct is_tuple_like<T, std::void_t<typename std::tuple_size<T>::type>> : std::true_type {
120 };
121 
126 template <typename T>
128 
135 template <typename T>
136 struct is_specialisation : std::false_type {
137 };
138 
139 template <template <typename...> typename U, typename... Args>
140 struct is_specialisation<U<Args...>> : std::true_type {
141 };
142 
147 template <typename T>
149 
161 template <typename T, template <typename...> typename U>
162 struct is_specialisation_of : std::false_type {
163 };
164 
165 template <template <typename...> typename U, typename... Args>
166 struct is_specialisation_of<U<Args...>, U> : std::true_type {
167 };
168 
174 template <typename T, template <typename...> typename U>
176 
189 template <typename T, typename U, typename... Args>
190 struct is_same_when_despecialised : std::false_type {
191 };
192 
193 template <template <typename...> typename T, typename U, typename... Args>
194 struct is_same_when_despecialised<T<Args...>, U> : is_specialisation_of<U, T> {
195 };
196 
202 template <typename T, typename U>
204 
209 template <auto Value>
210 using integral_constant = std::integral_constant<decltype(Value), Value>;
211 
216 template <typename T>
217 struct add_optional {
218  using type = std::optional<T>;
219 };
220 
225 template <typename T>
226 using add_optional_t = typename add_optional<T>::type;
227 
234 template <typename T>
236 {
237  static_assert(always_false_v<T>, "T must be a tuple-like type");
238 };
239 
240 template <template <typename...> typename T, typename... Params>
241 class unpack_and_derive<T<Params...>> : public Params...
242 {
243  // When are we going to get language-level tuple unpacking!?
244  template <std::size_t... I>
245  constexpr explicit unpack_and_derive(
246  T<Params...> params,
247  [[maybe_unused]] std::integer_sequence<std::size_t, I...> Is) noexcept :
248  Params{std::get<I>(std::move(params))}...
249  {
250  }
251 
252  // This empty tuple overload is just to prevent an
253  // -Werror=unused-but-set-parameter on the params parameter
254  template <std::size_t... I>
255  constexpr explicit unpack_and_derive(
256  [[maybe_unused]] T<Params...> t,
257  [[maybe_unused]] std::integer_sequence<std::size_t> Is) noexcept
258  {
259  }
260 
261 public:
262  constexpr explicit unpack_and_derive(T<Params...> params) noexcept :
263  unpack_and_derive{std::move(params), std::make_index_sequence<sizeof...(Params)>{}}
264  {
265  }
266 };
267 
273 template <typename From, typename To>
275  template <typename F, typename T>
276  using type = decltype(static_cast<T>(std::declval<F>()));
277 
278  constexpr static bool value = boost::mp11::mp_valid<type, From, To>::value;
279 };
280 
286 template <typename From, typename To>
288 
293 template <typename T>
295  template <typename U>
296  using type = decltype(U::long_name());
297 
298  constexpr static bool value = boost::mp11::mp_valid<type, T>::value;
299 };
300 
305 template <typename T>
307 
312 template <typename T>
314  template <typename U>
315  using type = decltype(U::short_name());
316 
317  constexpr static bool value = boost::mp11::mp_valid<type, T>::value;
318 };
319 
324 template <typename T>
326 
331 template <typename T>
333  template <typename U>
334  using type = decltype(U::display_name());
335 
336  constexpr static bool value = boost::mp11::mp_valid<type, T>::value;
337 };
338 
343 template <typename T>
345 
350 template <typename T>
352  template <typename U>
353  using type = decltype(U::none_name());
354 
355  constexpr static bool value = boost::mp11::mp_valid<type, T>::value;
356 };
357 
362 template <typename T>
364 
369 template <typename T>
371  template <typename U>
372  using type = decltype(U::error_name());
373 
374  constexpr static bool value = boost::mp11::mp_valid<type, T>::value;
375 };
376 
381 template <typename T>
383 
388 template <typename T>
390  template <typename U>
391  using type = decltype(U::description());
392 
393  constexpr static bool value = boost::mp11::mp_valid<type, T>::value;
394 };
395 
400 template <typename T>
402 
407 template <typename T>
409  template <typename U>
410  using type = decltype(U::value_separator());
411 
412  constexpr static bool value = boost::mp11::mp_valid<type, T>::value;
413 };
414 
419 template <typename T>
421 
426 template <typename T>
428  template <typename U>
429  using type = decltype(U::token_end_marker());
430 
431  constexpr static bool value = boost::mp11::mp_valid<type, T>::value;
432 };
433 
438 template <typename T>
440 
445 template <typename T>
447  template <typename U>
448  using type = decltype(U::maximum_count());
449 
450  constexpr static bool value = boost::mp11::mp_valid<type, T>::value;
451 };
452 
457 template <typename T>
459 
464 template <typename T>
466  template <typename U>
467  using type = decltype(U::minimum_count());
468 
469  constexpr static bool value = boost::mp11::mp_valid<type, T>::value;
470 };
471 
476 template <typename T>
478 
483 template <typename T>
485  template <typename U>
486  using type = decltype(U::minimum_value());
487 
488  constexpr static bool value = boost::mp11::mp_valid<type, T>::value;
489 };
490 
495 template <typename T>
497 
502 template <typename T>
504  template <typename U>
505  using type = decltype(U::maximum_value());
506 
507  constexpr static bool value = boost::mp11::mp_valid<type, T>::value;
508 };
509 
514 template <typename T>
516 
521 template <typename T>
523  template <typename U>
524  using type = decltype(std::declval<U&>().push_back(std::declval<typename U::value_type>()));
525 
526  constexpr static bool value = boost::mp11::mp_valid<type, T>::value;
527 };
528 
533 template <typename T>
535 
540 template <typename T>
542  template <typename U>
543  using type = typename U::template help_data_type<false>;
544 
545  constexpr static bool value = boost::mp11::mp_valid<type, T>::value;
546 };
547 
552 template <typename T>
554 
559 template <typename T>
561 {
562  struct fake_tree_node {
563  [[nodiscard]] const std::tuple<>& children() const { return children_; }
564 
565  std::tuple<> children_;
566  };
567 
568  template <typename U>
569  using type =
570  decltype(U::runtime_children(std::declval<const fake_tree_node&>(),
571  std::declval<std::function<bool(const fake_tree_node&)>>()));
572 
573 public:
574  constexpr static bool value = boost::mp11::mp_valid<type, T>::value;
575 };
576 
581 template <typename T>
583 
589 template <typename T>
591  template <typename U>
592  using type = decltype(U::template generate_help<U, U, false>(std::declval<std::ostream&>()));
593 
594  constexpr static bool value = boost::mp11::mp_valid<type, T>::value;
595 };
596 
601 template <typename T>
603 
609 template <typename T>
611  template <typename U>
612  using type =
613  decltype(U::template generate_help<U, U, false>(std::declval<std::ostream&>(),
614  std::declval<const runtime_help_data&>()));
615 
616  constexpr static bool value = boost::mp11::mp_valid<type, T>::value;
617 };
618 
623 template <typename T>
625 
631 template <typename T>
633  template <typename U>
634  using type = decltype(std::declval<const T&>().template generate_runtime_help_data<true, U>(
635  std::declval<const U&>()));
636 
637  constexpr static bool value = boost::mp11::mp_valid<type, T>::value;
638 };
639 
644 template <typename T>
647 
652 template <typename T>
654  template <typename U>
655  using type = decltype(std::declval<const U&>().runtime_enabled());
656 
657  constexpr static bool value = boost::mp11::mp_valid<type, T>::value;
658 };
659 
664 template <typename T>
666 
671 template <typename T>
673  template <typename U>
674  using type = decltype(U::translate_exception(std::declval<const multi_lang_exception&>()));
675 
676  constexpr static bool value = boost::mp11::mp_valid<type, T>::value;
677 };
678 
683 template <typename T>
684 constexpr static bool has_translate_exception_method_v = has_translate_exception_method<T>::value;
685 
690 template <typename T>
692  template <typename U>
693  using type = typename U::error_code_translations;
694 
695  constexpr static bool value = boost::mp11::mp_valid<type, T>::value;
696 };
697 
702 template <typename T>
703 constexpr static bool has_error_code_translations_type_v =
705 
717 template <typename T>
718 struct arg_extractor : arg_extractor<decltype(&T::operator())> {
719 };
720 
721 template <typename R, typename... Args>
722 struct arg_extractor<R (*)(Args...)> {
723  using type = std::tuple<R, Args...>;
724 };
725 template <typename R, typename C, typename... Args>
726 struct arg_extractor<R (C::*)(Args...)> {
727  using type = std::tuple<R, Args...>;
728 };
729 template <typename R, typename C, typename... Args>
730 struct arg_extractor<R (C::*)(Args...) const> {
731  using type = std::tuple<R, Args...>;
732 };
733 template <typename R, typename C, typename... Args>
734 struct arg_extractor<R (C::*)(Args...) noexcept> {
735  using type = std::tuple<R, Args...>;
736 };
737 template <typename R, typename C, typename... Args>
738 struct arg_extractor<R (C::*)(Args...) const noexcept> {
739  using type = std::tuple<R, Args...>;
740 };
741 
746 template <typename T>
748 
753 template <typename T>
754 constexpr std::size_t arity_v = std::tuple_size_v<arg_extractor_t<T>> - 1;
755 
761 template <typename T, std::size_t I>
762 using arg_type_at_index = std::tuple_element_t<I + 1, arg_extractor_t<T>>;
763 } // namespace traits
764 } // namespace arg_router
constexpr bool has_generate_help_method_v
Definition: traits.hpp:602
constexpr bool has_token_end_marker_method_v
Definition: traits.hpp:439
constexpr bool is_specialisation_of_v
Definition: traits.hpp:175
constexpr bool is_same_when_despecialised_v
Definition: traits.hpp:203
constexpr bool has_error_name_method_v
Definition: traits.hpp:382
constexpr bool has_runtime_generate_help_method_v
Definition: traits.hpp:624
constexpr bool supports_static_cast_conversion_v
Definition: traits.hpp:287
constexpr bool has_description_method_v
Definition: traits.hpp:401
constexpr bool has_maximum_value_method_v
Definition: traits.hpp:515
constexpr bool has_runtime_enabled_method_v
Definition: traits.hpp:665
constexpr bool has_maximum_count_method_v
Definition: traits.hpp:458
constexpr bool is_tuple_like_v
Definition: traits.hpp:127
constexpr bool has_value_type_v
Definition: traits.hpp:85
constexpr std::size_t arity_v
Definition: traits.hpp:754
constexpr bool has_minimum_count_method_v
Definition: traits.hpp:477
typename T::type get_type
Definition: traits.hpp:62
constexpr bool has_none_name_method_v
Definition: traits.hpp:363
constexpr bool has_runtime_children_method_v
Definition: traits.hpp:582
constexpr bool has_generate_runtime_help_data_method_v
Definition: traits.hpp:645
typename add_optional< T >::type add_optional_t
Definition: traits.hpp:226
constexpr bool has_minimum_value_method_v
Definition: traits.hpp:496
constexpr bool always_false_v
Definition: traits.hpp:55
std::integral_constant< decltype(Value), Value > integral_constant
Definition: traits.hpp:210
typename underlying_type< T >::type underlying_type_t
Definition: traits.hpp:106
constexpr bool has_short_name_method_v
Definition: traits.hpp:325
typename T::value_type get_value_type
Definition: traits.hpp:69
typename arg_extractor< T >::type arg_extractor_t
Definition: traits.hpp:747
constexpr bool has_long_name_method_v
Definition: traits.hpp:306
constexpr bool has_display_name_method_v
Definition: traits.hpp:344
constexpr bool is_specialisation_v
Definition: traits.hpp:148
constexpr bool has_push_back_method_v
Definition: traits.hpp:534
constexpr bool has_value_separator_method_v
Definition: traits.hpp:420
std::tuple_element_t< I+1, arg_extractor_t< T > > arg_type_at_index
Definition: traits.hpp:762
constexpr bool has_help_data_type_v
Definition: traits.hpp:553