arg_router  1.4.0
C++ command line argument parsing and routing
min_max_value.hpp
1 // Copyright (C) 2022 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/exception.hpp"
8 #include "arg_router/parsing/parsing.hpp"
9 #include "arg_router/policy/policy.hpp"
10 
11 #include <limits>
12 
13 namespace arg_router::policy
14 {
21 template <typename ValueType, typename LessThanCompare = std::less<ValueType>>
23 {
24 public:
26  using value_type = ValueType;
28  using less_than_compare = LessThanCompare;
29 
40  constexpr min_max_value_t(std::optional<value_type> min,
41  std::optional<value_type> max,
42  less_than_compare compare = less_than_compare{}) noexcept :
43  min_(std::move(min)),
44  max_(std::move(max)), //
45  comp_{std::move(compare)}
46  {
47  }
48 
53  [[nodiscard]] constexpr const less_than_compare& comp() const noexcept { return comp_; }
54 
62  template <typename InputValueType, typename... Parents>
63  void validation_phase(const InputValueType& value,
64  [[maybe_unused]] const Parents&... parents) const
65  {
66  static_assert(sizeof...(Parents) >= 1, "Min/max value requires at least 1 parent");
67 
68  using node_type = boost::mp11::mp_first<std::tuple<Parents...>>;
69 
70  if (min_ && comp_(value, *min_)) {
72  parsing::node_token_type<node_type>()};
73  }
74  if (max_ && comp_(*max_, value)) {
76  parsing::node_token_type<node_type>()};
77  }
78  }
79 
80 private:
81  std::optional<value_type> min_;
82  std::optional<value_type> max_;
83  less_than_compare comp_;
84 };
85 
97 template <typename MinType, typename MaxType>
99 {
100  static_assert(!(std::is_void_v<MinType> && std::is_void_v<MaxType>),
101  "MinType and MaxType cannot both be void");
102 
103 public:
105  explicit min_max_value_ct() noexcept
106  {
107  if constexpr (!std::is_void_v<MinType>) {
108  static_assert(traits::has_value_type_v<MinType>, "MinType must have a value_type");
109  static_assert(std::is_integral_v<typename MinType::value_type> ||
110  std::is_enum_v<typename MinType::value_type>,
111  "MinType value_type must be integrals or enums");
112  }
113  if constexpr (!std::is_void_v<MaxType>) {
114  static_assert(traits::has_value_type_v<MaxType>, "MaxType must have a value_type");
115  static_assert(std::is_integral_v<typename MaxType::value_type> ||
116  std::is_enum_v<typename MaxType::value_type>,
117  "MaxType value_type must be integrals or enums");
118  }
119 
120  if constexpr (!std::is_void_v<MinType> && !std::is_void_v<MaxType>) {
121  static_assert(
122  std::is_same_v<typename MinType::value_type, typename MaxType::value_type>,
123  "MinType and MaxType must have the same value_type");
124  static_assert(MinType::value <= MaxType::value,
125  "MinType must be less than or equal to MaxType");
126  }
127  }
128 
134  template <typename T = MinType>
135  [[nodiscard]] constexpr static auto minimum_value(
136  // NOLINTNEXTLINE(*-named-parameter)
137  std::enable_if_t<!std::is_void_v<T>>* = nullptr) noexcept
138  {
139  return MinType::value;
140  }
141 
147  template <typename T = MaxType>
148  [[nodiscard]] constexpr static auto maximum_value(
149  // NOLINTNEXTLINE(*-named-parameter)
150  std::enable_if_t<!std::is_void_v<T>>* = nullptr) noexcept
151  {
152  return MaxType::value;
153  }
154 
163  template <typename InputValueType, typename... Parents>
164  void validation_phase(const InputValueType& value,
165  [[maybe_unused]] const Parents&... parents) const
166  {
167  static_assert(sizeof...(Parents) >= 1, "Min/max value requires at least 1 parent");
168 
169  using node_type = boost::mp11::mp_first<std::tuple<Parents...>>;
170 
171  if constexpr (!std::is_void_v<MinType>) {
172  if (value < minimum_value()) {
174  parsing::node_token_type<node_type>()};
175  }
176  }
177  if constexpr (!std::is_void_v<MaxType>) {
178  if (value > maximum_value()) {
180  parsing::node_token_type<node_type>()};
181  }
182  }
183  }
184 };
185 
195 template <typename ValueType, typename LessThanCompare = std::less<ValueType>>
196 [[nodiscard]] constexpr auto min_max_value(ValueType&& min,
197  ValueType&& max,
198  LessThanCompare&& compare = LessThanCompare{}) noexcept
199 {
200  return min_max_value_t<ValueType, LessThanCompare>{std::forward<ValueType>(min),
201  std::forward<ValueType>(max),
202  std::forward<LessThanCompare>(compare)};
203 }
204 
213 template <typename ValueType, typename LessThanCompare = std::less<ValueType>>
214 [[nodiscard]] constexpr auto min_value(ValueType&& min,
215  LessThanCompare&& compare = LessThanCompare{}) noexcept
216 {
217  return min_max_value_t<ValueType, LessThanCompare>{std::forward<ValueType>(min),
218  {},
219  std::forward<LessThanCompare>(compare)};
220 }
221 
230 template <typename ValueType, typename LessThanCompare = std::less<ValueType>>
231 [[nodiscard]] constexpr auto max_value(ValueType&& max,
232  LessThanCompare&& compare = LessThanCompare{}) noexcept
233 {
234  return min_max_value_t<ValueType, LessThanCompare>{{},
235  std::forward<ValueType>(max),
236  std::forward<LessThanCompare>(compare)};
237 }
238 
245 template <auto Min, auto Max>
246 [[nodiscard]] constexpr auto min_max_value() noexcept
247 {
249 }
250 
256 template <auto Min>
257 [[nodiscard]] constexpr auto min_value() noexcept
258 {
260 }
261 
267 template <auto Max>
268 [[nodiscard]] constexpr auto max_value() noexcept
269 {
271 }
272 
273 template <typename ValueType, typename LessThanCompare>
274 struct is_policy<min_max_value_t<ValueType, LessThanCompare>> : std::true_type {
275 };
276 
277 template <typename ValueType>
278 struct is_policy<min_max_value_t<ValueType>> : std::true_type {
279 };
280 
281 template <typename MinType, typename MaxType>
282 struct is_policy<min_max_value_ct<MinType, MaxType>> : std::true_type {
283 };
284 } // namespace arg_router::policy
constexpr static auto minimum_value(std::enable_if_t<!std::is_void_v< T >> *=nullptr) noexcept
constexpr static auto maximum_value(std::enable_if_t<!std::is_void_v< T >> *=nullptr) noexcept
void validation_phase(const InputValueType &value, [[maybe_unused]] const Parents &... parents) const
constexpr min_max_value_t(std::optional< value_type > min, std::optional< value_type > max, less_than_compare compare=less_than_compare{}) noexcept
constexpr const less_than_compare & comp() const noexcept
void validation_phase(const InputValueType &value, [[maybe_unused]] const Parents &... parents) const
constexpr auto max_value(ValueType &&max, LessThanCompare &&compare=LessThanCompare{}) noexcept
constexpr auto min_max_value(ValueType &&min, ValueType &&max, LessThanCompare &&compare=LessThanCompare{}) noexcept
constexpr auto min_value(ValueType &&min, LessThanCompare &&compare=LessThanCompare{}) noexcept
std::integral_constant< decltype(Value), Value > integral_constant
Definition: traits.hpp:210
@ minimum_value_not_reached
Parsed value is below the minimum.
@ maximum_value_exceeded
Parsed value is above the maximum.