39 requires detail::members_are_derived_from_valid_cli_class<T>();
40 requires detail::options_have_unique_long_name<T>();
41 requires detail::options_have_unique_short_name<T>();
42 requires detail::commands_have_unique_long_name<T>();
43 requires detail::positionals_have_variadic_at_end<T>();
44 requires detail::relations_are_well_formed<T>();
47template <ArgumentSpec T>
71 std::function<void(
const T&)>
73 std::string_view
env{};
82template <StringLiteral Name,
char ShortName, Nargs N, Action A>
84 detail::is_valid_long_option_name<Name>();
85 detail::is_valid_short_option_name(ShortName);
88 (N.max == -1 || N.min <= N.max);
90struct ArgImpl :
public OptionTag {
92 typename std::remove_cvref_t<decltype(std::get<1>(A.validate()))>::type;
93 ArgImpl() : ArgImpl(ArgParameter<value_type>{}) {}
94 ArgImpl(ArgParameter<value_type> param)
95 : param_(std::move(param)),
96 value_(param_.default_value.value_or(value_type{})) {}
99 ArgImpl(std::remove_pointer_t<value_type>& ref)
100 requires std::is_pointer_v<value_type>
102 ArgImpl(std::remove_pointer_t<value_type>& ref, ArgParameter<value_type> param)
103 requires std::is_pointer_v<value_type>
104 : param_(param), value_(&ref) {}
108 auto bind(std::remove_pointer_t<value_type>& ref) -> ArgImpl&
109 requires std::is_pointer_v<value_type>
114 auto operator=(std::remove_pointer_t<value_type>* ptr) -> ArgImpl&
115 requires std::is_pointer_v<value_type>
121 static constexpr auto name = Name;
122 static constexpr auto short_name = ShortName;
123 static constexpr auto nargs = N;
125 [[nodiscard]]
auto value() const -> const value_type& {
return value_; }
126 [[nodiscard]]
auto value() -> value_type& {
return value_; }
127 [[nodiscard]]
auto provided() const ->
bool {
return provided_; }
128 [[nodiscard]]
auto occurrences() const -> std::
size_t {
129 return occurrence_count_;
131 [[nodiscard]]
explicit operator bool()
const {
return value_present_; }
132 [[nodiscard]]
auto operator*() -> value_type& {
return value_; }
133 [[nodiscard]]
auto operator*() const -> const value_type& {
return value_; }
134 [[nodiscard]]
auto operator->() -> value_type* {
return &value_; }
135 [[nodiscard]]
auto operator->() const -> const value_type* {
return &value_; }
138 [[nodiscard]]
auto value_or(U&& fallback)
const -> value_type {
139 if (value_present_)
return value_;
140 return static_cast<value_type
>(std::forward<U>(fallback));
143 [[nodiscard]]
explicit operator std::optional<value_type>()
const {
144 if (value_present_)
return value_;
148 [[nodiscard]]
auto help_text() const -> const std::string_view {
151 [[nodiscard]]
auto hidden() const ->
bool {
return param_.hidden; }
152 [[nodiscard]]
auto deprecated() const -> std::string_view {
153 return param_.deprecated;
155 [[nodiscard]]
auto presence() const ->
Presence {
return param_.presence; }
156 [[nodiscard]]
auto env() const -> std::string_view {
return param_.env; }
157 [[nodiscard]]
auto default_value() const -> const std::
optional<value_type>& {
158 return param_.default_value;
162 static constexpr bool entry_is_optional =
163 std::remove_cvref_t<
decltype(A)>::entry_is_optional;
166 auto notify_option_seen() ->
void { ++occurrence_count_; }
169 auto invoke_action(std::optional<std::string_view> text, std::size_t arg_index,
170 std::size_t occurrence_nargs, std::size_t value_index,
171 bool mark_provided =
true) -> ActionResult<void> {
172 if (mark_provided) provided_ =
true;
173 ActionCtx<value_type> ctx{
175 .occurrences = occurrence_count_,
176 .nargs = occurrence_nargs,
177 .value_index = value_index,
178 .total_values = total_values_,
179 .arg = std::ref(value_),
181 if (text.has_value()) ++total_values_;
183 auto invoke_result = [&ctx, &text]() ->
auto {
184 if constexpr (entry_is_optional) {
185 return decltype(A)::invoke(
186 ctx, ActionResult<std::optional<std::string_view>>
::ok(text));
188 return decltype(A)::invoke(
192 if (invoke_result.has_error()) {
195 if (invoke_result.has_value()) value_present_ =
true;
200 auto on_parse() ->
void {
201 if (param_.on_parse) param_.on_parse(value_);
204 [[nodiscard]]
auto get_param() const -> const ArgParameter<value_type>& {
208 template <ArgumentSpec>
209 friend struct ::cli::Parser;
212 std::size_t total_values_{};
213 ArgParameter<value_type> param_;
215 std::size_t occurrence_count_{};
217 bool value_present_{param_.default_value.has_value()};
221concept ActionValue =
requires { std::remove_cvref_t<
decltype(A)>::validate(); };
223template <
auto... Args>
226 sizeof...(Args) && !
sizeof...(Args),
227 "Unsupported Arg<> parameter combination.\n"
228 "Supported forms (after the Name parameter):\n"
229 " Arg<Name, Action>\n"
230 " Arg<Name, Action, Nargs>\n"
231 " Arg<Name, ShortName, Action>\n"
232 " Arg<Name, ShortName, Action, Nargs>\n"
233 "Consider using Flag, Option, or ListOption for common argument kinds.");
236template <StringLiteral Name, auto A>
237 requires ActionValue<A>
238struct ArgAlias<Name, A> {
239 using type = ArgImpl<Name,
'\0',
nargs::one, A>;
242template <StringLiteral Name, auto A, auto N>
243 requires(ActionValue<A> &&
244 std::same_as<std::remove_cvref_t<
decltype(N)>, Nargs>)
245struct ArgAlias<Name, A, N> {
246 using type = ArgImpl<Name,
'\0', N, A>;
249template <StringLiteral Name,
char ShortName, auto A>
250 requires ActionValue<A>
251struct ArgAlias<Name, ShortName, A> {
252 using type = ArgImpl<Name, ShortName, nargs::one, A>;
255template <StringLiteral Name,
char ShortName, auto A, auto N>
256 requires(ActionValue<A> &&
257 std::same_as<std::remove_cvref_t<
decltype(N)>, Nargs>)
258struct ArgAlias<Name, ShortName, A, N> {
259 using type = ArgImpl<Name, ShortName, N, A>;
264template <Nargs N, Action A>
268 (N.max == -1 || N.min <= N.max);
272 typename std::remove_cvref_t<decltype(std::get<1>(A.validate()))>::type;
277 param_(std::move(param)) {}
283 if (param_.on_parse) param_.on_parse(value_);
288 [[nodiscard]]
auto provided() const ->
bool {
return provided_; }
290 return occurrence_count_;
292 [[nodiscard]]
explicit operator bool()
const {
return value_present_; }
300 if (value_present_)
return value_;
301 return static_cast<value_type>(std::forward<U>(fallback));
304 [[nodiscard]]
explicit operator std::optional<value_type>()
const {
305 if (value_present_)
return value_;
309 [[nodiscard]]
auto help_text() const -> const std::string_view {
312 [[nodiscard]]
auto hidden() const ->
bool {
return param_.hidden; }
314 return param_.deprecated;
317 [[nodiscard]]
auto env() const -> std::string_view {
return param_.env; }
319 return param_.default_value;
332 std::size_t occurrence_nargs = 1,
338 .occurrences = occurrence_count_,
339 .nargs = occurrence_nargs,
340 .value_index = value_index,
341 .total_values = total_values_,
342 .arg = std::ref(value_),
347 if (result.has_error()) {
350 if (result.has_value()) value_present_ =
true;
355 template <ArgumentSpec>
360 std::size_t occurrence_count_{};
361 std::size_t total_values_{};
363 bool value_present_{param_.default_value.has_value()};
382 template <std::
size_t N>
386 constexpr operator std::string_view()
const {
return text; }
411template <StringLiteral Name, ArgumentSpec T>
412 requires requires { detail::is_valid_command_name<Name>(); }
422 static constexpr auto name = Name;
426 [[nodiscard]]
auto provided() const ->
bool {
return provided_; }
427 [[nodiscard]]
auto help_text() const -> std::string_view {
return help_; }
428 [[nodiscard]]
auto hidden() const ->
bool {
return hidden_; }
435 std::string_view help_{};
437 std::string_view deprecated_{};
447struct ActionFor<std::
string> {
450 inline static constexpr auto write_to =
455struct ActionFor<bool> {
458 inline static constexpr auto write_to =
463struct ActionFor<std::filesystem::path> {
466 inline static constexpr auto write_to =
470template <std::
integral T>
472 inline static constexpr auto set_once =
475 inline static constexpr auto write_to =
479template <std::
floating_po
int T>
481 inline static constexpr auto set_once =
484 inline static constexpr auto write_to =
488template <
class T, Nargs N>
489struct PositionalActionFor {
490 inline static constexpr auto value = []() ->
auto {
491 if constexpr (N.max == 1) {
492 return ActionFor<T>::set_once;
494 return ActionFor<T>::push;
526using Arg =
typename detail::ArgAlias<Name, Args...>::type;
536template <StringLiteral Name,
char ShortName = '\0'>
552template <
class T, StringLiteral Name,
char ShortName = '\0'>
556template <StringLiteral Name,
char ShortName = '\0'>
560template <StringLiteral Name,
char ShortName = '\0'>
564template <StringLiteral Name,
char ShortName = '\0'>
568template <StringLiteral Name,
char ShortName = '\0'>
593template <
class T, StringLiteral Name,
char ShortName = '\0'>
619template <
class T, Nargs N = nargs::one>
625template <StringLiteral Name,
char ShortName = '\0'>
629template <StringLiteral Name,
char ShortName = '\0'>
633template <StringLiteral Name,
char ShortName = '\0'>
637template <StringLiteral Name,
char ShortName = '\0'>
Concept that validates an aggregate type as a well-formed CLI argument specification.
constexpr Nargs one_or_more
Accepts one or more values.
constexpr Nargs one
Accepts exactly one value.
Arg< Name, ShortName, action::print_help|action::exit_success, nargs::none > Help
A built-in help flag that prints help and exits with code 0.
PositionalImpl< N, detail::PositionalActionFor< T, N >::value > Positional
A typed positional argument.
constexpr auto ok() -> ActionResult< void >
Helper function for constructing a successful ActionResult<void>.
constexpr auto optional
Convenience constant for Presence::optional.
Option< double, Name, ShortName > DoubleOption
Option<double, Name, ShortName>.
Arg< Name, ShortName, detail::ActionFor< T >::push, N > ListOption
A multi-value option that appends each occurrence to a std::vector<T>.
Arg< Name, ShortName, detail::ActionFor< T >::write_to > BoundOption
An option whose parsed value is written directly into an external variable.
Option< std::string, Name, ShortName > StringOption
Option<std::string, Name, ShortName>.
BoundOption< int, Name, ShortName > BoundIntOption
BoundOption specialisation for int.
Option< int, Name, ShortName > IntOption
Option<int, Name, ShortName>.
BoundOption< std::filesystem::path, Name, ShortName > BoundPathOption
BoundOption specialisation for std::filesystem::path.
Option< std::filesystem::path, Name, ShortName > PathOption
Option<std::filesystem::path, Name, ShortName>.
BoundOption< double, Name, ShortName > BoundDoubleOption
BoundOption specialisation for double.
BoundOption< std::string, Name, ShortName > BoundStringOption
BoundOption specialisation for std::string.
Arg< Name, ShortName, pack::set_true, nargs::none > Flag
A boolean flag option that stores true when present.
typename detail::ArgAlias< Name, Args... >::type Arg
Defines a typed command-line argument specification.
Presence
Controls whether an option or positional argument is mandatory.
Arg< Name, ShortName, detail::ActionFor< T >::set_once > Option
A single-value option that stores the parsed result in T.
Context passed to each action function during pipeline execution.
The result type produced and consumed at each step of an action pipeline.
static constexpr auto ok(U &&v) -> ActionResult
Creates a success result holding value.
static constexpr auto fail(ParseError e) -> ActionResult
Creates a failure result carrying error.
Parameter bag used when constructing ArgImpl or PositionalImpl with named fields.
std::function< void(const T &)> on_parse
Callback invoked once after parsing completes.
std::string_view help
Help text shown in --help output.
std::optional< T > default_value
Default value when the argument is absent.
Presence presence
Whether the argument is required.
std::string_view env
Environment variable name to fall back to when the option is absent from the command line.
std::string_view deprecated
Optional deprecation message shown in generated help.
bool hidden
Whether this argument is omitted from generated help.
Parameter bag used when constructing a Command field.
std::string_view help
Brief description shown in the parent command's help.
std::string_view deprecated
Optional deprecation message shown in generated help.
bool hidden
Whether this command is omitted from generated help.
Tag base class for subcommand fields.
auto help_text() const -> std::string_view
static constexpr auto command_name() -> std::string_view
Command(CommandParameter param)
auto deprecated() const -> std::string_view
auto hidden() const -> bool
auto mark_provided() -> void
static constexpr auto name
auto provided() const -> bool
Tag base class for the Description field that provides the CLI's help text.
constexpr Description()=default
constexpr Description(const char(&s)[N])
constexpr Description(std::string_view)=delete
Specifies the minimum and maximum number of values an option or positional accepts.
The main parsing engine for a typed argument specification.
auto default_value() const -> const std::optional< value_type > &
auto provided() const -> bool
auto invoke_action(std::string_view text, std::size_t arg_index, std::size_t occurrence_nargs=1, std::size_t value_index=0) -> ActionResult< void >
auto presence() const -> Presence
typename std::remove_cvref_t< decltype(std::get< 1 >(A.validate()))>::type value_type
auto operator*() const -> const value_type &
static constexpr bool entry_is_optional
static constexpr auto nargs
auto help_text() const -> const std::string_view
auto operator->() const -> const value_type *
auto env() const -> std::string_view
auto get_param() const -> const ArgParameter< value_type > &
auto operator*() -> value_type &
auto value() const -> const value_type &
auto deprecated() const -> std::string_view
auto value_or(U &&fallback) const -> value_type
auto value() -> value_type &
auto hidden() const -> bool
PositionalImpl(ArgParameter< value_type > param)
auto occurrences() const -> std::size_t
auto operator->() -> value_type *
Tag base class for positional argument fields.
Compile-time string type usable as a non-type template parameter.