Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 08:52:37

0001 // Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
0002 // under NSF AWARD 1414736 and by the respective contributors.
0003 // All rights reserved.
0004 //
0005 // SPDX-License-Identifier: BSD-3-Clause
0006 
0007 #pragma once
0008 
0009 // IWYU pragma: private, include "CLI/CLI.hpp"
0010 
0011 // [CLI11:public_includes:set]
0012 #include <algorithm>
0013 #include <cstdint>
0014 #include <functional>
0015 #include <iostream>
0016 #include <iterator>
0017 #include <memory>
0018 #include <numeric>
0019 #include <set>
0020 #include <sstream>
0021 #include <string>
0022 #include <utility>
0023 #include <vector>
0024 // [CLI11:public_includes:end]
0025 
0026 // CLI Library includes
0027 #include "ConfigFwd.hpp"
0028 #include "Error.hpp"
0029 #include "FormatterFwd.hpp"
0030 #include "Macros.hpp"
0031 #include "Option.hpp"
0032 #include "Split.hpp"
0033 #include "StringTools.hpp"
0034 #include "TypeTools.hpp"
0035 
0036 namespace CLI {
0037 // [CLI11:app_hpp:verbatim]
0038 
0039 #ifndef CLI11_PARSE
0040 #define CLI11_PARSE(app, ...)                                                                                          \
0041     try {                                                                                                              \
0042         (app).parse(__VA_ARGS__);                                                                                      \
0043     } catch(const CLI::ParseError &e) {                                                                                \
0044         return (app).exit(e);                                                                                          \
0045     }
0046 #endif
0047 
0048 namespace detail {
0049 enum class Classifier { NONE, POSITIONAL_MARK, SHORT, LONG, WINDOWS_STYLE, SUBCOMMAND, SUBCOMMAND_TERMINATOR };
0050 struct AppFriend;
0051 }  // namespace detail
0052 
0053 namespace FailureMessage {
0054 /// Printout a clean, simple message on error (the default in CLI11 1.5+)
0055 CLI11_INLINE std::string simple(const App *app, const Error &e);
0056 
0057 /// Printout the full help string on error (if this fn is set, the old default for CLI11)
0058 CLI11_INLINE std::string help(const App *app, const Error &e);
0059 }  // namespace FailureMessage
0060 
0061 /// enumeration of modes of how to deal with extras in config files
0062 
0063 enum class config_extras_mode : char { error = 0, ignore, ignore_all, capture };
0064 
0065 class App;
0066 
0067 using App_p = std::shared_ptr<App>;
0068 
0069 namespace detail {
0070 /// helper functions for adding in appropriate flag modifiers for add_flag
0071 
0072 template <typename T, enable_if_t<!std::is_integral<T>::value || (sizeof(T) <= 1U), detail::enabler> = detail::dummy>
0073 Option *default_flag_modifiers(Option *opt) {
0074     return opt->always_capture_default();
0075 }
0076 
0077 /// summing modifiers
0078 template <typename T, enable_if_t<std::is_integral<T>::value && (sizeof(T) > 1U), detail::enabler> = detail::dummy>
0079 Option *default_flag_modifiers(Option *opt) {
0080     return opt->multi_option_policy(MultiOptionPolicy::Sum)->default_str("0")->force_callback();
0081 }
0082 
0083 }  // namespace detail
0084 
0085 class Option_group;
0086 /// Creates a command line program, with very few defaults.
0087 /** To use, create a new `Program()` instance with `argc`, `argv`, and a help description. The templated
0088  *  add_option methods make it easy to prepare options. Remember to call `.start` before starting your
0089  * program, so that the options can be evaluated and the help option doesn't accidentally run your program. */
0090 class App {
0091     friend Option;
0092     friend detail::AppFriend;
0093 
0094   protected:
0095     // This library follows the Google style guide for member names ending in underscores
0096 
0097     /// @name Basics
0098     ///@{
0099 
0100     /// Subcommand name or program name (from parser if name is empty)
0101     std::string name_{};
0102 
0103     /// Description of the current program/subcommand
0104     std::string description_{};
0105 
0106     /// If true, allow extra arguments (ie, don't throw an error). INHERITABLE
0107     bool allow_extras_{false};
0108 
0109     /// If ignore, allow extra arguments in the ini file (ie, don't throw an error). INHERITABLE
0110     /// if error, error on an extra argument, and if capture feed it to the app
0111     config_extras_mode allow_config_extras_{config_extras_mode::ignore};
0112 
0113     ///  If true, cease processing on an unrecognized option (implies allow_extras) INHERITABLE
0114     bool prefix_command_{false};
0115 
0116     /// If set to true the name was automatically generated from the command line vs a user set name
0117     bool has_automatic_name_{false};
0118 
0119     /// If set to true the subcommand is required to be processed and used, ignored for main app
0120     bool required_{false};
0121 
0122     /// If set to true the subcommand is disabled and cannot be used, ignored for main app
0123     bool disabled_{false};
0124 
0125     /// Flag indicating that the pre_parse_callback has been triggered
0126     bool pre_parse_called_{false};
0127 
0128     /// Flag indicating that the callback for the subcommand should be executed immediately on parse completion which is
0129     /// before help or ini files are processed. INHERITABLE
0130     bool immediate_callback_{false};
0131 
0132     /// This is a function that runs prior to the start of parsing
0133     std::function<void(std::size_t)> pre_parse_callback_{};
0134 
0135     /// This is a function that runs when parsing has finished.
0136     std::function<void()> parse_complete_callback_{};
0137 
0138     /// This is a function that runs when all processing has completed
0139     std::function<void()> final_callback_{};
0140 
0141     ///@}
0142     /// @name Options
0143     ///@{
0144 
0145     /// The default values for options, customizable and changeable INHERITABLE
0146     OptionDefaults option_defaults_{};
0147 
0148     /// The list of options, stored locally
0149     std::vector<Option_p> options_{};
0150 
0151     ///@}
0152     /// @name Help
0153     ///@{
0154 
0155     /// Usage to put after program/subcommand description in the help output INHERITABLE
0156     std::string usage_{};
0157 
0158     /// This is a function that generates a usage to put after program/subcommand description in help output
0159     std::function<std::string()> usage_callback_{};
0160 
0161     /// Footer to put after all options in the help output INHERITABLE
0162     std::string footer_{};
0163 
0164     /// This is a function that generates a footer to put after all other options in help output
0165     std::function<std::string()> footer_callback_{};
0166 
0167     /// A pointer to the help flag if there is one INHERITABLE
0168     Option *help_ptr_{nullptr};
0169 
0170     /// A pointer to the help all flag if there is one INHERITABLE
0171     Option *help_all_ptr_{nullptr};
0172 
0173     /// A pointer to a version flag if there is one
0174     Option *version_ptr_{nullptr};
0175 
0176     /// This is the formatter for help printing. Default provided. INHERITABLE (same pointer)
0177     std::shared_ptr<FormatterBase> formatter_{new Formatter()};
0178 
0179     /// The error message printing function INHERITABLE
0180     std::function<std::string(const App *, const Error &e)> failure_message_{FailureMessage::simple};
0181 
0182     ///@}
0183     /// @name Parsing
0184     ///@{
0185 
0186     using missing_t = std::vector<std::pair<detail::Classifier, std::string>>;
0187 
0188     /// Pair of classifier, string for missing options. (extra detail is removed on returning from parse)
0189     ///
0190     /// This is faster and cleaner than storing just a list of strings and reparsing. This may contain the -- separator.
0191     missing_t missing_{};
0192 
0193     /// This is a list of pointers to options with the original parse order
0194     std::vector<Option *> parse_order_{};
0195 
0196     /// This is a list of the subcommands collected, in order
0197     std::vector<App *> parsed_subcommands_{};
0198 
0199     /// this is a list of subcommands that are exclusionary to this one
0200     std::set<App *> exclude_subcommands_{};
0201 
0202     /// This is a list of options which are exclusionary to this App, if the options were used this subcommand should
0203     /// not be
0204     std::set<Option *> exclude_options_{};
0205 
0206     /// this is a list of subcommands or option groups that are required by this one, the list is not mutual,  the
0207     /// listed subcommands do not require this one
0208     std::set<App *> need_subcommands_{};
0209 
0210     /// This is a list of options which are required by this app, the list is not mutual, listed options do not need the
0211     /// subcommand not be
0212     std::set<Option *> need_options_{};
0213 
0214     ///@}
0215     /// @name Subcommands
0216     ///@{
0217 
0218     /// Storage for subcommand list
0219     std::vector<App_p> subcommands_{};
0220 
0221     /// If true, the program name is not case-sensitive INHERITABLE
0222     bool ignore_case_{false};
0223 
0224     /// If true, the program should ignore underscores INHERITABLE
0225     bool ignore_underscore_{false};
0226 
0227     /// Allow options or other arguments to fallthrough, so that parent commands can collect options after subcommand.
0228     /// INHERITABLE
0229     bool fallthrough_{false};
0230 
0231     /// Allow subcommands to fallthrough, so that parent commands can trigger other subcommands after subcommand.
0232     bool subcommand_fallthrough_{true};
0233 
0234     /// Allow '/' for options for Windows like options. Defaults to true on Windows, false otherwise. INHERITABLE
0235     bool allow_windows_style_options_{
0236 #ifdef _WIN32
0237         true
0238 #else
0239         false
0240 #endif
0241     };
0242     /// specify that positional arguments come at the end of the argument sequence not inheritable
0243     bool positionals_at_end_{false};
0244 
0245     enum class startup_mode : char { stable, enabled, disabled };
0246     /// specify the startup mode for the app
0247     /// stable=no change, enabled= startup enabled, disabled=startup disabled
0248     startup_mode default_startup{startup_mode::stable};
0249 
0250     /// if set to true the subcommand can be triggered via configuration files INHERITABLE
0251     bool configurable_{false};
0252 
0253     /// If set to true positional options are validated before assigning INHERITABLE
0254     bool validate_positionals_{false};
0255 
0256     /// If set to true optional vector arguments are validated before assigning INHERITABLE
0257     bool validate_optional_arguments_{false};
0258 
0259     /// indicator that the subcommand is silent and won't show up in subcommands list
0260     /// This is potentially useful as a modifier subcommand
0261     bool silent_{false};
0262 
0263     /// indicator that the subcommand should allow non-standard option arguments, such as -single_dash_flag
0264     bool allow_non_standard_options_{false};
0265 
0266     /// Counts the number of times this command/subcommand was parsed
0267     std::uint32_t parsed_{0U};
0268 
0269     /// Minimum required subcommands (not inheritable!)
0270     std::size_t require_subcommand_min_{0};
0271 
0272     /// Max number of subcommands allowed (parsing stops after this number). 0 is unlimited INHERITABLE
0273     std::size_t require_subcommand_max_{0};
0274 
0275     /// Minimum required options (not inheritable!)
0276     std::size_t require_option_min_{0};
0277 
0278     /// Max number of options allowed. 0 is unlimited (not inheritable)
0279     std::size_t require_option_max_{0};
0280 
0281     /// A pointer to the parent if this is a subcommand
0282     App *parent_{nullptr};
0283 
0284     /// The group membership INHERITABLE
0285     std::string group_{"SUBCOMMANDS"};
0286 
0287     /// Alias names for the subcommand
0288     std::vector<std::string> aliases_{};
0289 
0290     ///@}
0291     /// @name Config
0292     ///@{
0293 
0294     /// Pointer to the config option
0295     Option *config_ptr_{nullptr};
0296 
0297     /// This is the formatter for help printing. Default provided. INHERITABLE (same pointer)
0298     std::shared_ptr<Config> config_formatter_{new ConfigTOML()};
0299 
0300     ///@}
0301 
0302 #ifdef _WIN32
0303     /// When normalizing argv to UTF-8 on Windows, this is the storage for normalized args.
0304     std::vector<std::string> normalized_argv_{};
0305 
0306     /// When normalizing argv to UTF-8 on Windows, this is the `char**` value returned to the user.
0307     std::vector<char *> normalized_argv_view_{};
0308 #endif
0309 
0310     /// Special private constructor for subcommand
0311     App(std::string app_description, std::string app_name, App *parent);
0312 
0313   public:
0314     /// @name Basic
0315     ///@{
0316 
0317     /// Create a new program. Pass in the same arguments as main(), along with a help string.
0318     explicit App(std::string app_description = "", std::string app_name = "")
0319         : App(app_description, app_name, nullptr) {
0320         set_help_flag("-h,--help", "Print this help message and exit");
0321     }
0322 
0323     App(const App &) = delete;
0324     App &operator=(const App &) = delete;
0325 
0326     /// virtual destructor
0327     virtual ~App() = default;
0328 
0329     /// Convert the contents of argv to UTF-8. Only does something on Windows, does nothing elsewhere.
0330     CLI11_NODISCARD char **ensure_utf8(char **argv);
0331 
0332     /// Set a callback for execution when all parsing and processing has completed
0333     ///
0334     /// Due to a bug in c++11,
0335     /// it is not possible to overload on std::function (fixed in c++14
0336     /// and backported to c++11 on newer compilers). Use capture by reference
0337     /// to get a pointer to App if needed.
0338     App *callback(std::function<void()> app_callback) {
0339         if(immediate_callback_) {
0340             parse_complete_callback_ = std::move(app_callback);
0341         } else {
0342             final_callback_ = std::move(app_callback);
0343         }
0344         return this;
0345     }
0346 
0347     /// Set a callback for execution when all parsing and processing has completed
0348     /// aliased as callback
0349     App *final_callback(std::function<void()> app_callback) {
0350         final_callback_ = std::move(app_callback);
0351         return this;
0352     }
0353 
0354     /// Set a callback to execute when parsing has completed for the app
0355     ///
0356     App *parse_complete_callback(std::function<void()> pc_callback) {
0357         parse_complete_callback_ = std::move(pc_callback);
0358         return this;
0359     }
0360 
0361     /// Set a callback to execute prior to parsing.
0362     ///
0363     App *preparse_callback(std::function<void(std::size_t)> pp_callback) {
0364         pre_parse_callback_ = std::move(pp_callback);
0365         return this;
0366     }
0367 
0368     /// Set a name for the app (empty will use parser to set the name)
0369     App *name(std::string app_name = "");
0370 
0371     /// Set an alias for the app
0372     App *alias(std::string app_name);
0373 
0374     /// Remove the error when extras are left over on the command line.
0375     App *allow_extras(bool allow = true) {
0376         allow_extras_ = allow;
0377         return this;
0378     }
0379 
0380     /// Remove the error when extras are left over on the command line.
0381     App *required(bool require = true) {
0382         required_ = require;
0383         return this;
0384     }
0385 
0386     /// Disable the subcommand or option group
0387     App *disabled(bool disable = true) {
0388         disabled_ = disable;
0389         return this;
0390     }
0391 
0392     /// silence the subcommand from showing up in the processed list
0393     App *silent(bool silence = true) {
0394         silent_ = silence;
0395         return this;
0396     }
0397 
0398     /// allow non standard option names
0399     App *allow_non_standard_option_names(bool allowed = true) {
0400         allow_non_standard_options_ = allowed;
0401         return this;
0402     }
0403 
0404     /// Set the subcommand to be disabled by default, so on clear(), at the start of each parse it is disabled
0405     App *disabled_by_default(bool disable = true) {
0406         if(disable) {
0407             default_startup = startup_mode::disabled;
0408         } else {
0409             default_startup = (default_startup == startup_mode::enabled) ? startup_mode::enabled : startup_mode::stable;
0410         }
0411         return this;
0412     }
0413 
0414     /// Set the subcommand to be enabled by default, so on clear(), at the start of each parse it is enabled (not
0415     /// disabled)
0416     App *enabled_by_default(bool enable = true) {
0417         if(enable) {
0418             default_startup = startup_mode::enabled;
0419         } else {
0420             default_startup =
0421                 (default_startup == startup_mode::disabled) ? startup_mode::disabled : startup_mode::stable;
0422         }
0423         return this;
0424     }
0425 
0426     /// Set the subcommand callback to be executed immediately on subcommand completion
0427     App *immediate_callback(bool immediate = true);
0428 
0429     /// Set the subcommand to validate positional arguments before assigning
0430     App *validate_positionals(bool validate = true) {
0431         validate_positionals_ = validate;
0432         return this;
0433     }
0434 
0435     /// Set the subcommand to validate optional vector arguments before assigning
0436     App *validate_optional_arguments(bool validate = true) {
0437         validate_optional_arguments_ = validate;
0438         return this;
0439     }
0440 
0441     /// ignore extras in config files
0442     App *allow_config_extras(bool allow = true) {
0443         if(allow) {
0444             allow_config_extras_ = config_extras_mode::capture;
0445             allow_extras_ = true;
0446         } else {
0447             allow_config_extras_ = config_extras_mode::error;
0448         }
0449         return this;
0450     }
0451 
0452     /// ignore extras in config files
0453     App *allow_config_extras(config_extras_mode mode) {
0454         allow_config_extras_ = mode;
0455         return this;
0456     }
0457 
0458     /// Do not parse anything after the first unrecognized option (if true) all remaining arguments are stored in
0459     /// remaining args
0460     App *prefix_command(bool is_prefix = true) {
0461         prefix_command_ = is_prefix;
0462         return this;
0463     }
0464 
0465     /// Ignore case. Subcommands inherit value.
0466     App *ignore_case(bool value = true);
0467 
0468     /// Allow windows style options, such as `/opt`. First matching short or long name used. Subcommands inherit
0469     /// value.
0470     App *allow_windows_style_options(bool value = true) {
0471         allow_windows_style_options_ = value;
0472         return this;
0473     }
0474 
0475     /// Specify that the positional arguments are only at the end of the sequence
0476     App *positionals_at_end(bool value = true) {
0477         positionals_at_end_ = value;
0478         return this;
0479     }
0480 
0481     /// Specify that the subcommand can be triggered by a config file
0482     App *configurable(bool value = true) {
0483         configurable_ = value;
0484         return this;
0485     }
0486 
0487     /// Ignore underscore. Subcommands inherit value.
0488     App *ignore_underscore(bool value = true);
0489 
0490     /// Set the help formatter
0491     App *formatter(std::shared_ptr<FormatterBase> fmt) {
0492         formatter_ = fmt;
0493         return this;
0494     }
0495 
0496     /// Set the help formatter
0497     App *formatter_fn(std::function<std::string(const App *, std::string, AppFormatMode)> fmt) {
0498         formatter_ = std::make_shared<FormatterLambda>(fmt);
0499         return this;
0500     }
0501 
0502     /// Set the config formatter
0503     App *config_formatter(std::shared_ptr<Config> fmt) {
0504         config_formatter_ = fmt;
0505         return this;
0506     }
0507 
0508     /// Check to see if this subcommand was parsed, true only if received on command line.
0509     CLI11_NODISCARD bool parsed() const { return parsed_ > 0; }
0510 
0511     /// Get the OptionDefault object, to set option defaults
0512     OptionDefaults *option_defaults() { return &option_defaults_; }
0513 
0514     ///@}
0515     /// @name Adding options
0516     ///@{
0517 
0518     /// Add an option, will automatically understand the type for common types.
0519     ///
0520     /// To use, create a variable with the expected type, and pass it in after the name.
0521     /// After start is called, you can use count to see if the value was passed, and
0522     /// the value will be initialized properly. Numbers, vectors, and strings are supported.
0523     ///
0524     /// ->required(), ->default, and the validators are options,
0525     /// The positional options take an optional number of arguments.
0526     ///
0527     /// For example,
0528     ///
0529     ///     std::string filename;
0530     ///     program.add_option("filename", filename, "description of filename");
0531     ///
0532     Option *add_option(std::string option_name,
0533                        callback_t option_callback,
0534                        std::string option_description = "",
0535                        bool defaulted = false,
0536                        std::function<std::string()> func = {});
0537 
0538     /// Add option for assigning to a variable
0539     template <typename AssignTo,
0540               typename ConvertTo = AssignTo,
0541               enable_if_t<!std::is_const<ConvertTo>::value, detail::enabler> = detail::dummy>
0542     Option *add_option(std::string option_name,
0543                        AssignTo &variable,  ///< The variable to set
0544                        std::string option_description = "") {
0545 
0546         auto fun = [&variable](const CLI::results_t &res) {  // comment for spacing
0547             return detail::lexical_conversion<AssignTo, ConvertTo>(res, variable);
0548         };
0549 
0550         Option *opt = add_option(option_name, fun, option_description, false, [&variable]() {
0551             return CLI::detail::checked_to_string<AssignTo, ConvertTo>(variable);
0552         });
0553         opt->type_name(detail::type_name<ConvertTo>());
0554         // these must be actual lvalues since (std::max) sometimes is defined in terms of references and references
0555         // to structs used in the evaluation can be temporary so that would cause issues.
0556         auto Tcount = detail::type_count<AssignTo>::value;
0557         auto XCcount = detail::type_count<ConvertTo>::value;
0558         opt->type_size(detail::type_count_min<ConvertTo>::value, (std::max)(Tcount, XCcount));
0559         opt->expected(detail::expected_count<ConvertTo>::value);
0560         opt->run_callback_for_default();
0561         return opt;
0562     }
0563 
0564     /// Add option for assigning to a variable
0565     template <typename AssignTo, enable_if_t<!std::is_const<AssignTo>::value, detail::enabler> = detail::dummy>
0566     Option *add_option_no_stream(std::string option_name,
0567                                  AssignTo &variable,  ///< The variable to set
0568                                  std::string option_description = "") {
0569 
0570         auto fun = [&variable](const CLI::results_t &res) {  // comment for spacing
0571             return detail::lexical_conversion<AssignTo, AssignTo>(res, variable);
0572         };
0573 
0574         Option *opt = add_option(option_name, fun, option_description, false, []() { return std::string{}; });
0575         opt->type_name(detail::type_name<AssignTo>());
0576         opt->type_size(detail::type_count_min<AssignTo>::value, detail::type_count<AssignTo>::value);
0577         opt->expected(detail::expected_count<AssignTo>::value);
0578         opt->run_callback_for_default();
0579         return opt;
0580     }
0581 
0582     /// Add option for a callback of a specific type
0583     template <typename ArgType>
0584     Option *add_option_function(std::string option_name,
0585                                 const std::function<void(const ArgType &)> &func,  ///< the callback to execute
0586                                 std::string option_description = "") {
0587 
0588         auto fun = [func](const CLI::results_t &res) {
0589             ArgType variable;
0590             bool result = detail::lexical_conversion<ArgType, ArgType>(res, variable);
0591             if(result) {
0592                 func(variable);
0593             }
0594             return result;
0595         };
0596 
0597         Option *opt = add_option(option_name, std::move(fun), option_description, false);
0598         opt->type_name(detail::type_name<ArgType>());
0599         opt->type_size(detail::type_count_min<ArgType>::value, detail::type_count<ArgType>::value);
0600         opt->expected(detail::expected_count<ArgType>::value);
0601         return opt;
0602     }
0603 
0604     /// Add option with no description or variable assignment
0605     Option *add_option(std::string option_name) {
0606         return add_option(option_name, CLI::callback_t{}, std::string{}, false);
0607     }
0608 
0609     /// Add option with description but with no variable assignment or callback
0610     template <typename T,
0611               enable_if_t<std::is_const<T>::value && std::is_constructible<std::string, T>::value, detail::enabler> =
0612                   detail::dummy>
0613     Option *add_option(std::string option_name, T &option_description) {
0614         return add_option(option_name, CLI::callback_t(), option_description, false);
0615     }
0616 
0617     /// Set a help flag, replace the existing one if present
0618     Option *set_help_flag(std::string flag_name = "", const std::string &help_description = "");
0619 
0620     /// Set a help all flag, replaced the existing one if present
0621     Option *set_help_all_flag(std::string help_name = "", const std::string &help_description = "");
0622 
0623     /// Set a version flag and version display string, replace the existing one if present
0624     Option *set_version_flag(std::string flag_name = "",
0625                              const std::string &versionString = "",
0626                              const std::string &version_help = "Display program version information and exit");
0627 
0628     /// Generate the version string through a callback function
0629     Option *set_version_flag(std::string flag_name,
0630                              std::function<std::string()> vfunc,
0631                              const std::string &version_help = "Display program version information and exit");
0632 
0633   private:
0634     /// Internal function for adding a flag
0635     Option *_add_flag_internal(std::string flag_name, CLI::callback_t fun, std::string flag_description);
0636 
0637   public:
0638     /// Add a flag with no description or variable assignment
0639     Option *add_flag(std::string flag_name) { return _add_flag_internal(flag_name, CLI::callback_t(), std::string{}); }
0640 
0641     /// Add flag with description but with no variable assignment or callback
0642     /// takes a constant string,  if a variable string is passed that variable will be assigned the results from the
0643     /// flag
0644     template <typename T,
0645               enable_if_t<std::is_const<T>::value && std::is_constructible<std::string, T>::value, detail::enabler> =
0646                   detail::dummy>
0647     Option *add_flag(std::string flag_name, T &flag_description) {
0648         return _add_flag_internal(flag_name, CLI::callback_t(), flag_description);
0649     }
0650 
0651     /// Other type version accepts all other types that are not vectors such as bool, enum, string or other classes
0652     /// that can be converted from a string
0653     template <typename T,
0654               enable_if_t<!detail::is_mutable_container<T>::value && !std::is_const<T>::value &&
0655                               !std::is_constructible<std::function<void(int)>, T>::value,
0656                           detail::enabler> = detail::dummy>
0657     Option *add_flag(std::string flag_name,
0658                      T &flag_result,  ///< A variable holding the flag result
0659                      std::string flag_description = "") {
0660 
0661         CLI::callback_t fun = [&flag_result](const CLI::results_t &res) {
0662             using CLI::detail::lexical_cast;
0663             return lexical_cast(res[0], flag_result);
0664         };
0665         auto *opt = _add_flag_internal(flag_name, std::move(fun), std::move(flag_description));
0666         return detail::default_flag_modifiers<T>(opt);
0667     }
0668 
0669     /// Vector version to capture multiple flags.
0670     template <typename T,
0671               enable_if_t<!std::is_assignable<std::function<void(std::int64_t)> &, T>::value, detail::enabler> =
0672                   detail::dummy>
0673     Option *add_flag(std::string flag_name,
0674                      std::vector<T> &flag_results,  ///< A vector of values with the flag results
0675                      std::string flag_description = "") {
0676         CLI::callback_t fun = [&flag_results](const CLI::results_t &res) {
0677             bool retval = true;
0678             for(const auto &elem : res) {
0679                 using CLI::detail::lexical_cast;
0680                 flag_results.emplace_back();
0681                 retval &= lexical_cast(elem, flag_results.back());
0682             }
0683             return retval;
0684         };
0685         return _add_flag_internal(flag_name, std::move(fun), std::move(flag_description))
0686             ->multi_option_policy(MultiOptionPolicy::TakeAll)
0687             ->run_callback_for_default();
0688     }
0689 
0690     /// Add option for callback that is triggered with a true flag and takes no arguments
0691     Option *add_flag_callback(std::string flag_name,
0692                               std::function<void(void)> function,  ///< A function to call, void(void)
0693                               std::string flag_description = "");
0694 
0695     /// Add option for callback with an integer value
0696     Option *add_flag_function(std::string flag_name,
0697                               std::function<void(std::int64_t)> function,  ///< A function to call, void(int)
0698                               std::string flag_description = "");
0699 
0700 #ifdef CLI11_CPP14
0701     /// Add option for callback (C++14 or better only)
0702     Option *add_flag(std::string flag_name,
0703                      std::function<void(std::int64_t)> function,  ///< A function to call, void(std::int64_t)
0704                      std::string flag_description = "") {
0705         return add_flag_function(std::move(flag_name), std::move(function), std::move(flag_description));
0706     }
0707 #endif
0708 
0709     /// Set a configuration ini file option, or clear it if no name passed
0710     Option *set_config(std::string option_name = "",
0711                        std::string default_filename = "",
0712                        const std::string &help_message = "Read an ini file",
0713                        bool config_required = false);
0714 
0715     /// Removes an option from the App. Takes an option pointer. Returns true if found and removed.
0716     bool remove_option(Option *opt);
0717 
0718     /// creates an option group as part of the given app
0719     template <typename T = Option_group>
0720     T *add_option_group(std::string group_name, std::string group_description = "") {
0721         if(!detail::valid_alias_name_string(group_name)) {
0722             throw IncorrectConstruction("option group names may not contain newlines or null characters");
0723         }
0724         auto option_group = std::make_shared<T>(std::move(group_description), group_name, this);
0725         auto *ptr = option_group.get();
0726         // move to App_p for overload resolution on older gcc versions
0727         App_p app_ptr = std::dynamic_pointer_cast<App>(option_group);
0728         add_subcommand(std::move(app_ptr));
0729         return ptr;
0730     }
0731 
0732     ///@}
0733     /// @name Subcommands
0734     ///@{
0735 
0736     /// Add a subcommand. Inherits INHERITABLE and OptionDefaults, and help flag
0737     App *add_subcommand(std::string subcommand_name = "", std::string subcommand_description = "");
0738 
0739     /// Add a previously created app as a subcommand
0740     App *add_subcommand(CLI::App_p subcom);
0741 
0742     /// Removes a subcommand from the App. Takes a subcommand pointer. Returns true if found and removed.
0743     bool remove_subcommand(App *subcom);
0744 
0745     /// Check to see if a subcommand is part of this command (doesn't have to be in command line)
0746     /// returns the first subcommand if passed a nullptr
0747     App *get_subcommand(const App *subcom) const;
0748 
0749     /// Check to see if a subcommand is part of this command (text version)
0750     CLI11_NODISCARD App *get_subcommand(std::string subcom) const;
0751 
0752     /// Get a subcommand by name (noexcept non-const version)
0753     /// returns null if subcommand doesn't exist
0754     CLI11_NODISCARD App *get_subcommand_no_throw(std::string subcom) const noexcept;
0755 
0756     /// Get a pointer to subcommand by index
0757     CLI11_NODISCARD App *get_subcommand(int index = 0) const;
0758 
0759     /// Check to see if a subcommand is part of this command and get a shared_ptr to it
0760     CLI::App_p get_subcommand_ptr(App *subcom) const;
0761 
0762     /// Check to see if a subcommand is part of this command (text version)
0763     CLI11_NODISCARD CLI::App_p get_subcommand_ptr(std::string subcom) const;
0764 
0765     /// Get an owning pointer to subcommand by index
0766     CLI11_NODISCARD CLI::App_p get_subcommand_ptr(int index = 0) const;
0767 
0768     /// Check to see if an option group is part of this App
0769     CLI11_NODISCARD App *get_option_group(std::string group_name) const;
0770 
0771     /// No argument version of count counts the number of times this subcommand was
0772     /// passed in. The main app will return 1. Unnamed subcommands will also return 1 unless
0773     /// otherwise modified in a callback
0774     CLI11_NODISCARD std::size_t count() const { return parsed_; }
0775 
0776     /// Get a count of all the arguments processed in options and subcommands, this excludes arguments which were
0777     /// treated as extras.
0778     CLI11_NODISCARD std::size_t count_all() const;
0779 
0780     /// Changes the group membership
0781     App *group(std::string group_name) {
0782         group_ = group_name;
0783         return this;
0784     }
0785 
0786     /// The argumentless form of require subcommand requires 1 or more subcommands
0787     App *require_subcommand() {
0788         require_subcommand_min_ = 1;
0789         require_subcommand_max_ = 0;
0790         return this;
0791     }
0792 
0793     /// Require a subcommand to be given (does not affect help call)
0794     /// The number required can be given. Negative values indicate maximum
0795     /// number allowed (0 for any number). Max number inheritable.
0796     App *require_subcommand(int value) {
0797         if(value < 0) {
0798             require_subcommand_min_ = 0;
0799             require_subcommand_max_ = static_cast<std::size_t>(-value);
0800         } else {
0801             require_subcommand_min_ = static_cast<std::size_t>(value);
0802             require_subcommand_max_ = static_cast<std::size_t>(value);
0803         }
0804         return this;
0805     }
0806 
0807     /// Explicitly control the number of subcommands required. Setting 0
0808     /// for the max means unlimited number allowed. Max number inheritable.
0809     App *require_subcommand(std::size_t min, std::size_t max) {
0810         require_subcommand_min_ = min;
0811         require_subcommand_max_ = max;
0812         return this;
0813     }
0814 
0815     /// The argumentless form of require option requires 1 or more options be used
0816     App *require_option() {
0817         require_option_min_ = 1;
0818         require_option_max_ = 0;
0819         return this;
0820     }
0821 
0822     /// Require an option to be given (does not affect help call)
0823     /// The number required can be given. Negative values indicate maximum
0824     /// number allowed (0 for any number).
0825     App *require_option(int value) {
0826         if(value < 0) {
0827             require_option_min_ = 0;
0828             require_option_max_ = static_cast<std::size_t>(-value);
0829         } else {
0830             require_option_min_ = static_cast<std::size_t>(value);
0831             require_option_max_ = static_cast<std::size_t>(value);
0832         }
0833         return this;
0834     }
0835 
0836     /// Explicitly control the number of options required. Setting 0
0837     /// for the max means unlimited number allowed. Max number inheritable.
0838     App *require_option(std::size_t min, std::size_t max) {
0839         require_option_min_ = min;
0840         require_option_max_ = max;
0841         return this;
0842     }
0843 
0844     /// Set fallthrough, set to true so that options will fallthrough to parent if not recognized in a subcommand
0845     /// Default from parent, usually set on parent.
0846     App *fallthrough(bool value = true) {
0847         fallthrough_ = value;
0848         return this;
0849     }
0850 
0851     /// Set subcommand fallthrough, set to true so that subcommands on parents are recognized
0852     App *subcommand_fallthrough(bool value = true) {
0853         subcommand_fallthrough_ = value;
0854         return this;
0855     }
0856 
0857     /// Check to see if this subcommand was parsed, true only if received on command line.
0858     /// This allows the subcommand to be directly checked.
0859     explicit operator bool() const { return parsed_ > 0; }
0860 
0861     ///@}
0862     /// @name Extras for subclassing
0863     ///@{
0864 
0865     /// This allows subclasses to inject code before callbacks but after parse.
0866     ///
0867     /// This does not run if any errors or help is thrown.
0868     virtual void pre_callback() {}
0869 
0870     ///@}
0871     /// @name Parsing
0872     ///@{
0873     //
0874     /// Reset the parsed data
0875     void clear();
0876 
0877     /// Parses the command line - throws errors.
0878     /// This must be called after the options are in but before the rest of the program.
0879     void parse(int argc, const char *const *argv);
0880     void parse(int argc, const wchar_t *const *argv);
0881 
0882   private:
0883     template <class CharT> void parse_char_t(int argc, const CharT *const *argv);
0884 
0885   public:
0886     /// Parse a single string as if it contained command line arguments.
0887     /// This function splits the string into arguments then calls parse(std::vector<std::string> &)
0888     /// the function takes an optional boolean argument specifying if the programName is included in the string to
0889     /// process
0890     void parse(std::string commandline, bool program_name_included = false);
0891     void parse(std::wstring commandline, bool program_name_included = false);
0892 
0893     /// The real work is done here. Expects a reversed vector.
0894     /// Changes the vector to the remaining options.
0895     void parse(std::vector<std::string> &args);
0896 
0897     /// The real work is done here. Expects a reversed vector.
0898     void parse(std::vector<std::string> &&args);
0899 
0900     void parse_from_stream(std::istream &input);
0901 
0902     /// Provide a function to print a help message. The function gets access to the App pointer and error.
0903     void failure_message(std::function<std::string(const App *, const Error &e)> function) {
0904         failure_message_ = function;
0905     }
0906 
0907     /// Print a nice error message and return the exit code
0908     int exit(const Error &e, std::ostream &out = std::cout, std::ostream &err = std::cerr) const;
0909 
0910     ///@}
0911     /// @name Post parsing
0912     ///@{
0913 
0914     /// Counts the number of times the given option was passed.
0915     CLI11_NODISCARD std::size_t count(std::string option_name) const { return get_option(option_name)->count(); }
0916 
0917     /// Get a subcommand pointer list to the currently selected subcommands (after parsing by default, in command
0918     /// line order; use parsed = false to get the original definition list.)
0919     CLI11_NODISCARD std::vector<App *> get_subcommands() const { return parsed_subcommands_; }
0920 
0921     /// Get a filtered subcommand pointer list from the original definition list. An empty function will provide all
0922     /// subcommands (const)
0923     std::vector<const App *> get_subcommands(const std::function<bool(const App *)> &filter) const;
0924 
0925     /// Get a filtered subcommand pointer list from the original definition list. An empty function will provide all
0926     /// subcommands
0927     std::vector<App *> get_subcommands(const std::function<bool(App *)> &filter);
0928 
0929     /// Check to see if given subcommand was selected
0930     bool got_subcommand(const App *subcom) const {
0931         // get subcom needed to verify that this was a real subcommand
0932         return get_subcommand(subcom)->parsed_ > 0;
0933     }
0934 
0935     /// Check with name instead of pointer to see if subcommand was selected
0936     CLI11_NODISCARD bool got_subcommand(std::string subcommand_name) const noexcept {
0937         App *sub = get_subcommand_no_throw(subcommand_name);
0938         return (sub != nullptr) ? (sub->parsed_ > 0) : false;
0939     }
0940 
0941     /// Sets excluded options for the subcommand
0942     App *excludes(Option *opt) {
0943         if(opt == nullptr) {
0944             throw OptionNotFound("nullptr passed");
0945         }
0946         exclude_options_.insert(opt);
0947         return this;
0948     }
0949 
0950     /// Sets excluded subcommands for the subcommand
0951     App *excludes(App *app) {
0952         if(app == nullptr) {
0953             throw OptionNotFound("nullptr passed");
0954         }
0955         if(app == this) {
0956             throw OptionNotFound("cannot self reference in needs");
0957         }
0958         auto res = exclude_subcommands_.insert(app);
0959         // subcommand exclusion should be symmetric
0960         if(res.second) {
0961             app->exclude_subcommands_.insert(this);
0962         }
0963         return this;
0964     }
0965 
0966     App *needs(Option *opt) {
0967         if(opt == nullptr) {
0968             throw OptionNotFound("nullptr passed");
0969         }
0970         need_options_.insert(opt);
0971         return this;
0972     }
0973 
0974     App *needs(App *app) {
0975         if(app == nullptr) {
0976             throw OptionNotFound("nullptr passed");
0977         }
0978         if(app == this) {
0979             throw OptionNotFound("cannot self reference in needs");
0980         }
0981         need_subcommands_.insert(app);
0982         return this;
0983     }
0984 
0985     /// Removes an option from the excludes list of this subcommand
0986     bool remove_excludes(Option *opt);
0987 
0988     /// Removes a subcommand from the excludes list of this subcommand
0989     bool remove_excludes(App *app);
0990 
0991     /// Removes an option from the needs list of this subcommand
0992     bool remove_needs(Option *opt);
0993 
0994     /// Removes a subcommand from the needs list of this subcommand
0995     bool remove_needs(App *app);
0996     ///@}
0997     /// @name Help
0998     ///@{
0999 
1000     /// Set usage.
1001     App *usage(std::string usage_string) {
1002         usage_ = std::move(usage_string);
1003         return this;
1004     }
1005     /// Set usage.
1006     App *usage(std::function<std::string()> usage_function) {
1007         usage_callback_ = std::move(usage_function);
1008         return this;
1009     }
1010     /// Set footer.
1011     App *footer(std::string footer_string) {
1012         footer_ = std::move(footer_string);
1013         return this;
1014     }
1015     /// Set footer.
1016     App *footer(std::function<std::string()> footer_function) {
1017         footer_callback_ = std::move(footer_function);
1018         return this;
1019     }
1020     /// Produce a string that could be read in as a config of the current values of the App. Set default_also to
1021     /// include default arguments. write_descriptions will print a description for the App and for each option.
1022     CLI11_NODISCARD std::string config_to_str(bool default_also = false, bool write_description = false) const {
1023         return config_formatter_->to_config(this, default_also, write_description, "");
1024     }
1025 
1026     /// Makes a help message, using the currently configured formatter
1027     /// Will only do one subcommand at a time
1028     CLI11_NODISCARD std::string help(std::string prev = "", AppFormatMode mode = AppFormatMode::Normal) const;
1029 
1030     /// Displays a version string
1031     CLI11_NODISCARD std::string version() const;
1032     ///@}
1033     /// @name Getters
1034     ///@{
1035 
1036     /// Access the formatter
1037     CLI11_NODISCARD std::shared_ptr<FormatterBase> get_formatter() const { return formatter_; }
1038 
1039     /// Access the config formatter
1040     CLI11_NODISCARD std::shared_ptr<Config> get_config_formatter() const { return config_formatter_; }
1041 
1042     /// Access the config formatter as a configBase pointer
1043     CLI11_NODISCARD std::shared_ptr<ConfigBase> get_config_formatter_base() const {
1044         // This is safer as a dynamic_cast if we have RTTI, as Config -> ConfigBase
1045 #if CLI11_USE_STATIC_RTTI == 0
1046         return std::dynamic_pointer_cast<ConfigBase>(config_formatter_);
1047 #else
1048         return std::static_pointer_cast<ConfigBase>(config_formatter_);
1049 #endif
1050     }
1051 
1052     /// Get the app or subcommand description
1053     CLI11_NODISCARD std::string get_description() const { return description_; }
1054 
1055     /// Set the description of the app
1056     App *description(std::string app_description) {
1057         description_ = std::move(app_description);
1058         return this;
1059     }
1060 
1061     /// Get the list of options (user facing function, so returns raw pointers), has optional filter function
1062     std::vector<const Option *> get_options(const std::function<bool(const Option *)> filter = {}) const;
1063 
1064     /// Non-const version of the above
1065     std::vector<Option *> get_options(const std::function<bool(Option *)> filter = {});
1066 
1067     /// Get an option by name (noexcept non-const version)
1068     CLI11_NODISCARD Option *get_option_no_throw(std::string option_name) noexcept;
1069 
1070     /// Get an option by name (noexcept const version)
1071     CLI11_NODISCARD const Option *get_option_no_throw(std::string option_name) const noexcept;
1072 
1073     /// Get an option by name
1074     CLI11_NODISCARD const Option *get_option(std::string option_name) const {
1075         const auto *opt = get_option_no_throw(option_name);
1076         if(opt == nullptr) {
1077             throw OptionNotFound(option_name);
1078         }
1079         return opt;
1080     }
1081 
1082     /// Get an option by name (non-const version)
1083     Option *get_option(std::string option_name) {
1084         auto *opt = get_option_no_throw(option_name);
1085         if(opt == nullptr) {
1086             throw OptionNotFound(option_name);
1087         }
1088         return opt;
1089     }
1090 
1091     /// Shortcut bracket operator for getting a pointer to an option
1092     const Option *operator[](const std::string &option_name) const { return get_option(option_name); }
1093 
1094     /// Shortcut bracket operator for getting a pointer to an option
1095     const Option *operator[](const char *option_name) const { return get_option(option_name); }
1096 
1097     /// Check the status of ignore_case
1098     CLI11_NODISCARD bool get_ignore_case() const { return ignore_case_; }
1099 
1100     /// Check the status of ignore_underscore
1101     CLI11_NODISCARD bool get_ignore_underscore() const { return ignore_underscore_; }
1102 
1103     /// Check the status of fallthrough
1104     CLI11_NODISCARD bool get_fallthrough() const { return fallthrough_; }
1105 
1106     /// Check the status of subcommand fallthrough
1107     CLI11_NODISCARD bool get_subcommand_fallthrough() const { return subcommand_fallthrough_; }
1108 
1109     /// Check the status of the allow windows style options
1110     CLI11_NODISCARD bool get_allow_windows_style_options() const { return allow_windows_style_options_; }
1111 
1112     /// Check the status of the allow windows style options
1113     CLI11_NODISCARD bool get_positionals_at_end() const { return positionals_at_end_; }
1114 
1115     /// Check the status of the allow windows style options
1116     CLI11_NODISCARD bool get_configurable() const { return configurable_; }
1117 
1118     /// Get the group of this subcommand
1119     CLI11_NODISCARD const std::string &get_group() const { return group_; }
1120 
1121     /// Generate and return the usage.
1122     CLI11_NODISCARD std::string get_usage() const {
1123         return (usage_callback_) ? usage_callback_() + '\n' + usage_ : usage_;
1124     }
1125 
1126     /// Generate and return the footer.
1127     CLI11_NODISCARD std::string get_footer() const {
1128         return (footer_callback_) ? footer_callback_() + '\n' + footer_ : footer_;
1129     }
1130 
1131     /// Get the required min subcommand value
1132     CLI11_NODISCARD std::size_t get_require_subcommand_min() const { return require_subcommand_min_; }
1133 
1134     /// Get the required max subcommand value
1135     CLI11_NODISCARD std::size_t get_require_subcommand_max() const { return require_subcommand_max_; }
1136 
1137     /// Get the required min option value
1138     CLI11_NODISCARD std::size_t get_require_option_min() const { return require_option_min_; }
1139 
1140     /// Get the required max option value
1141     CLI11_NODISCARD std::size_t get_require_option_max() const { return require_option_max_; }
1142 
1143     /// Get the prefix command status
1144     CLI11_NODISCARD bool get_prefix_command() const { return prefix_command_; }
1145 
1146     /// Get the status of allow extras
1147     CLI11_NODISCARD bool get_allow_extras() const { return allow_extras_; }
1148 
1149     /// Get the status of required
1150     CLI11_NODISCARD bool get_required() const { return required_; }
1151 
1152     /// Get the status of disabled
1153     CLI11_NODISCARD bool get_disabled() const { return disabled_; }
1154 
1155     /// Get the status of silence
1156     CLI11_NODISCARD bool get_silent() const { return silent_; }
1157 
1158     /// Get the status of silence
1159     CLI11_NODISCARD bool get_allow_non_standard_option_names() const { return allow_non_standard_options_; }
1160 
1161     /// Get the status of disabled
1162     CLI11_NODISCARD bool get_immediate_callback() const { return immediate_callback_; }
1163 
1164     /// Get the status of disabled by default
1165     CLI11_NODISCARD bool get_disabled_by_default() const { return (default_startup == startup_mode::disabled); }
1166 
1167     /// Get the status of disabled by default
1168     CLI11_NODISCARD bool get_enabled_by_default() const { return (default_startup == startup_mode::enabled); }
1169     /// Get the status of validating positionals
1170     CLI11_NODISCARD bool get_validate_positionals() const { return validate_positionals_; }
1171     /// Get the status of validating optional vector arguments
1172     CLI11_NODISCARD bool get_validate_optional_arguments() const { return validate_optional_arguments_; }
1173 
1174     /// Get the status of allow extras
1175     CLI11_NODISCARD config_extras_mode get_allow_config_extras() const { return allow_config_extras_; }
1176 
1177     /// Get a pointer to the help flag.
1178     Option *get_help_ptr() { return help_ptr_; }
1179 
1180     /// Get a pointer to the help flag. (const)
1181     CLI11_NODISCARD const Option *get_help_ptr() const { return help_ptr_; }
1182 
1183     /// Get a pointer to the help all flag. (const)
1184     CLI11_NODISCARD const Option *get_help_all_ptr() const { return help_all_ptr_; }
1185 
1186     /// Get a pointer to the config option.
1187     Option *get_config_ptr() { return config_ptr_; }
1188 
1189     /// Get a pointer to the config option. (const)
1190     CLI11_NODISCARD const Option *get_config_ptr() const { return config_ptr_; }
1191 
1192     /// Get a pointer to the version option.
1193     Option *get_version_ptr() { return version_ptr_; }
1194 
1195     /// Get a pointer to the version option. (const)
1196     CLI11_NODISCARD const Option *get_version_ptr() const { return version_ptr_; }
1197 
1198     /// Get the parent of this subcommand (or nullptr if main app)
1199     App *get_parent() { return parent_; }
1200 
1201     /// Get the parent of this subcommand (or nullptr if main app) (const version)
1202     CLI11_NODISCARD const App *get_parent() const { return parent_; }
1203 
1204     /// Get the name of the current app
1205     CLI11_NODISCARD const std::string &get_name() const { return name_; }
1206 
1207     /// Get the aliases of the current app
1208     CLI11_NODISCARD const std::vector<std::string> &get_aliases() const { return aliases_; }
1209 
1210     /// clear all the aliases of the current App
1211     App *clear_aliases() {
1212         aliases_.clear();
1213         return this;
1214     }
1215 
1216     /// Get a display name for an app
1217     CLI11_NODISCARD std::string get_display_name(bool with_aliases = false) const;
1218 
1219     /// Check the name, case-insensitive and underscore insensitive if set
1220     CLI11_NODISCARD bool check_name(std::string name_to_check) const;
1221 
1222     /// Get the groups available directly from this option (in order)
1223     CLI11_NODISCARD std::vector<std::string> get_groups() const;
1224 
1225     /// This gets a vector of pointers with the original parse order
1226     CLI11_NODISCARD const std::vector<Option *> &parse_order() const { return parse_order_; }
1227 
1228     /// This returns the missing options from the current subcommand
1229     CLI11_NODISCARD std::vector<std::string> remaining(bool recurse = false) const;
1230 
1231     /// This returns the missing options in a form ready for processing by another command line program
1232     CLI11_NODISCARD std::vector<std::string> remaining_for_passthrough(bool recurse = false) const;
1233 
1234     /// This returns the number of remaining options, minus the -- separator
1235     CLI11_NODISCARD std::size_t remaining_size(bool recurse = false) const;
1236 
1237     ///@}
1238 
1239   protected:
1240     /// Check the options to make sure there are no conflicts.
1241     ///
1242     /// Currently checks to see if multiple positionals exist with unlimited args and checks if the min and max options
1243     /// are feasible
1244     void _validate() const;
1245 
1246     /// configure subcommands to enable parsing through the current object
1247     /// set the correct fallthrough and prefix for nameless subcommands and manage the automatic enable or disable
1248     /// makes sure parent is set correctly
1249     void _configure();
1250 
1251     /// Internal function to run (App) callback, bottom up
1252     void run_callback(bool final_mode = false, bool suppress_final_callback = false);
1253 
1254     /// Check to see if a subcommand is valid. Give up immediately if subcommand max has been reached.
1255     CLI11_NODISCARD bool _valid_subcommand(const std::string &current, bool ignore_used = true) const;
1256 
1257     /// Selects a Classifier enum based on the type of the current argument
1258     CLI11_NODISCARD detail::Classifier _recognize(const std::string &current,
1259                                                   bool ignore_used_subcommands = true) const;
1260 
1261     // The parse function is now broken into several parts, and part of process
1262 
1263     /// Read and process a configuration file (main app only)
1264     void _process_config_file();
1265 
1266     /// Read and process a particular configuration file
1267     bool _process_config_file(const std::string &config_file, bool throw_error);
1268 
1269     /// Get envname options if not yet passed. Runs on *all* subcommands.
1270     void _process_env();
1271 
1272     /// Process callbacks. Runs on *all* subcommands.
1273     void _process_callbacks();
1274 
1275     /// Run help flag processing if any are found.
1276     ///
1277     /// The flags allow recursive calls to remember if there was a help flag on a parent.
1278     void _process_help_flags(bool trigger_help = false, bool trigger_all_help = false) const;
1279 
1280     /// Verify required options and cross requirements. Subcommands too (only if selected).
1281     void _process_requirements();
1282 
1283     /// Process callbacks and such.
1284     void _process();
1285 
1286     /// Throw an error if anything is left over and should not be.
1287     void _process_extras();
1288 
1289     /// Throw an error if anything is left over and should not be.
1290     /// Modifies the args to fill in the missing items before throwing.
1291     void _process_extras(std::vector<std::string> &args);
1292 
1293     /// Internal function to recursively increment the parsed counter on the current app as well unnamed subcommands
1294     void increment_parsed();
1295 
1296     /// Internal parse function
1297     void _parse(std::vector<std::string> &args);
1298 
1299     /// Internal parse function
1300     void _parse(std::vector<std::string> &&args);
1301 
1302     /// Internal function to parse a stream
1303     void _parse_stream(std::istream &input);
1304 
1305     /// Parse one config param, return false if not found in any subcommand, remove if it is
1306     ///
1307     /// If this has more than one dot.separated.name, go into the subcommand matching it
1308     /// Returns true if it managed to find the option, if false you'll need to remove the arg manually.
1309     void _parse_config(const std::vector<ConfigItem> &args);
1310 
1311     /// Fill in a single config option
1312     bool _parse_single_config(const ConfigItem &item, std::size_t level = 0);
1313 
1314     /// Parse "one" argument (some may eat more than one), delegate to parent if fails, add to missing if missing
1315     /// from main return false if the parse has failed and needs to return to parent
1316     bool _parse_single(std::vector<std::string> &args, bool &positional_only);
1317 
1318     /// Count the required remaining positional arguments
1319     CLI11_NODISCARD std::size_t _count_remaining_positionals(bool required_only = false) const;
1320 
1321     /// Count the required remaining positional arguments
1322     CLI11_NODISCARD bool _has_remaining_positionals() const;
1323 
1324     /// Parse a positional, go up the tree to check
1325     /// @param haltOnSubcommand if set to true the operation will not process subcommands merely return false
1326     /// Return true if the positional was used false otherwise
1327     bool _parse_positional(std::vector<std::string> &args, bool haltOnSubcommand);
1328 
1329     /// Locate a subcommand by name with two conditions, should disabled subcommands be ignored, and should used
1330     /// subcommands be ignored
1331     CLI11_NODISCARD App *
1332     _find_subcommand(const std::string &subc_name, bool ignore_disabled, bool ignore_used) const noexcept;
1333 
1334     /// Parse a subcommand, modify args and continue
1335     ///
1336     /// Unlike the others, this one will always allow fallthrough
1337     /// return true if the subcommand was processed false otherwise
1338     bool _parse_subcommand(std::vector<std::string> &args);
1339 
1340     /// Parse a short (false) or long (true) argument, must be at the top of the list
1341     /// if local_processing_only is set to true then fallthrough is disabled will return false if not found
1342     /// return true if the argument was processed or false if nothing was done
1343     bool _parse_arg(std::vector<std::string> &args, detail::Classifier current_type, bool local_processing_only);
1344 
1345     /// Trigger the pre_parse callback if needed
1346     void _trigger_pre_parse(std::size_t remaining_args);
1347 
1348     /// Get the appropriate parent to fallthrough to which is the first one that has a name or the main app
1349     App *_get_fallthrough_parent();
1350 
1351     /// Helper function to run through all possible comparisons of subcommand names to check there is no overlap
1352     CLI11_NODISCARD const std::string &_compare_subcommand_names(const App &subcom, const App &base) const;
1353 
1354     /// Helper function to place extra values in the most appropriate position
1355     void _move_to_missing(detail::Classifier val_type, const std::string &val);
1356 
1357   public:
1358     /// function that could be used by subclasses of App to shift options around into subcommands
1359     void _move_option(Option *opt, App *app);
1360 };  // namespace CLI
1361 
1362 /// Extension of App to better manage groups of options
1363 class Option_group : public App {
1364   public:
1365     Option_group(std::string group_description, std::string group_name, App *parent)
1366         : App(std::move(group_description), "", parent) {
1367         group(group_name);
1368         // option groups should have automatic fallthrough
1369         if(group_name.empty() || group_name.front() == '+') {
1370             // help will not be used by default in these contexts
1371             set_help_flag("");
1372             set_help_all_flag("");
1373         }
1374     }
1375     using App::add_option;
1376     /// Add an existing option to the Option_group
1377     Option *add_option(Option *opt) {
1378         if(get_parent() == nullptr) {
1379             throw OptionNotFound("Unable to locate the specified option");
1380         }
1381         get_parent()->_move_option(opt, this);
1382         return opt;
1383     }
1384     /// Add an existing option to the Option_group
1385     void add_options(Option *opt) { add_option(opt); }
1386     /// Add a bunch of options to the group
1387     template <typename... Args> void add_options(Option *opt, Args... args) {
1388         add_option(opt);
1389         add_options(args...);
1390     }
1391     using App::add_subcommand;
1392     /// Add an existing subcommand to be a member of an option_group
1393     App *add_subcommand(App *subcom) {
1394         App_p subc = subcom->get_parent()->get_subcommand_ptr(subcom);
1395         subc->get_parent()->remove_subcommand(subcom);
1396         add_subcommand(std::move(subc));
1397         return subcom;
1398     }
1399 };
1400 
1401 /// Helper function to enable one option group/subcommand when another is used
1402 CLI11_INLINE void TriggerOn(App *trigger_app, App *app_to_enable);
1403 
1404 /// Helper function to enable one option group/subcommand when another is used
1405 CLI11_INLINE void TriggerOn(App *trigger_app, std::vector<App *> apps_to_enable);
1406 
1407 /// Helper function to disable one option group/subcommand when another is used
1408 CLI11_INLINE void TriggerOff(App *trigger_app, App *app_to_enable);
1409 
1410 /// Helper function to disable one option group/subcommand when another is used
1411 CLI11_INLINE void TriggerOff(App *trigger_app, std::vector<App *> apps_to_enable);
1412 
1413 /// Helper function to mark an option as deprecated
1414 CLI11_INLINE void deprecate_option(Option *opt, const std::string &replacement = "");
1415 
1416 /// Helper function to mark an option as deprecated
1417 inline void deprecate_option(App *app, const std::string &option_name, const std::string &replacement = "") {
1418     auto *opt = app->get_option(option_name);
1419     deprecate_option(opt, replacement);
1420 }
1421 
1422 /// Helper function to mark an option as deprecated
1423 inline void deprecate_option(App &app, const std::string &option_name, const std::string &replacement = "") {
1424     auto *opt = app.get_option(option_name);
1425     deprecate_option(opt, replacement);
1426 }
1427 
1428 /// Helper function to mark an option as retired
1429 CLI11_INLINE void retire_option(App *app, Option *opt);
1430 
1431 /// Helper function to mark an option as retired
1432 CLI11_INLINE void retire_option(App &app, Option *opt);
1433 
1434 /// Helper function to mark an option as retired
1435 CLI11_INLINE void retire_option(App *app, const std::string &option_name);
1436 
1437 /// Helper function to mark an option as retired
1438 CLI11_INLINE void retire_option(App &app, const std::string &option_name);
1439 
1440 namespace detail {
1441 /// This class is simply to allow tests access to App's protected functions
1442 struct AppFriend {
1443 #ifdef CLI11_CPP14
1444 
1445     /// Wrap _parse_short, perfectly forward arguments and return
1446     template <typename... Args> static decltype(auto) parse_arg(App *app, Args &&...args) {
1447         return app->_parse_arg(std::forward<Args>(args)...);
1448     }
1449 
1450     /// Wrap _parse_subcommand, perfectly forward arguments and return
1451     template <typename... Args> static decltype(auto) parse_subcommand(App *app, Args &&...args) {
1452         return app->_parse_subcommand(std::forward<Args>(args)...);
1453     }
1454 #else
1455     /// Wrap _parse_short, perfectly forward arguments and return
1456     template <typename... Args>
1457     static auto parse_arg(App *app, Args &&...args) ->
1458         typename std::result_of<decltype (&App::_parse_arg)(App, Args...)>::type {
1459         return app->_parse_arg(std::forward<Args>(args)...);
1460     }
1461 
1462     /// Wrap _parse_subcommand, perfectly forward arguments and return
1463     template <typename... Args>
1464     static auto parse_subcommand(App *app, Args &&...args) ->
1465         typename std::result_of<decltype (&App::_parse_subcommand)(App, Args...)>::type {
1466         return app->_parse_subcommand(std::forward<Args>(args)...);
1467     }
1468 #endif
1469     /// Wrap the fallthrough parent function to make sure that is working correctly
1470     static App *get_fallthrough_parent(App *app) { return app->_get_fallthrough_parent(); }
1471 };
1472 }  // namespace detail
1473 
1474 // [CLI11:app_hpp:end]
1475 }  // namespace CLI
1476 
1477 #ifndef CLI11_COMPILE
1478 #include "impl/App_inl.hpp"  // IWYU pragma: export
1479 #endif