arg_router  1.4.0
C++ command line argument parsing and routing
parse_target.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/parsing/token_type.hpp"
8 #include "arg_router/tree_node_fwd.hpp"
9 #include "arg_router/utility/type_hash.hpp"
10 #include "arg_router/utility/unsafe_any.hpp"
11 
12 #include <boost/mp11/algorithm.hpp>
13 
14 #include <functional>
15 
16 namespace arg_router
17 {
18 namespace parsing
19 {
29 {
30 public:
40  template <typename Node, typename... Parents>
41  parse_target(vector<token_type> tokens, const Node& node, const Parents&... parents) noexcept :
42  node_type_{utility::type_hash<std::decay_t<Node>>()}, tokens_(std::move(tokens))
43  {
44  static_assert(is_tree_node_v<Node>, "Target must be a tree_node");
45 
46  parse_ = [&node, &parents...](parse_target target) -> utility::unsafe_any {
47  if constexpr (std::is_void_v<decltype(node.parse(std::move(target), parents...))>) {
48  node.parse(std::move(target), parents...);
49  return {};
50  } else {
51  return node.parse(std::move(target), parents...);
52  }
53  };
54  }
55 
63  template <typename Node, typename... Parents>
64  // https://github.com/llvm/llvm-project/issues/37250
65  // NOLINTNEXTLINE(*-member-init)
66  explicit parse_target(const Node& node, //
67  const Parents&... parents) noexcept :
68  parse_target(vector<token_type>{}, node, parents...)
69  {
70  }
71 
76  [[nodiscard]] vector<token_type>& tokens() noexcept { return tokens_; }
77 
82  [[nodiscard]] const vector<token_type>& tokens() const noexcept { return tokens_; }
83 
88  [[nodiscard]] vector<parse_target>& sub_targets() noexcept { return sub_targets_; }
89 
94  [[nodiscard]] const vector<parse_target>& sub_targets() const noexcept { return sub_targets_; }
95 
100  [[nodiscard]] explicit operator bool() const noexcept { return static_cast<bool>(parse_); }
101 
106  [[nodiscard]] std::size_t node_type() const noexcept { return node_type_; }
107 
113  void add_sub_target(parse_target target) { sub_targets_.push_back(std::move(target)); }
114 
119  void tokens(vector<token_type> tokens) { tokens_ = std::move(tokens); }
120 
126  {
127  if (parse_) {
128  auto parse = std::move(parse_);
129  parse_ = nullptr;
130  return parse(std::move(*this));
131  }
132 
133  return {};
134  }
135 
136 private:
137  std::size_t node_type_;
138  vector<token_type> tokens_;
139  vector<parse_target> sub_targets_;
140  std::function<utility::unsafe_any(parse_target)> parse_;
141 };
142 } // namespace parsing
143 
144 namespace traits
145 {
150 template <typename T>
152  static_assert(is_tree_node_v<T>, "T must be node");
153 
154  template <typename U>
155  using type = decltype( //
156  std::declval<const U&>().template parse<>(std::declval<parsing::parse_target>()));
157 
158  constexpr static bool value = boost::mp11::mp_valid<type, T>::value;
159 };
160 
165 template <typename T>
166 constexpr static bool has_parse_method_v = has_parse_method<T>::value;
167 } // namespace traits
168 } // namespace arg_router
const vector< parse_target > & sub_targets() const noexcept
utility::unsafe_any operator()()
const vector< token_type > & tokens() const noexcept
vector< parse_target > & sub_targets() noexcept
parse_target(vector< token_type > tokens, const Node &node, const Parents &... parents) noexcept
void tokens(vector< token_type > tokens)
parse_target(const Node &node, const Parents &... parents) noexcept
std::size_t node_type() const noexcept
void add_sub_target(parse_target target)
vector< token_type > & tokens() noexcept
unsafe_any_t< sizeof(std::string_view)> unsafe_any
Definition: unsafe_any.hpp:210
std::vector< T, config::allocator< T > > vector
Definition: basic_types.hpp:39