arg_router  1.4.0
C++ command line argument parsing and routing
root.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/multi_lang/translation.hpp"
8 #include "arg_router/parsing/token_type.hpp"
9 #include "arg_router/utility/tuple_iterator.hpp"
10 
11 #include <variant>
12 
13 namespace arg_router::multi_lang
14 {
89 template <typename RootFactory, typename DefaultLanguageID, typename... SupportedLanguageIDs>
90 class root_t
91 {
92  using supported_language_ids = std::tuple<DefaultLanguageID, SupportedLanguageIDs...>;
93  constexpr static auto num_supported_ids = std::tuple_size_v<supported_language_ids>;
94 
95  static_assert(num_supported_ids > 1, "Must be more than one language supported");
96  static_assert(num_supported_ids ==
97  std::tuple_size_v<boost::mp11::mp_unique<supported_language_ids>>,
98  "Supported languages must be unique");
99 
100  using root_variant_t =
101  std::variant<std::decay_t<decltype(std::declval<RootFactory>()(
102  std::declval<translation<DefaultLanguageID>>()))>,
103  std::decay_t<decltype(std::declval<RootFactory>()(
104  std::declval<translation<SupportedLanguageIDs>>()))>...>;
105 
106 public:
113  explicit root_t(std::string_view language_id, const RootFactory& f)
114  {
115  utility::tuple_type_iterator<supported_language_ids>([&](auto I) {
116  using id = std::tuple_element_t<I, supported_language_ids>;
117 
118  if (root_ || (language_id != id::get())) {
119  return;
120  }
121 
122  root_.emplace(root_variant_t{f(translation<id>{})});
123  });
124 
125  // No match, so fall back to the default (the first language)
126  if (!root_) {
127  root_.emplace(root_variant_t{f(translation<DefaultLanguageID>{})});
128  }
129  }
130 
138  {
139  std::visit([&](const auto& root) { root.parse(std::move(args)); }, *root_);
140  }
141 
150  template <typename Iter, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Iter>, int>>>
151  void parse(Iter begin, Iter end) const
152  {
153  std::visit([&](const auto& root) { root.parse(begin, end); }, *root_);
154  }
155 
164  template <typename Container,
165  typename = std::enable_if_t<
166  !std::is_same_v<std::decay_t<Container>, vector<parsing::token_type>>>>
167  void parse(const Container& c) const
168  {
169  std::visit([&](const auto& root) { root.parse(c); }, *root_);
170  }
171 
177  void parse(int argc, char** argv) const
178  {
179  std::visit([&](const auto& root) { root.parse(argc, argv); }, *root_);
180  }
181 
186  void help(std::ostream& stream) const
187  {
188  std::visit([&](const auto& root) { root.help(stream); }, *root_);
189  }
190 
195  [[nodiscard]] string help() const
196  {
197  return std::visit([](const auto& root) { root.help(); }, *root_);
198  }
199 
200 private:
201  // Only optional due to the delayed initialisation
202  std::optional<root_variant_t> root_;
203 };
204 
220 template <typename DefaultLanguageID, typename... SupportedLanguageIDs, typename RootFactory>
221 auto root(std::string_view language_id, const RootFactory& f)
222 {
223  return root_t<RootFactory, DefaultLanguageID, SupportedLanguageIDs...>{language_id, f};
224 }
225 } // namespace arg_router::multi_lang
void parse(vector< parsing::token_type > args) const
Definition: root.hpp:137
void help(std::ostream &stream) const
Definition: root.hpp:186
void parse(int argc, char **argv) const
Definition: root.hpp:177
root_t(std::string_view language_id, const RootFactory &f)
Definition: root.hpp:113
void parse(const Container &c) const
Definition: root.hpp:167
void parse(Iter begin, Iter end) const
Definition: root.hpp:151
auto root(std::string_view language_id, const RootFactory &f)
Definition: root.hpp:221
std::vector< T, config::allocator< T > > vector
Definition: basic_types.hpp:39