Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:54:44

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