Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-02 09:04:47

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