Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/CLI/Option.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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 <functional>
0014 #include <memory>
0015 #include <set>
0016 #include <string>
0017 #include <tuple>
0018 #include <utility>
0019 #include <vector>
0020 // [CLI11:public_includes:end]
0021 
0022 #include "Error.hpp"
0023 #include "Macros.hpp"
0024 #include "Split.hpp"
0025 #include "StringTools.hpp"
0026 #include "Validators.hpp"
0027 
0028 namespace CLI {
0029 // [CLI11:option_hpp:verbatim]
0030 
0031 using results_t = std::vector<std::string>;
0032 /// callback function definition
0033 using callback_t = std::function<bool(const results_t &)>;
0034 
0035 class Option;
0036 class App;
0037 
0038 using Option_p = std::unique_ptr<Option>;
0039 /// Enumeration of the multiOption Policy selection
0040 enum class MultiOptionPolicy : char {
0041     Throw,      //!< Throw an error if any extra arguments were given
0042     TakeLast,   //!< take only the last Expected number of arguments
0043     TakeFirst,  //!< take only the first Expected number of arguments
0044     Join,       //!< merge all the arguments together into a single string via the delimiter character default('\n')
0045     TakeAll,    //!< just get all the passed argument regardless
0046     Sum,        //!< sum all the arguments together if numerical or concatenate directly without delimiter
0047     Reverse,    //!< take only the last Expected number of arguments in reverse order
0048 };
0049 
0050 /// This is the CRTP base class for Option and OptionDefaults. It was designed this way
0051 /// to share parts of the class; an OptionDefaults can copy to an Option.
0052 template <typename CRTP> class OptionBase {
0053     friend App;
0054 
0055   protected:
0056     /// The group membership
0057     std::string group_ = std::string("OPTIONS");
0058 
0059     /// True if this is a required option
0060     bool required_{false};
0061 
0062     /// Ignore the case when matching (option, not value)
0063     bool ignore_case_{false};
0064 
0065     /// Ignore underscores when matching (option, not value)
0066     bool ignore_underscore_{false};
0067 
0068     /// Allow this option to be given in a configuration file
0069     bool configurable_{true};
0070 
0071     /// Disable overriding flag values with '=value'
0072     bool disable_flag_override_{false};
0073 
0074     /// Specify a delimiter character for vector arguments
0075     char delimiter_{'\0'};
0076 
0077     /// Automatically capture default value
0078     bool always_capture_default_{false};
0079 
0080     /// Policy for handling multiple arguments beyond the expected Max
0081     MultiOptionPolicy multi_option_policy_{MultiOptionPolicy::Throw};
0082 
0083     /// Copy the contents to another similar class (one based on OptionBase)
0084     template <typename T> void copy_to(T *other) const;
0085 
0086   public:
0087     // setters
0088 
0089     /// Changes the group membership
0090     CRTP *group(const std::string &name) {
0091         if(!detail::valid_alias_name_string(name)) {
0092             throw IncorrectConstruction("Group names may not contain newlines or null characters");
0093         }
0094         group_ = name;
0095         return static_cast<CRTP *>(this);
0096     }
0097 
0098     /// Set the option as required
0099     CRTP *required(bool value = true) {
0100         required_ = value;
0101         return static_cast<CRTP *>(this);
0102     }
0103 
0104     /// Support Plumbum term
0105     CRTP *mandatory(bool value = true) { return required(value); }
0106 
0107     CRTP *always_capture_default(bool value = true) {
0108         always_capture_default_ = value;
0109         return static_cast<CRTP *>(this);
0110     }
0111 
0112     // Getters
0113 
0114     /// Get the group of this option
0115     CLI11_NODISCARD const std::string &get_group() const { return group_; }
0116 
0117     /// True if this is a required option
0118     CLI11_NODISCARD bool get_required() const { return required_; }
0119 
0120     /// The status of ignore case
0121     CLI11_NODISCARD bool get_ignore_case() const { return ignore_case_; }
0122 
0123     /// The status of ignore_underscore
0124     CLI11_NODISCARD bool get_ignore_underscore() const { return ignore_underscore_; }
0125 
0126     /// The status of configurable
0127     CLI11_NODISCARD bool get_configurable() const { return configurable_; }
0128 
0129     /// The status of configurable
0130     CLI11_NODISCARD bool get_disable_flag_override() const { return disable_flag_override_; }
0131 
0132     /// Get the current delimiter char
0133     CLI11_NODISCARD char get_delimiter() const { return delimiter_; }
0134 
0135     /// Return true if this will automatically capture the default value for help printing
0136     CLI11_NODISCARD bool get_always_capture_default() const { return always_capture_default_; }
0137 
0138     /// The status of the multi option policy
0139     CLI11_NODISCARD MultiOptionPolicy get_multi_option_policy() const { return multi_option_policy_; }
0140 
0141     // Shortcuts for multi option policy
0142 
0143     /// Set the multi option policy to take last
0144     CRTP *take_last() {
0145         auto *self = static_cast<CRTP *>(this);
0146         self->multi_option_policy(MultiOptionPolicy::TakeLast);
0147         return self;
0148     }
0149 
0150     /// Set the multi option policy to take last
0151     CRTP *take_first() {
0152         auto *self = static_cast<CRTP *>(this);
0153         self->multi_option_policy(MultiOptionPolicy::TakeFirst);
0154         return self;
0155     }
0156 
0157     /// Set the multi option policy to take all arguments
0158     CRTP *take_all() {
0159         auto self = static_cast<CRTP *>(this);
0160         self->multi_option_policy(MultiOptionPolicy::TakeAll);
0161         return self;
0162     }
0163 
0164     /// Set the multi option policy to join
0165     CRTP *join() {
0166         auto *self = static_cast<CRTP *>(this);
0167         self->multi_option_policy(MultiOptionPolicy::Join);
0168         return self;
0169     }
0170 
0171     /// Set the multi option policy to join with a specific delimiter
0172     CRTP *join(char delim) {
0173         auto self = static_cast<CRTP *>(this);
0174         self->delimiter_ = delim;
0175         self->multi_option_policy(MultiOptionPolicy::Join);
0176         return self;
0177     }
0178 
0179     /// Allow in a configuration file
0180     CRTP *configurable(bool value = true) {
0181         configurable_ = value;
0182         return static_cast<CRTP *>(this);
0183     }
0184 
0185     /// Allow in a configuration file
0186     CRTP *delimiter(char value = '\0') {
0187         delimiter_ = value;
0188         return static_cast<CRTP *>(this);
0189     }
0190 };
0191 
0192 /// This is a version of OptionBase that only supports setting values,
0193 /// for defaults. It is stored as the default option in an App.
0194 class OptionDefaults : public OptionBase<OptionDefaults> {
0195   public:
0196     OptionDefaults() = default;
0197 
0198     // Methods here need a different implementation if they are Option vs. OptionDefault
0199 
0200     /// Take the last argument if given multiple times
0201     OptionDefaults *multi_option_policy(MultiOptionPolicy value = MultiOptionPolicy::Throw) {
0202         multi_option_policy_ = value;
0203         return this;
0204     }
0205 
0206     /// Ignore the case of the option name
0207     OptionDefaults *ignore_case(bool value = true) {
0208         ignore_case_ = value;
0209         return this;
0210     }
0211 
0212     /// Ignore underscores in the option name
0213     OptionDefaults *ignore_underscore(bool value = true) {
0214         ignore_underscore_ = value;
0215         return this;
0216     }
0217 
0218     /// Disable overriding flag values with an '=<value>' segment
0219     OptionDefaults *disable_flag_override(bool value = true) {
0220         disable_flag_override_ = value;
0221         return this;
0222     }
0223 
0224     /// set a delimiter character to split up single arguments to treat as multiple inputs
0225     OptionDefaults *delimiter(char value = '\0') {
0226         delimiter_ = value;
0227         return this;
0228     }
0229 };
0230 
0231 class Option : public OptionBase<Option> {
0232     friend App;
0233 
0234   protected:
0235     /// @name Names
0236     ///@{
0237 
0238     /// A list of the short names (`-a`) without the leading dashes
0239     std::vector<std::string> snames_{};
0240 
0241     /// A list of the long names (`--long`) without the leading dashes
0242     std::vector<std::string> lnames_{};
0243 
0244     /// A list of the flag names with the appropriate default value, the first part of the pair should be duplicates of
0245     /// what is in snames or lnames but will trigger a particular response on a flag
0246     std::vector<std::pair<std::string, std::string>> default_flag_values_{};
0247 
0248     /// a list of flag names with specified default values;
0249     std::vector<std::string> fnames_{};
0250 
0251     /// A positional name
0252     std::string pname_{};
0253 
0254     /// If given, check the environment for this option
0255     std::string envname_{};
0256 
0257     ///@}
0258     /// @name Help
0259     ///@{
0260 
0261     /// The description for help strings
0262     std::string description_{};
0263 
0264     /// A human readable default value, either manually set, captured, or captured by default
0265     std::string default_str_{};
0266 
0267     /// If given, replace the text that describes the option type and usage in the help text
0268     std::string option_text_{};
0269 
0270     /// A human readable type value, set when App creates this
0271     ///
0272     /// This is a lambda function so "types" can be dynamic, such as when a set prints its contents.
0273     std::function<std::string()> type_name_{[]() { return std::string(); }};
0274 
0275     /// Run this function to capture a default (ignore if empty)
0276     std::function<std::string()> default_function_{};
0277 
0278     ///@}
0279     /// @name Configuration
0280     ///@{
0281 
0282     /// The number of arguments that make up one option. max is the nominal type size, min is the minimum number of
0283     /// strings
0284     int type_size_max_{1};
0285     /// The minimum number of arguments an option should be expecting
0286     int type_size_min_{1};
0287 
0288     /// The minimum number of expected values
0289     int expected_min_{1};
0290     /// The maximum number of expected values
0291     int expected_max_{1};
0292 
0293     /// A list of Validators to run on each value parsed
0294     std::vector<Validator> validators_{};
0295 
0296     /// A list of options that are required with this option
0297     std::set<Option *> needs_{};
0298 
0299     /// A list of options that are excluded with this option
0300     std::set<Option *> excludes_{};
0301 
0302     ///@}
0303     /// @name Other
0304     ///@{
0305 
0306     /// link back up to the parent App for fallthrough
0307     App *parent_{nullptr};
0308 
0309     /// Options store a callback to do all the work
0310     callback_t callback_{};
0311 
0312     ///@}
0313     /// @name Parsing results
0314     ///@{
0315 
0316     /// complete Results of parsing
0317     results_t results_{};
0318     /// results after reduction
0319     results_t proc_results_{};
0320     /// enumeration for the option state machine
0321     enum class option_state : char {
0322         parsing = 0,       //!< The option is currently collecting parsed results
0323         validated = 2,     //!< the results have been validated
0324         reduced = 4,       //!< a subset of results has been generated
0325         callback_run = 6,  //!< the callback has been executed
0326     };
0327     /// Whether the callback has run (needed for INI parsing)
0328     option_state current_option_state_{option_state::parsing};
0329     /// Specify that extra args beyond type_size_max should be allowed
0330     bool allow_extra_args_{false};
0331     /// Specify that the option should act like a flag vs regular option
0332     bool flag_like_{false};
0333     /// Control option to run the callback to set the default
0334     bool run_callback_for_default_{false};
0335     /// flag indicating a separator needs to be injected after each argument call
0336     bool inject_separator_{false};
0337     /// flag indicating that the option should trigger the validation and callback chain on each result when loaded
0338     bool trigger_on_result_{false};
0339     /// flag indicating that the option should force the callback regardless if any results present
0340     bool force_callback_{false};
0341     ///@}
0342 
0343     /// Making an option by hand is not defined, it must be made by the App class
0344     Option(std::string option_name,
0345            std::string option_description,
0346            callback_t callback,
0347            App *parent,
0348            bool allow_non_standard = false)
0349         : description_(std::move(option_description)), parent_(parent), callback_(std::move(callback)) {
0350         std::tie(snames_, lnames_, pname_) = detail::get_names(detail::split_names(option_name), allow_non_standard);
0351     }
0352 
0353   public:
0354     /// @name Basic
0355     ///@{
0356 
0357     Option(const Option &) = delete;
0358     Option &operator=(const Option &) = delete;
0359 
0360     /// Count the total number of times an option was passed
0361     CLI11_NODISCARD std::size_t count() const { return results_.size(); }
0362 
0363     /// True if the option was not passed
0364     CLI11_NODISCARD bool empty() const { return results_.empty(); }
0365 
0366     /// This bool operator returns true if any arguments were passed or the option callback is forced
0367     explicit operator bool() const { return !empty() || force_callback_; }
0368 
0369     /// Clear the parsed results (mostly for testing)
0370     void clear() {
0371         results_.clear();
0372         current_option_state_ = option_state::parsing;
0373     }
0374 
0375     ///@}
0376     /// @name Setting options
0377     ///@{
0378 
0379     /// Set the number of expected arguments
0380     Option *expected(int value);
0381 
0382     /// Set the range of expected arguments
0383     Option *expected(int value_min, int value_max);
0384 
0385     /// Set the value of allow_extra_args which allows extra value arguments on the flag or option to be included
0386     /// with each instance
0387     Option *allow_extra_args(bool value = true) {
0388         allow_extra_args_ = value;
0389         return this;
0390     }
0391     /// Get the current value of allow extra args
0392     CLI11_NODISCARD bool get_allow_extra_args() const { return allow_extra_args_; }
0393     /// Set the value of trigger_on_parse which specifies that the option callback should be triggered on every parse
0394     Option *trigger_on_parse(bool value = true) {
0395         trigger_on_result_ = value;
0396         return this;
0397     }
0398     /// The status of trigger on parse
0399     CLI11_NODISCARD bool get_trigger_on_parse() const { return trigger_on_result_; }
0400 
0401     /// Set the value of force_callback
0402     Option *force_callback(bool value = true) {
0403         force_callback_ = value;
0404         return this;
0405     }
0406     /// The status of force_callback
0407     CLI11_NODISCARD bool get_force_callback() const { return force_callback_; }
0408 
0409     /// Set the value of run_callback_for_default which controls whether the callback function should be called to set
0410     /// the default This is controlled automatically but could be manipulated by the user.
0411     Option *run_callback_for_default(bool value = true) {
0412         run_callback_for_default_ = value;
0413         return this;
0414     }
0415     /// Get the current value of run_callback_for_default
0416     CLI11_NODISCARD bool get_run_callback_for_default() const { return run_callback_for_default_; }
0417 
0418     /// Adds a Validator with a built in type name
0419     Option *check(Validator validator, const std::string &validator_name = "");
0420 
0421     /// Adds a Validator. Takes a const string& and returns an error message (empty if conversion/check is okay).
0422     Option *check(std::function<std::string(const std::string &)> Validator,
0423                   std::string Validator_description = "",
0424                   std::string Validator_name = "");
0425 
0426     /// Adds a transforming Validator with a built in type name
0427     Option *transform(Validator Validator, const std::string &Validator_name = "");
0428 
0429     /// Adds a Validator-like function that can change result
0430     Option *transform(const std::function<std::string(std::string)> &func,
0431                       std::string transform_description = "",
0432                       std::string transform_name = "");
0433 
0434     /// Adds a user supplied function to run on each item passed in (communicate though lambda capture)
0435     Option *each(const std::function<void(std::string)> &func);
0436 
0437     /// Get a named Validator
0438     Validator *get_validator(const std::string &Validator_name = "");
0439 
0440     /// Get a Validator by index NOTE: this may not be the order of definition
0441     Validator *get_validator(int index);
0442 
0443     /// Sets required options
0444     Option *needs(Option *opt) {
0445         if(opt != this) {
0446             needs_.insert(opt);
0447         }
0448         return this;
0449     }
0450 
0451     /// Can find a string if needed
0452     template <typename T = App> Option *needs(std::string opt_name) {
0453         auto opt = static_cast<T *>(parent_)->get_option_no_throw(opt_name);
0454         if(opt == nullptr) {
0455             throw IncorrectConstruction::MissingOption(opt_name);
0456         }
0457         return needs(opt);
0458     }
0459 
0460     /// Any number supported, any mix of string and Opt
0461     template <typename A, typename B, typename... ARG> Option *needs(A opt, B opt1, ARG... args) {
0462         needs(opt);
0463         return needs(opt1, args...);  // NOLINT(readability-suspicious-call-argument)
0464     }
0465 
0466     /// Remove needs link from an option. Returns true if the option really was in the needs list.
0467     bool remove_needs(Option *opt);
0468 
0469     /// Sets excluded options
0470     Option *excludes(Option *opt);
0471 
0472     /// Can find a string if needed
0473     template <typename T = App> Option *excludes(std::string opt_name) {
0474         auto opt = static_cast<T *>(parent_)->get_option_no_throw(opt_name);
0475         if(opt == nullptr) {
0476             throw IncorrectConstruction::MissingOption(opt_name);
0477         }
0478         return excludes(opt);
0479     }
0480 
0481     /// Any number supported, any mix of string and Opt
0482     template <typename A, typename B, typename... ARG> Option *excludes(A opt, B opt1, ARG... args) {
0483         excludes(opt);
0484         return excludes(opt1, args...);
0485     }
0486 
0487     /// Remove needs link from an option. Returns true if the option really was in the needs list.
0488     bool remove_excludes(Option *opt);
0489 
0490     /// Sets environment variable to read if no option given
0491     Option *envname(std::string name) {
0492         envname_ = std::move(name);
0493         return this;
0494     }
0495 
0496     /// Ignore case
0497     ///
0498     /// The template hides the fact that we don't have the definition of App yet.
0499     /// You are never expected to add an argument to the template here.
0500     template <typename T = App> Option *ignore_case(bool value = true);
0501 
0502     /// Ignore underscores in the option names
0503     ///
0504     /// The template hides the fact that we don't have the definition of App yet.
0505     /// You are never expected to add an argument to the template here.
0506     template <typename T = App> Option *ignore_underscore(bool value = true);
0507 
0508     /// Take the last argument if given multiple times (or another policy)
0509     Option *multi_option_policy(MultiOptionPolicy value = MultiOptionPolicy::Throw);
0510 
0511     /// Disable flag overrides values, e.g. --flag=<value> is not allowed
0512     Option *disable_flag_override(bool value = true) {
0513         disable_flag_override_ = value;
0514         return this;
0515     }
0516     ///@}
0517     /// @name Accessors
0518     ///@{
0519 
0520     /// The number of arguments the option expects
0521     CLI11_NODISCARD int get_type_size() const { return type_size_min_; }
0522 
0523     /// The minimum number of arguments the option expects
0524     CLI11_NODISCARD int get_type_size_min() const { return type_size_min_; }
0525     /// The maximum number of arguments the option expects
0526     CLI11_NODISCARD int get_type_size_max() const { return type_size_max_; }
0527 
0528     /// Return the inject_separator flag
0529     CLI11_NODISCARD bool get_inject_separator() const { return inject_separator_; }
0530 
0531     /// The environment variable associated to this value
0532     CLI11_NODISCARD std::string get_envname() const { return envname_; }
0533 
0534     /// The set of options needed
0535     CLI11_NODISCARD std::set<Option *> get_needs() const { return needs_; }
0536 
0537     /// The set of options excluded
0538     CLI11_NODISCARD std::set<Option *> get_excludes() const { return excludes_; }
0539 
0540     /// The default value (for help printing)
0541     CLI11_NODISCARD std::string get_default_str() const { return default_str_; }
0542 
0543     /// Get the callback function
0544     CLI11_NODISCARD callback_t get_callback() const { return callback_; }
0545 
0546     /// Get the long names
0547     CLI11_NODISCARD const std::vector<std::string> &get_lnames() const { return lnames_; }
0548 
0549     /// Get the short names
0550     CLI11_NODISCARD const std::vector<std::string> &get_snames() const { return snames_; }
0551 
0552     /// Get the flag names with specified default values
0553     CLI11_NODISCARD const std::vector<std::string> &get_fnames() const { return fnames_; }
0554     /// Get a single name for the option, first of lname, sname, pname, envname
0555     CLI11_NODISCARD const std::string &get_single_name() const {
0556         if(!lnames_.empty()) {
0557             return lnames_[0];
0558         }
0559         if(!snames_.empty()) {
0560             return snames_[0];
0561         }
0562         if(!pname_.empty()) {
0563             return pname_;
0564         }
0565         return envname_;
0566     }
0567     /// The number of times the option expects to be included
0568     CLI11_NODISCARD int get_expected() const { return expected_min_; }
0569 
0570     /// The number of times the option expects to be included
0571     CLI11_NODISCARD int get_expected_min() const { return expected_min_; }
0572     /// The max number of times the option expects to be included
0573     CLI11_NODISCARD int get_expected_max() const { return expected_max_; }
0574 
0575     /// The total min number of expected  string values to be used
0576     CLI11_NODISCARD int get_items_expected_min() const { return type_size_min_ * expected_min_; }
0577 
0578     /// Get the maximum number of items expected to be returned and used for the callback
0579     CLI11_NODISCARD int get_items_expected_max() const {
0580         int t = type_size_max_;
0581         return detail::checked_multiply(t, expected_max_) ? t : detail::expected_max_vector_size;
0582     }
0583     /// The total min number of expected  string values to be used
0584     CLI11_NODISCARD int get_items_expected() const { return get_items_expected_min(); }
0585 
0586     /// True if the argument can be given directly
0587     CLI11_NODISCARD bool get_positional() const { return !pname_.empty(); }
0588 
0589     /// True if option has at least one non-positional name
0590     CLI11_NODISCARD bool nonpositional() const { return (!lnames_.empty() || !snames_.empty()); }
0591 
0592     /// True if option has description
0593     CLI11_NODISCARD bool has_description() const { return !description_.empty(); }
0594 
0595     /// Get the description
0596     CLI11_NODISCARD const std::string &get_description() const { return description_; }
0597 
0598     /// Set the description
0599     Option *description(std::string option_description) {
0600         description_ = std::move(option_description);
0601         return this;
0602     }
0603 
0604     Option *option_text(std::string text) {
0605         option_text_ = std::move(text);
0606         return this;
0607     }
0608 
0609     CLI11_NODISCARD const std::string &get_option_text() const { return option_text_; }
0610 
0611     ///@}
0612     /// @name Help tools
0613     ///@{
0614 
0615     /// \brief Gets a comma separated list of names.
0616     /// Will include / prefer the positional name if positional is true.
0617     /// If all_options is false, pick just the most descriptive name to show.
0618     /// Use `get_name(true)` to get the positional name (replaces `get_pname`)
0619     CLI11_NODISCARD std::string get_name(bool positional = false,  ///< Show the positional name
0620                                          bool all_options = false  ///< Show every option
0621     ) const;
0622 
0623     ///@}
0624     /// @name Parser tools
0625     ///@{
0626 
0627     /// Process the callback
0628     void run_callback();
0629 
0630     /// If options share any of the same names, find it
0631     CLI11_NODISCARD const std::string &matching_name(const Option &other) const;
0632 
0633     /// If options share any of the same names, they are equal (not counting positional)
0634     bool operator==(const Option &other) const { return !matching_name(other).empty(); }
0635 
0636     /// Check a name. Requires "-" or "--" for short / long, supports positional name
0637     CLI11_NODISCARD bool check_name(const std::string &name) const;
0638 
0639     /// Requires "-" to be removed from string
0640     CLI11_NODISCARD bool check_sname(std::string name) const {
0641         return (detail::find_member(std::move(name), snames_, ignore_case_) >= 0);
0642     }
0643 
0644     /// Requires "--" to be removed from string
0645     CLI11_NODISCARD bool check_lname(std::string name) const {
0646         return (detail::find_member(std::move(name), lnames_, ignore_case_, ignore_underscore_) >= 0);
0647     }
0648 
0649     /// Requires "--" to be removed from string
0650     CLI11_NODISCARD bool check_fname(std::string name) const {
0651         if(fnames_.empty()) {
0652             return false;
0653         }
0654         return (detail::find_member(std::move(name), fnames_, ignore_case_, ignore_underscore_) >= 0);
0655     }
0656 
0657     /// Get the value that goes for a flag, nominally gets the default value but allows for overrides if not
0658     /// disabled
0659     CLI11_NODISCARD std::string get_flag_value(const std::string &name, std::string input_value) const;
0660 
0661     /// Puts a result at the end
0662     Option *add_result(std::string s);
0663 
0664     /// Puts a result at the end and get a count of the number of arguments actually added
0665     Option *add_result(std::string s, int &results_added);
0666 
0667     /// Puts a result at the end
0668     Option *add_result(std::vector<std::string> s);
0669 
0670     /// Get the current complete results set
0671     CLI11_NODISCARD const results_t &results() const { return results_; }
0672 
0673     /// Get a copy of the results
0674     CLI11_NODISCARD results_t reduced_results() const;
0675 
0676     /// Get the results as a specified type
0677     template <typename T> void results(T &output) const {
0678         bool retval = false;
0679         if(current_option_state_ >= option_state::reduced || (results_.size() == 1 && validators_.empty())) {
0680             const results_t &res = (proc_results_.empty()) ? results_ : proc_results_;
0681             retval = detail::lexical_conversion<T, T>(res, output);
0682         } else {
0683             results_t res;
0684             if(results_.empty()) {
0685                 if(!default_str_.empty()) {
0686                     // _add_results takes an rvalue only
0687                     _add_result(std::string(default_str_), res);
0688                     _validate_results(res);
0689                     results_t extra;
0690                     _reduce_results(extra, res);
0691                     if(!extra.empty()) {
0692                         res = std::move(extra);
0693                     }
0694                 } else {
0695                     res.emplace_back();
0696                 }
0697             } else {
0698                 res = reduced_results();
0699             }
0700             retval = detail::lexical_conversion<T, T>(res, output);
0701         }
0702         if(!retval) {
0703             throw ConversionError(get_name(), results_);
0704         }
0705     }
0706 
0707     /// Return the results as the specified type
0708     template <typename T> CLI11_NODISCARD T as() const {
0709         T output;
0710         results(output);
0711         return output;
0712     }
0713 
0714     /// See if the callback has been run already
0715     CLI11_NODISCARD bool get_callback_run() const { return (current_option_state_ == option_state::callback_run); }
0716 
0717     ///@}
0718     /// @name Custom options
0719     ///@{
0720 
0721     /// Set the type function to run when displayed on this option
0722     Option *type_name_fn(std::function<std::string()> typefun) {
0723         type_name_ = std::move(typefun);
0724         return this;
0725     }
0726 
0727     /// Set a custom option typestring
0728     Option *type_name(std::string typeval) {
0729         type_name_fn([typeval]() { return typeval; });
0730         return this;
0731     }
0732 
0733     /// Set a custom option size
0734     Option *type_size(int option_type_size);
0735 
0736     /// Set a custom option type size range
0737     Option *type_size(int option_type_size_min, int option_type_size_max);
0738 
0739     /// Set the value of the separator injection flag
0740     void inject_separator(bool value = true) { inject_separator_ = value; }
0741 
0742     /// Set a capture function for the default. Mostly used by App.
0743     Option *default_function(const std::function<std::string()> &func) {
0744         default_function_ = func;
0745         return this;
0746     }
0747 
0748     /// Capture the default value from the original value (if it can be captured)
0749     Option *capture_default_str() {
0750         if(default_function_) {
0751             default_str_ = default_function_();
0752         }
0753         return this;
0754     }
0755 
0756     /// Set the default value string representation (does not change the contained value)
0757     Option *default_str(std::string val) {
0758         default_str_ = std::move(val);
0759         return this;
0760     }
0761 
0762     /// Set the default value and validate the results and run the callback if appropriate to set the value into the
0763     /// bound value only available for types that can be converted to a string
0764     template <typename X> Option *default_val(const X &val) {
0765         std::string val_str = detail::to_string(val);
0766         auto old_option_state = current_option_state_;
0767         results_t old_results{std::move(results_)};
0768         results_.clear();
0769         try {
0770             add_result(val_str);
0771             // if trigger_on_result_ is set the callback already ran
0772             if(run_callback_for_default_ && !trigger_on_result_) {
0773                 run_callback();  // run callback sets the state, we need to reset it again
0774                 current_option_state_ = option_state::parsing;
0775             } else {
0776                 _validate_results(results_);
0777                 current_option_state_ = old_option_state;
0778             }
0779         } catch(const ValidationError &err) {
0780             // this should be done
0781             results_ = std::move(old_results);
0782             current_option_state_ = old_option_state;
0783             // try an alternate way to convert
0784             std::string alternate = detail::value_string(val);
0785             if(!alternate.empty() && alternate != val_str) {
0786                 return default_val(alternate);
0787             }
0788 
0789             throw ValidationError(get_name(),
0790                                   std::string("given default value does not pass validation :") + err.what());
0791         } catch(const ConversionError &err) {
0792             // this should be done
0793             results_ = std::move(old_results);
0794             current_option_state_ = old_option_state;
0795 
0796             throw ConversionError(
0797                 get_name(), std::string("given default value(\"") + val_str + "\") produces an error : " + err.what());
0798         } catch(const CLI::Error &) {
0799             results_ = std::move(old_results);
0800             current_option_state_ = old_option_state;
0801             throw;
0802         }
0803         results_ = std::move(old_results);
0804         default_str_ = std::move(val_str);
0805         return this;
0806     }
0807 
0808     /// Get the full typename for this option
0809     CLI11_NODISCARD std::string get_type_name() const;
0810 
0811   private:
0812     /// Run the results through the Validators
0813     void _validate_results(results_t &res) const;
0814 
0815     /** reduce the results in accordance with the MultiOptionPolicy
0816     @param[out] out results are assigned to res if there if they are different
0817     */
0818     void _reduce_results(results_t &out, const results_t &original) const;
0819 
0820     // Run a result through the Validators
0821     std::string _validate(std::string &result, int index) const;
0822 
0823     /// Add a single result to the result set, taking into account delimiters
0824     int _add_result(std::string &&result, std::vector<std::string> &res) const;
0825 };
0826 
0827 // [CLI11:option_hpp:end]
0828 }  // namespace CLI
0829 
0830 #ifndef CLI11_COMPILE
0831 #include "impl/Option_inl.hpp"  // IWYU pragma: export
0832 #endif