Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-05 08:51:43

0001 // Copyright (c) 2017-2024, 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, std::string option_description, callback_t callback, App *parent)
0345         : description_(std::move(option_description)), parent_(parent), callback_(std::move(callback)) {
0346         std::tie(snames_, lnames_, pname_) = detail::get_names(detail::split_names(option_name));
0347     }
0348 
0349   public:
0350     /// @name Basic
0351     ///@{
0352 
0353     Option(const Option &) = delete;
0354     Option &operator=(const Option &) = delete;
0355 
0356     /// Count the total number of times an option was passed
0357     CLI11_NODISCARD std::size_t count() const { return results_.size(); }
0358 
0359     /// True if the option was not passed
0360     CLI11_NODISCARD bool empty() const { return results_.empty(); }
0361 
0362     /// This bool operator returns true if any arguments were passed or the option callback is forced
0363     explicit operator bool() const { return !empty() || force_callback_; }
0364 
0365     /// Clear the parsed results (mostly for testing)
0366     void clear() {
0367         results_.clear();
0368         current_option_state_ = option_state::parsing;
0369     }
0370 
0371     ///@}
0372     /// @name Setting options
0373     ///@{
0374 
0375     /// Set the number of expected arguments
0376     Option *expected(int value);
0377 
0378     /// Set the range of expected arguments
0379     Option *expected(int value_min, int value_max);
0380 
0381     /// Set the value of allow_extra_args which allows extra value arguments on the flag or option to be included
0382     /// with each instance
0383     Option *allow_extra_args(bool value = true) {
0384         allow_extra_args_ = value;
0385         return this;
0386     }
0387     /// Get the current value of allow extra args
0388     CLI11_NODISCARD bool get_allow_extra_args() const { return allow_extra_args_; }
0389     /// Set the value of trigger_on_parse which specifies that the option callback should be triggered on every parse
0390     Option *trigger_on_parse(bool value = true) {
0391         trigger_on_result_ = value;
0392         return this;
0393     }
0394     /// The status of trigger on parse
0395     CLI11_NODISCARD bool get_trigger_on_parse() const { return trigger_on_result_; }
0396 
0397     /// Set the value of force_callback
0398     Option *force_callback(bool value = true) {
0399         force_callback_ = value;
0400         return this;
0401     }
0402     /// The status of force_callback
0403     CLI11_NODISCARD bool get_force_callback() const { return force_callback_; }
0404 
0405     /// Set the value of run_callback_for_default which controls whether the callback function should be called to set
0406     /// the default This is controlled automatically but could be manipulated by the user.
0407     Option *run_callback_for_default(bool value = true) {
0408         run_callback_for_default_ = value;
0409         return this;
0410     }
0411     /// Get the current value of run_callback_for_default
0412     CLI11_NODISCARD bool get_run_callback_for_default() const { return run_callback_for_default_; }
0413 
0414     /// Adds a Validator with a built in type name
0415     Option *check(Validator validator, const std::string &validator_name = "");
0416 
0417     /// Adds a Validator. Takes a const string& and returns an error message (empty if conversion/check is okay).
0418     Option *check(std::function<std::string(const std::string &)> Validator,
0419                   std::string Validator_description = "",
0420                   std::string Validator_name = "");
0421 
0422     /// Adds a transforming Validator with a built in type name
0423     Option *transform(Validator Validator, const std::string &Validator_name = "");
0424 
0425     /// Adds a Validator-like function that can change result
0426     Option *transform(const std::function<std::string(std::string)> &func,
0427                       std::string transform_description = "",
0428                       std::string transform_name = "");
0429 
0430     /// Adds a user supplied function to run on each item passed in (communicate though lambda capture)
0431     Option *each(const std::function<void(std::string)> &func);
0432 
0433     /// Get a named Validator
0434     Validator *get_validator(const std::string &Validator_name = "");
0435 
0436     /// Get a Validator by index NOTE: this may not be the order of definition
0437     Validator *get_validator(int index);
0438 
0439     /// Sets required options
0440     Option *needs(Option *opt) {
0441         if(opt != this) {
0442             needs_.insert(opt);
0443         }
0444         return this;
0445     }
0446 
0447     /// Can find a string if needed
0448     template <typename T = App> Option *needs(std::string opt_name) {
0449         auto opt = static_cast<T *>(parent_)->get_option_no_throw(opt_name);
0450         if(opt == nullptr) {
0451             throw IncorrectConstruction::MissingOption(opt_name);
0452         }
0453         return needs(opt);
0454     }
0455 
0456     /// Any number supported, any mix of string and Opt
0457     template <typename A, typename B, typename... ARG> Option *needs(A opt, B opt1, ARG... args) {
0458         needs(opt);
0459         return needs(opt1, args...);  // NOLINT(readability-suspicious-call-argument)
0460     }
0461 
0462     /// Remove needs link from an option. Returns true if the option really was in the needs list.
0463     bool remove_needs(Option *opt);
0464 
0465     /// Sets excluded options
0466     Option *excludes(Option *opt);
0467 
0468     /// Can find a string if needed
0469     template <typename T = App> Option *excludes(std::string opt_name) {
0470         auto opt = static_cast<T *>(parent_)->get_option_no_throw(opt_name);
0471         if(opt == nullptr) {
0472             throw IncorrectConstruction::MissingOption(opt_name);
0473         }
0474         return excludes(opt);
0475     }
0476 
0477     /// Any number supported, any mix of string and Opt
0478     template <typename A, typename B, typename... ARG> Option *excludes(A opt, B opt1, ARG... args) {
0479         excludes(opt);
0480         return excludes(opt1, args...);
0481     }
0482 
0483     /// Remove needs link from an option. Returns true if the option really was in the needs list.
0484     bool remove_excludes(Option *opt);
0485 
0486     /// Sets environment variable to read if no option given
0487     Option *envname(std::string name) {
0488         envname_ = std::move(name);
0489         return this;
0490     }
0491 
0492     /// Ignore case
0493     ///
0494     /// The template hides the fact that we don't have the definition of App yet.
0495     /// You are never expected to add an argument to the template here.
0496     template <typename T = App> Option *ignore_case(bool value = true);
0497 
0498     /// Ignore underscores in the option names
0499     ///
0500     /// The template hides the fact that we don't have the definition of App yet.
0501     /// You are never expected to add an argument to the template here.
0502     template <typename T = App> Option *ignore_underscore(bool value = true);
0503 
0504     /// Take the last argument if given multiple times (or another policy)
0505     Option *multi_option_policy(MultiOptionPolicy value = MultiOptionPolicy::Throw);
0506 
0507     /// Disable flag overrides values, e.g. --flag=<value> is not allowed
0508     Option *disable_flag_override(bool value = true) {
0509         disable_flag_override_ = value;
0510         return this;
0511     }
0512     ///@}
0513     /// @name Accessors
0514     ///@{
0515 
0516     /// The number of arguments the option expects
0517     CLI11_NODISCARD int get_type_size() const { return type_size_min_; }
0518 
0519     /// The minimum number of arguments the option expects
0520     CLI11_NODISCARD int get_type_size_min() const { return type_size_min_; }
0521     /// The maximum number of arguments the option expects
0522     CLI11_NODISCARD int get_type_size_max() const { return type_size_max_; }
0523 
0524     /// Return the inject_separator flag
0525     CLI11_NODISCARD bool get_inject_separator() const { return inject_separator_; }
0526 
0527     /// The environment variable associated to this value
0528     CLI11_NODISCARD std::string get_envname() const { return envname_; }
0529 
0530     /// The set of options needed
0531     CLI11_NODISCARD std::set<Option *> get_needs() const { return needs_; }
0532 
0533     /// The set of options excluded
0534     CLI11_NODISCARD std::set<Option *> get_excludes() const { return excludes_; }
0535 
0536     /// The default value (for help printing)
0537     CLI11_NODISCARD std::string get_default_str() const { return default_str_; }
0538 
0539     /// Get the callback function
0540     CLI11_NODISCARD callback_t get_callback() const { return callback_; }
0541 
0542     /// Get the long names
0543     CLI11_NODISCARD const std::vector<std::string> &get_lnames() const { return lnames_; }
0544 
0545     /// Get the short names
0546     CLI11_NODISCARD const std::vector<std::string> &get_snames() const { return snames_; }
0547 
0548     /// Get the flag names with specified default values
0549     CLI11_NODISCARD const std::vector<std::string> &get_fnames() const { return fnames_; }
0550     /// Get a single name for the option, first of lname, pname, sname, envname
0551     CLI11_NODISCARD const std::string &get_single_name() const {
0552         if(!lnames_.empty()) {
0553             return lnames_[0];
0554         }
0555         if(!snames_.empty()) {
0556             return snames_[0];
0557         }
0558         if(!pname_.empty()) {
0559             return pname_;
0560         }
0561         return envname_;
0562     }
0563     /// The number of times the option expects to be included
0564     CLI11_NODISCARD int get_expected() const { return expected_min_; }
0565 
0566     /// The number of times the option expects to be included
0567     CLI11_NODISCARD int get_expected_min() const { return expected_min_; }
0568     /// The max number of times the option expects to be included
0569     CLI11_NODISCARD int get_expected_max() const { return expected_max_; }
0570 
0571     /// The total min number of expected  string values to be used
0572     CLI11_NODISCARD int get_items_expected_min() const { return type_size_min_ * expected_min_; }
0573 
0574     /// Get the maximum number of items expected to be returned and used for the callback
0575     CLI11_NODISCARD int get_items_expected_max() const {
0576         int t = type_size_max_;
0577         return detail::checked_multiply(t, expected_max_) ? t : detail::expected_max_vector_size;
0578     }
0579     /// The total min number of expected  string values to be used
0580     CLI11_NODISCARD int get_items_expected() const { return get_items_expected_min(); }
0581 
0582     /// True if the argument can be given directly
0583     CLI11_NODISCARD bool get_positional() const { return !pname_.empty(); }
0584 
0585     /// True if option has at least one non-positional name
0586     CLI11_NODISCARD bool nonpositional() const { return (!lnames_.empty() || !snames_.empty()); }
0587 
0588     /// True if option has description
0589     CLI11_NODISCARD bool has_description() const { return !description_.empty(); }
0590 
0591     /// Get the description
0592     CLI11_NODISCARD const std::string &get_description() const { return description_; }
0593 
0594     /// Set the description
0595     Option *description(std::string option_description) {
0596         description_ = std::move(option_description);
0597         return this;
0598     }
0599 
0600     Option *option_text(std::string text) {
0601         option_text_ = std::move(text);
0602         return this;
0603     }
0604 
0605     CLI11_NODISCARD const std::string &get_option_text() const { return option_text_; }
0606 
0607     ///@}
0608     /// @name Help tools
0609     ///@{
0610 
0611     /// \brief Gets a comma separated list of names.
0612     /// Will include / prefer the positional name if positional is true.
0613     /// If all_options is false, pick just the most descriptive name to show.
0614     /// Use `get_name(true)` to get the positional name (replaces `get_pname`)
0615     CLI11_NODISCARD std::string get_name(bool positional = false,  ///< Show the positional name
0616                                          bool all_options = false  ///< Show every option
0617     ) const;
0618 
0619     ///@}
0620     /// @name Parser tools
0621     ///@{
0622 
0623     /// Process the callback
0624     void run_callback();
0625 
0626     /// If options share any of the same names, find it
0627     CLI11_NODISCARD const std::string &matching_name(const Option &other) const;
0628 
0629     /// If options share any of the same names, they are equal (not counting positional)
0630     bool operator==(const Option &other) const { return !matching_name(other).empty(); }
0631 
0632     /// Check a name. Requires "-" or "--" for short / long, supports positional name
0633     CLI11_NODISCARD bool check_name(const std::string &name) const;
0634 
0635     /// Requires "-" to be removed from string
0636     CLI11_NODISCARD bool check_sname(std::string name) const {
0637         return (detail::find_member(std::move(name), snames_, ignore_case_) >= 0);
0638     }
0639 
0640     /// Requires "--" to be removed from string
0641     CLI11_NODISCARD bool check_lname(std::string name) const {
0642         return (detail::find_member(std::move(name), lnames_, ignore_case_, ignore_underscore_) >= 0);
0643     }
0644 
0645     /// Requires "--" to be removed from string
0646     CLI11_NODISCARD bool check_fname(std::string name) const {
0647         if(fnames_.empty()) {
0648             return false;
0649         }
0650         return (detail::find_member(std::move(name), fnames_, ignore_case_, ignore_underscore_) >= 0);
0651     }
0652 
0653     /// Get the value that goes for a flag, nominally gets the default value but allows for overrides if not
0654     /// disabled
0655     CLI11_NODISCARD std::string get_flag_value(const std::string &name, std::string input_value) const;
0656 
0657     /// Puts a result at the end
0658     Option *add_result(std::string s);
0659 
0660     /// Puts a result at the end and get a count of the number of arguments actually added
0661     Option *add_result(std::string s, int &results_added);
0662 
0663     /// Puts a result at the end
0664     Option *add_result(std::vector<std::string> s);
0665 
0666     /// Get the current complete results set
0667     CLI11_NODISCARD const results_t &results() const { return results_; }
0668 
0669     /// Get a copy of the results
0670     CLI11_NODISCARD results_t reduced_results() const;
0671 
0672     /// Get the results as a specified type
0673     template <typename T> void results(T &output) const {
0674         bool retval = false;
0675         if(current_option_state_ >= option_state::reduced || (results_.size() == 1 && validators_.empty())) {
0676             const results_t &res = (proc_results_.empty()) ? results_ : proc_results_;
0677             retval = detail::lexical_conversion<T, T>(res, output);
0678         } else {
0679             results_t res;
0680             if(results_.empty()) {
0681                 if(!default_str_.empty()) {
0682                     // _add_results takes an rvalue only
0683                     _add_result(std::string(default_str_), res);
0684                     _validate_results(res);
0685                     results_t extra;
0686                     _reduce_results(extra, res);
0687                     if(!extra.empty()) {
0688                         res = std::move(extra);
0689                     }
0690                 } else {
0691                     res.emplace_back();
0692                 }
0693             } else {
0694                 res = reduced_results();
0695             }
0696             retval = detail::lexical_conversion<T, T>(res, output);
0697         }
0698         if(!retval) {
0699             throw ConversionError(get_name(), results_);
0700         }
0701     }
0702 
0703     /// Return the results as the specified type
0704     template <typename T> CLI11_NODISCARD T as() const {
0705         T output;
0706         results(output);
0707         return output;
0708     }
0709 
0710     /// See if the callback has been run already
0711     CLI11_NODISCARD bool get_callback_run() const { return (current_option_state_ == option_state::callback_run); }
0712 
0713     ///@}
0714     /// @name Custom options
0715     ///@{
0716 
0717     /// Set the type function to run when displayed on this option
0718     Option *type_name_fn(std::function<std::string()> typefun) {
0719         type_name_ = std::move(typefun);
0720         return this;
0721     }
0722 
0723     /// Set a custom option typestring
0724     Option *type_name(std::string typeval) {
0725         type_name_fn([typeval]() { return typeval; });
0726         return this;
0727     }
0728 
0729     /// Set a custom option size
0730     Option *type_size(int option_type_size);
0731 
0732     /// Set a custom option type size range
0733     Option *type_size(int option_type_size_min, int option_type_size_max);
0734 
0735     /// Set the value of the separator injection flag
0736     void inject_separator(bool value = true) { inject_separator_ = value; }
0737 
0738     /// Set a capture function for the default. Mostly used by App.
0739     Option *default_function(const std::function<std::string()> &func) {
0740         default_function_ = func;
0741         return this;
0742     }
0743 
0744     /// Capture the default value from the original value (if it can be captured)
0745     Option *capture_default_str() {
0746         if(default_function_) {
0747             default_str_ = default_function_();
0748         }
0749         return this;
0750     }
0751 
0752     /// Set the default value string representation (does not change the contained value)
0753     Option *default_str(std::string val) {
0754         default_str_ = std::move(val);
0755         return this;
0756     }
0757 
0758     /// Set the default value and validate the results and run the callback if appropriate to set the value into the
0759     /// bound value only available for types that can be converted to a string
0760     template <typename X> Option *default_val(const X &val) {
0761         std::string val_str = detail::to_string(val);
0762         auto old_option_state = current_option_state_;
0763         results_t old_results{std::move(results_)};
0764         results_.clear();
0765         try {
0766             add_result(val_str);
0767             // if trigger_on_result_ is set the callback already ran
0768             if(run_callback_for_default_ && !trigger_on_result_) {
0769                 run_callback();  // run callback sets the state, we need to reset it again
0770                 current_option_state_ = option_state::parsing;
0771             } else {
0772                 _validate_results(results_);
0773                 current_option_state_ = old_option_state;
0774             }
0775         } catch(const CLI::Error &) {
0776             // this should be done
0777             results_ = std::move(old_results);
0778             current_option_state_ = old_option_state;
0779             throw;
0780         }
0781         results_ = std::move(old_results);
0782         default_str_ = std::move(val_str);
0783         return this;
0784     }
0785 
0786     /// Get the full typename for this option
0787     CLI11_NODISCARD std::string get_type_name() const;
0788 
0789   private:
0790     /// Run the results through the Validators
0791     void _validate_results(results_t &res) const;
0792 
0793     /** reduce the results in accordance with the MultiOptionPolicy
0794     @param[out] out results are assigned to res if there if they are different
0795     */
0796     void _reduce_results(results_t &out, const results_t &original) const;
0797 
0798     // Run a result through the Validators
0799     std::string _validate(std::string &result, int index) const;
0800 
0801     /// Add a single result to the result set, taking into account delimiters
0802     int _add_result(std::string &&result, std::vector<std::string> &res) const;
0803 };
0804 
0805 // [CLI11:option_hpp:end]
0806 }  // namespace CLI
0807 
0808 #ifndef CLI11_COMPILE
0809 #include "impl/Option_inl.hpp"  // IWYU pragma: export
0810 #endif