diff --git a/include/sharg/parser.hpp b/include/sharg/parser.hpp index e3916913..9e7980b1 100644 --- a/include/sharg/parser.hpp +++ b/include/sharg/parser.hpp @@ -188,18 +188,7 @@ class parser subcommands{std::move(subcommands)}, original_arguments{arguments} { - for (auto & sub : this->subcommands) - { - if (!std::regex_match(sub, app_name_regex)) - { - throw design_error{"The subcommand name must only contain alpha-numeric characters or '_' and '-' " - "(regex: \"^[a-zA-Z0-9_-]+$\")."}; - } - } - info.app_name = app_name; - - init(); } //!\overload @@ -252,14 +241,17 @@ class parser { verify_option_config(config); - // copy variables into the lambda because the calls are pushed to a stack - // and the references would go out of scope. - std::visit( - [&value, &config](auto & f) + auto operation = [this, &value, config]() + { + auto visit_fn = [&value, &config](auto & f) { f.add_option(value, config); - }, - format); + }; + + std::visit(std::move(visit_fn), format); + }; + + operations.push_back(std::move(operation)); } /*!\brief Adds a flag to the sharg::parser. @@ -281,14 +273,17 @@ class parser if (value) throw design_error("A flag's default value must be false."); - // copy variables into the lambda because the calls are pushed to a stack - // and the references would go out of scope. - std::visit( - [&value, &config](auto & f) + auto operation = [this, &value, config]() + { + auto visit_fn = [&value, &config](auto & f) { f.add_flag(value, config); - }, - format); + }; + + std::visit(std::move(visit_fn), format); + }; + + operations.push_back(std::move(operation)); } /*!\brief Adds a positional option to the sharg::parser. @@ -323,14 +318,17 @@ class parser if constexpr (detail::is_container_option) has_positional_list_option = true; // keep track of a list option because there must be only one! - // copy variables into the lambda because the calls are pushed to a stack - // and the references would go out of scope. - std::visit( - [&value, &config](auto & f) + auto operation = [this, &value, config]() + { + auto visit_fn = [&value, &config](auto & f) { f.add_positional_option(value, config); - }, - format); + }; + + std::visit(std::move(visit_fn), format); + }; + + operations.push_back(std::move(operation)); } //!\} @@ -414,8 +412,19 @@ class parser "(regex: \"^[a-zA-Z0-9_-]+$\").")}; } + for (auto & sub : this->subcommands) + { + if (!std::regex_match(sub, app_name_regex)) + { + throw design_error{"The subcommand name must only contain alpha-numeric characters or '_' and '-' " + "(regex: \"^[a-zA-Z0-9_-]+$\")."}; + } + } + detail::version_checker app_version{info.app_name, info.version, info.url}; + init(); + if (std::holds_alternative(format) && !subcommands.empty() && sub_parser == nullptr) { assert(!subcommands.empty()); @@ -438,6 +447,10 @@ class parser version_check_future = app_version_prom.get_future(); app_version(std::move(app_version_prom)); } + + for (auto & operation : operations) + operation(); + std::visit( [this](T & f) { @@ -545,12 +558,17 @@ class parser */ void add_section(std::string const & title, bool const advanced_only = false) { - std::visit( - [&title, advanced_only](auto & f) + auto operation = [this, title, advanced_only]() + { + auto visit_fn = [&title, advanced_only](auto & f) { f.add_section(title, advanced_only); - }, - format); + }; + + std::visit(std::move(visit_fn), format); + }; + + operations.push_back(std::move(operation)); } /*!\brief Adds an help page subsection to the sharg::parser. @@ -564,12 +582,17 @@ class parser */ void add_subsection(std::string const & title, bool const advanced_only = false) { - std::visit( - [&title, advanced_only](auto & f) + auto operation = [this, title, advanced_only]() + { + auto visit_fn = [&title, advanced_only](auto & f) { f.add_subsection(title, advanced_only); - }, - format); + }; + + std::visit(std::move(visit_fn), format); + }; + + operations.push_back(std::move(operation)); } /*!\brief Adds an help page text line to the sharg::parser. @@ -584,12 +607,17 @@ class parser */ void add_line(std::string const & text, bool is_paragraph = false, bool const advanced_only = false) { - std::visit( - [&text, is_paragraph, advanced_only](auto & f) + auto operation = [this, text, is_paragraph, advanced_only]() + { + auto visit_fn = [&text, is_paragraph, advanced_only](auto & f) { f.add_line(text, is_paragraph, advanced_only); - }, - format); + }; + + std::visit(std::move(visit_fn), format); + }; + + operations.push_back(std::move(operation)); } /*!\brief Adds an help page list item (key-value) to the sharg::parser. @@ -613,12 +641,17 @@ class parser */ void add_list_item(std::string const & key, std::string const & desc, bool const advanced_only = false) { - std::visit( - [&key, &desc, advanced_only](auto & f) + auto operation = [this, key, desc, advanced_only]() + { + auto visit_fn = [&key, &desc, advanced_only](auto & f) { f.add_list_item(key, desc, advanced_only); - }, - format); + }; + + std::visit(std::move(visit_fn), format); + }; + + operations.push_back(std::move(operation)); } //!\} @@ -734,6 +767,9 @@ class parser //!\brief The command that lead to calling this parser, e.g. [./build/bin/raptor, build] std::vector executable_name{}; + //!\brief Vector of functions that stores all calls. + std::vector> operations; + /*!\brief Initializes the sharg::parser class on construction. * \throws sharg::too_few_arguments if option --export-help was specified without a value * \throws sharg::too_few_arguments if option --version-check was specified without a value