From 976963151b6916d676aa27089dfdfde980d264c6 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sun, 7 Jan 2024 20:26:03 +0000 Subject: [PATCH 01/11] command_line/options: Added new nouns and option_t noun functions for making options global and exclusive --- substrate/command_line/options | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/substrate/command_line/options b/substrate/command_line/options index 6e92f659..214ce79a 100644 --- a/substrate/command_line/options +++ b/substrate/command_line/options @@ -25,6 +25,8 @@ namespace substrate::commandLine repeatable, takesParameter, required, + global, + exclusive, }; enum class optionValueType_t @@ -125,6 +127,18 @@ namespace substrate::commandLine return *this; } + [[nodiscard]] constexpr option_t &global() noexcept + { + _flags.set(optionFlags_t::global); + return *this; + } + + [[nodiscard]] constexpr option_t &exclusive() noexcept + { + _flags.set(optionFlags_t::exclusive); + return *this; + } + template [[nodiscard]] constexpr option_t &valueRange(T min, T max) noexcept { // These perform casts only to silence conversion warnings @@ -144,6 +158,10 @@ namespace substrate::commandLine { return _flags.includes(optionFlags_t::repeatable); } [[nodiscard]] constexpr bool isRequired() const noexcept { return _flags.includes(optionFlags_t::required); } + [[nodiscard]] constexpr bool isGlobal() const noexcept + { return _flags.includes(optionFlags_t::global); } + [[nodiscard]] constexpr bool isExclusive() const noexcept + { return _flags.includes(optionFlags_t::exclusive); } [[nodiscard]] constexpr bool valueOnly() const noexcept { return std::holds_alternative(_option); } From a90c4fd859a659d501eda96e3ab4bf704c68e648 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sun, 7 Jan 2024 21:33:43 +0000 Subject: [PATCH 02/11] command_line/arguments: Implemented checks to enforce exclusivity on parsed options --- impl/command_line/arguments.cxx | 35 ++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/impl/command_line/arguments.cxx b/impl/command_line/arguments.cxx index bacd58e5..95875183 100644 --- a/impl/command_line/arguments.cxx +++ b/impl/command_line/arguments.cxx @@ -150,7 +150,7 @@ namespace substrate::commandLine return requiredOptions; } - static auto displayName(const optionsItem_t &item) + [[nodiscard]] static auto displayName(const optionsItem_t &item) { if (item.valueless_by_exception()) return ""s; @@ -161,6 +161,35 @@ namespace substrate::commandLine }, item); } + [[nodiscard]] static bool checkExclusivity(const std::set &options) noexcept + { + std::set exclusiveOptions{}; + // Loop through all the visited options + for (const auto &option : options) + { + // Dispatch on the option type + std::visit(match_t + { + [&](const option_t &value) + { + if (value.isExclusive()) + exclusiveOptions.insert(value); + }, + [](const optionSet_t &) { }, + }, option); + } + // Now we've collected all the options that are exclusive, display diagnostics + // if there is more than one in the set and return failure, otherwise success + if (exclusiveOptions.size() > 1) + { + console.error("Multiple mutually exclusive options given together on command line, only one allowed."sv); + console.error("Mutually exclusive options given are:"sv); + for (const auto &option : exclusiveOptions) + console.error(" "sv, option.displayName()); + } + return exclusiveOptions.size() <= 1; + } + // NOLINTNEXTLINE(readability-convert-member-functions-to-static) bool arguments_t::parseFrom(tokeniser_t &lexer, const options_t &options) { @@ -181,6 +210,10 @@ namespace substrate::commandLine return false; } } + // Having parsed as many options as we can, collect all exclusive options seen and + // perform the exclusivity check + if (!checkExclusivity(optionsVisited)) + return false; // Having parsed as many options as we can, collect all the required options into a set const auto requiredOptions{collectRequiredOptions(options)}; optionsVisited_t missingOptions{}; From d34fad634271d6748b56fb62c65e0f3431242c04 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 9 Jan 2024 15:36:48 +0000 Subject: [PATCH 03/11] command_line/arguments: Implemented a mechanism for arguments_t::parseArgument() to be able to take a set of options to recognise through the recursion step --- impl/command_line/arguments.cxx | 71 +++++++++++++++++++------------- substrate/command_line/arguments | 5 ++- 2 files changed, 46 insertions(+), 30 deletions(-) diff --git a/impl/command_line/arguments.cxx b/impl/command_line/arguments.cxx index 95875183..bdf44423 100644 --- a/impl/command_line/arguments.cxx +++ b/impl/command_line/arguments.cxx @@ -88,7 +88,7 @@ namespace substrate::commandLine tokeniser_t lexer{argCount - 1U, argList + 1}; arguments_t result{}; // Try to parse all available arguments against the options tree for the program - if (!result.parseFrom(lexer, options)) + if (!result.parseFrom(lexer, options, {})) return std::nullopt; return result; } @@ -191,13 +191,13 @@ namespace substrate::commandLine } // NOLINTNEXTLINE(readability-convert-member-functions-to-static) - bool arguments_t::parseFrom(tokeniser_t &lexer, const options_t &options) + bool arguments_t::parseFrom(tokeniser_t &lexer, const options_t &options, const optionsVisited_t globalOptions) { const auto &token{lexer.token()}; optionsVisited_t optionsVisited{}; while (token.valid()) { - const auto result{parseArgument(lexer, options, optionsVisited)}; + const auto result{parseArgument(lexer, options, globalOptions, optionsVisited)}; // If the result is a nullopt, we're unwinding an inner failure if (!result) return false; @@ -240,7 +240,7 @@ namespace substrate::commandLine static void handleUnrecognised(tokeniser_t &lexer, const std::string_view &argument) noexcept; std::optional arguments_t::parseArgument(tokeniser_t &lexer, const options_t &options, - optionsVisited_t &optionsVisited) noexcept + const optionsVisited_t &globalOptions, optionsVisited_t &optionsVisited) noexcept { // Start by checking we're in a suitable state const auto &token{lexer.token()}; @@ -253,34 +253,49 @@ namespace substrate::commandLine const auto argument{token.value()}; // Initialise look-aside for optionValue_t{} options std::optional valueOption{}; - for (const auto &option : options) + const auto matchOptions { - // Check if this option is an option_t that is valueOnly() (optionValue_t{}) - if (std::holds_alternative(option)) + [&](const auto &optionsSet) -> std::variant> { - const auto &value{std::get(option)}; - if (value.valueOnly()) + for (const auto &option : optionsSet) { - valueOption = value; - continue; + // Check if this option is an option_t that is valueOnly() (optionValue_t{}) + if (std::holds_alternative(option)) + { + const auto &value{std::get(option)}; + if (value.valueOnly()) + { + valueOption = value; + continue; + } + } + + // Otherwise, process the option normally + const auto match + { + // Dispatch based on the option type + std::visit(match_t + { + [&](const option_t &value) { return matchOption(lexer, value, argument); }, + [&](const optionSet_t &value) { return matchOptionSet(lexer, value, argument); }, + }, option) + }; + + // If we got a valid match, use the result + if (match) + return handleResult(*this, option, optionsVisited, argument, *match); } + return std::monostate{}; } - - // Otherwise, process the option normally - const auto match - { - // Dispatch based on the option type - std::visit(match_t - { - [&](const option_t &value) { return matchOption(lexer, value, argument); }, - [&](const optionSet_t &value) { return matchOptionSet(lexer, value, argument); }, - }, option) - }; - - // If we got a valid match, use the result - if (match) - return handleResult(*this, option, optionsVisited, argument, *match); - } + }; + // Try matching on the arguments from this level of the recursion + const auto localsMatch{matchOptions(options)}; + if (std::holds_alternative>(localsMatch)) + return std::get>(localsMatch); + // If that fails, now try matching on the global options + const auto globalsMatch{matchOptions(globalOptions)}; + if (std::holds_alternative>(globalsMatch)) + return std::get>(globalsMatch); // If there's an optionValue_t{} and we got no match so far, try matching on it if (valueOption) { @@ -354,7 +369,7 @@ namespace substrate::commandLine lexer.next(); arguments_t subarguments{}; const auto &suboptions{alternation.suboptions()}; - if (!suboptions.empty() && !subarguments.parseFrom(lexer, suboptions)) + if (!suboptions.empty() && !subarguments.parseFrom(lexer, suboptions, {})) // If the operation fails, use monostate to signal match-but-fail. return std::monostate{}; return choice_t{option.metaName(), argument, std::move(subarguments)}; diff --git a/substrate/command_line/arguments b/substrate/command_line/arguments index 12b24ed8..8f58ba6f 100644 --- a/substrate/command_line/arguments +++ b/substrate/command_line/arguments @@ -48,7 +48,7 @@ namespace substrate::commandLine storage_t _arguments; [[nodiscard]] std::optional parseArgument(internal::tokeniser_t &lexer, const options_t &options, - optionsVisited_t &optionsVisited) noexcept; + const optionsVisited_t &globalOptions, optionsVisited_t &optionsVisited) noexcept; public: arguments_t() noexcept; @@ -58,7 +58,8 @@ namespace substrate::commandLine arguments_t &operator =(const arguments_t &arguments) noexcept; arguments_t &operator =(arguments_t &&arguments) noexcept; - [[nodiscard]] bool parseFrom(internal::tokeniser_t &lexer, const options_t &options); + [[nodiscard]] bool parseFrom(internal::tokeniser_t &lexer, const options_t &options, + optionsVisited_t globalOptions); [[nodiscard]] bool add(item_t argument) noexcept; [[nodiscard]] size_t count() const noexcept; From d255b2430acc07476466ff1f13dd75e400926fb7 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 9 Jan 2024 16:03:55 +0000 Subject: [PATCH 04/11] command_line/arguments: Implemented gathering and passing of the set of global options through recursive arguments_t::parseFrom() calls --- impl/command_line/arguments.cxx | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/impl/command_line/arguments.cxx b/impl/command_line/arguments.cxx index bdf44423..f77a11f9 100644 --- a/impl/command_line/arguments.cxx +++ b/impl/command_line/arguments.cxx @@ -233,7 +233,8 @@ namespace substrate::commandLine static std::optional matchOption(tokeniser_t &lexer, const option_t &option, const std::string_view &argument) noexcept; static std::optional matchOptionSet(tokeniser_t &lexer, const optionSet_t &option, - const std::string_view &argument) noexcept; + const std::string_view &argument, const options_t &options, + const std::set &globalOptions) noexcept; template static bool checkMatchValid(const optionsItem_t &option, set_t &optionsVisited) noexcept; template static std::optional handleResult(arguments_t &arguments, const optionsItem_t &option, set_t &optionsVisited, const std::string_view &argument, const optionMatch_t &match) noexcept; @@ -277,7 +278,8 @@ namespace substrate::commandLine std::visit(match_t { [&](const option_t &value) { return matchOption(lexer, value, argument); }, - [&](const optionSet_t &value) { return matchOptionSet(lexer, value, argument); }, + [&](const optionSet_t &value) + { return matchOptionSet(lexer, value, argument, options, globalOptions); }, }, option) }; @@ -355,8 +357,31 @@ namespace substrate::commandLine return flag_t{option.metaName(), std::move(*value)}; } + static std::set gatherGlobals(const options_t &options, + const std::set &globalOptions) noexcept + { + // Clone the existing set of global options + auto result{globalOptions}; + // Loop through the current level's options and pull out any that are global + for (const auto &option : options) + { + std::visit(match_t + { + [&](const option_t &value) + { + if (value.isGlobal()) + result.insert(value); + }, + [&](const optionSet_t &) { }, + }, option); + } + // Having gathered all of them up, return the new set + return result; + } + static std::optional matchOptionSet(tokeniser_t &lexer, const optionSet_t &option, - const std::string_view &argument) noexcept + const std::string_view &argument, const options_t &options, + const std::set &globalOptions) noexcept { // Check if we're parsing an alternation from a set const auto match{option.matches(argument)}; @@ -369,7 +394,7 @@ namespace substrate::commandLine lexer.next(); arguments_t subarguments{}; const auto &suboptions{alternation.suboptions()}; - if (!suboptions.empty() && !subarguments.parseFrom(lexer, suboptions, {})) + if (!suboptions.empty() && !subarguments.parseFrom(lexer, suboptions, gatherGlobals(options, globalOptions))) // If the operation fails, use monostate to signal match-but-fail. return std::monostate{}; return choice_t{option.metaName(), argument, std::move(subarguments)}; From caf4d9388687a9ca50cc96d769ccdec6a722efe2 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 9 Jan 2024 17:32:10 +0000 Subject: [PATCH 05/11] command_line/arguments: Switched gatherGlobals() to using std::for_each() --- impl/command_line/arguments.cxx | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/impl/command_line/arguments.cxx b/impl/command_line/arguments.cxx index f77a11f9..dafedf65 100644 --- a/impl/command_line/arguments.cxx +++ b/impl/command_line/arguments.cxx @@ -363,18 +363,23 @@ namespace substrate::commandLine // Clone the existing set of global options auto result{globalOptions}; // Loop through the current level's options and pull out any that are global - for (const auto &option : options) - { - std::visit(match_t + std::for_each + ( + options.begin(), + options.end(), + [&](const internal::optionsItem_t &option) { - [&](const option_t &value) + std::visit(match_t { - if (value.isGlobal()) - result.insert(value); - }, - [&](const optionSet_t &) { }, - }, option); - } + [&](const option_t &value) + { + if (value.isGlobal()) + result.insert(value); + }, + [&](const optionSet_t &) { }, + }, option); + } + ); // Having gathered all of them up, return the new set return result; } From 724993182c6d1ba0534508748d260a10abf8e3aa Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 9 Jan 2024 17:54:10 +0000 Subject: [PATCH 06/11] command_line/arguments: Improved the exclusive arguments handling to bypass the required arguments checking if exactly one is given --- impl/command_line/arguments.cxx | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/impl/command_line/arguments.cxx b/impl/command_line/arguments.cxx index dafedf65..a0bdbb9a 100644 --- a/impl/command_line/arguments.cxx +++ b/impl/command_line/arguments.cxx @@ -161,7 +161,7 @@ namespace substrate::commandLine }, item); } - [[nodiscard]] static bool checkExclusivity(const std::set &options) noexcept + [[nodiscard]] static size_t checkExclusivity(const std::set &options) noexcept { std::set exclusiveOptions{}; // Loop through all the visited options @@ -179,7 +179,7 @@ namespace substrate::commandLine }, option); } // Now we've collected all the options that are exclusive, display diagnostics - // if there is more than one in the set and return failure, otherwise success + // if there is more than one in the set and then return how many there are if (exclusiveOptions.size() > 1) { console.error("Multiple mutually exclusive options given together on command line, only one allowed."sv); @@ -187,7 +187,7 @@ namespace substrate::commandLine for (const auto &option : exclusiveOptions) console.error(" "sv, option.displayName()); } - return exclusiveOptions.size() <= 1; + return exclusiveOptions.size(); } // NOLINTNEXTLINE(readability-convert-member-functions-to-static) @@ -211,9 +211,13 @@ namespace substrate::commandLine } } // Having parsed as many options as we can, collect all exclusive options seen and - // perform the exclusivity check - if (!checkExclusivity(optionsVisited)) + // perform the exclusivity check (there may not be more than 1 exclusive option given) + const auto exclusiveOptions{checkExclusivity(optionsVisited)}; + if (exclusiveOptions > 1U) return false; + // If there was just one exclusive option, return true to short-circuit the required options check + if (exclusiveOptions == 1U) + return true; // Having parsed as many options as we can, collect all the required options into a set const auto requiredOptions{collectRequiredOptions(options)}; optionsVisited_t missingOptions{}; From d390978b47ed9d7e5515b913d557d9d122282529 Mon Sep 17 00:00:00 2001 From: "L. E. Segovia" Date: Tue, 9 Jan 2024 18:59:19 -0300 Subject: [PATCH 07/11] command_line/arguments_t: Expose optionsVisited_t to clean up its downstream usage --- impl/command_line/arguments.cxx | 14 ++++++++------ substrate/command_line/arguments | 4 +++- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/impl/command_line/arguments.cxx b/impl/command_line/arguments.cxx index a0bdbb9a..0012657f 100644 --- a/impl/command_line/arguments.cxx +++ b/impl/command_line/arguments.cxx @@ -8,6 +8,7 @@ using namespace std::literals::string_literals; using namespace std::literals::string_view_literals; +using optionsVisited_t = substrate::commandLine::arguments_t::optionsVisited_t; namespace substrate::commandLine { @@ -129,7 +130,7 @@ namespace substrate::commandLine [[nodiscard]] static auto collectRequiredOptions(const options_t &options) noexcept { // Build a set of all the required options defined in this options_t - std::set requiredOptions{}; + optionsVisited_t requiredOptions{}; for (const auto &option : options) { // If the optionItem_t is a bad variant, ignore it @@ -161,7 +162,7 @@ namespace substrate::commandLine }, item); } - [[nodiscard]] static size_t checkExclusivity(const std::set &options) noexcept + [[nodiscard]] static size_t checkExclusivity(const optionsVisited_t &options) noexcept { std::set exclusiveOptions{}; // Loop through all the visited options @@ -191,6 +192,7 @@ namespace substrate::commandLine } // NOLINTNEXTLINE(readability-convert-member-functions-to-static) + // NOLINTNEXTLINE(performance-unnecessary-value-param) bool arguments_t::parseFrom(tokeniser_t &lexer, const options_t &options, const optionsVisited_t globalOptions) { const auto &token{lexer.token()}; @@ -238,7 +240,7 @@ namespace substrate::commandLine const std::string_view &argument) noexcept; static std::optional matchOptionSet(tokeniser_t &lexer, const optionSet_t &option, const std::string_view &argument, const options_t &options, - const std::set &globalOptions) noexcept; + const optionsVisited_t &globalOptions) noexcept; template static bool checkMatchValid(const optionsItem_t &option, set_t &optionsVisited) noexcept; template static std::optional handleResult(arguments_t &arguments, const optionsItem_t &option, set_t &optionsVisited, const std::string_view &argument, const optionMatch_t &match) noexcept; @@ -361,8 +363,8 @@ namespace substrate::commandLine return flag_t{option.metaName(), std::move(*value)}; } - static std::set gatherGlobals(const options_t &options, - const std::set &globalOptions) noexcept + static auto gatherGlobals(const options_t &options, + const optionsVisited_t &globalOptions) noexcept { // Clone the existing set of global options auto result{globalOptions}; @@ -390,7 +392,7 @@ namespace substrate::commandLine static std::optional matchOptionSet(tokeniser_t &lexer, const optionSet_t &option, const std::string_view &argument, const options_t &options, - const std::set &globalOptions) noexcept + const optionsVisited_t &globalOptions) noexcept { // Check if we're parsing an alternation from a set const auto match{option.matches(argument)}; diff --git a/substrate/command_line/arguments b/substrate/command_line/arguments index 8f58ba6f..202b6409 100644 --- a/substrate/command_line/arguments +++ b/substrate/command_line/arguments @@ -40,10 +40,12 @@ namespace substrate::commandLine struct SUBSTRATE_CLS_API arguments_t { + public: + using optionsVisited_t = std::set; + private: using storage_t = std::multiset>; using iterator_t = typename storage_t::const_iterator; - using optionsVisited_t = std::set; storage_t _arguments; From ff555e4d8516eda5b15c2b73271586ffe421e0b3 Mon Sep 17 00:00:00 2001 From: "L. E. Segovia" Date: Tue, 9 Jan 2024 19:01:49 -0300 Subject: [PATCH 08/11] command_line/arguments_t: Use default wherever possible A broken `= default;` in the header is recoverable by forward declaring in the header, then using it in a translation unit (once the class is complete). --- impl/command_line/arguments.cxx | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/impl/command_line/arguments.cxx b/impl/command_line/arguments.cxx index 0012657f..4964bc4f 100644 --- a/impl/command_line/arguments.cxx +++ b/impl/command_line/arguments.cxx @@ -472,12 +472,10 @@ namespace substrate::commandLine } // Implementation of the innards of arguments_t as otherwise we get compile errors - // NOLINTNEXTLINE(modernize-use-equals-default) - arguments_t::arguments_t() noexcept : _arguments{} { } - arguments_t::arguments_t(const arguments_t &arguments) noexcept : _arguments{arguments._arguments} { } - arguments_t::arguments_t(arguments_t &&arguments) noexcept : _arguments{std::move(arguments._arguments)} { } - // NOLINTNEXTLINE(modernize-use-equals-default) - arguments_t::~arguments_t() noexcept { } + arguments_t::arguments_t() noexcept = default; + arguments_t::arguments_t(const arguments_t &arguments) noexcept = default; + arguments_t::arguments_t(arguments_t &&arguments) noexcept = default; + arguments_t::~arguments_t() noexcept = default; size_t arguments_t::count() const noexcept { return _arguments.size(); } size_t arguments_t::countMatching(const std::string_view &option) const noexcept @@ -489,17 +487,9 @@ namespace substrate::commandLine arguments_t::iterator_t arguments_t::find(const std::string_view &option) const noexcept { return _arguments.find(option); } - arguments_t &arguments_t::operator =(const arguments_t &arguments) noexcept - { - _arguments = arguments._arguments; - return *this; - } + arguments_t &arguments_t::operator =(const arguments_t &arguments) noexcept = default; - arguments_t &arguments_t::operator =(arguments_t &&arguments) noexcept - { - _arguments = std::move(arguments._arguments); - return *this; - } + arguments_t &arguments_t::operator =(arguments_t &&arguments) noexcept = default; // NOLINTNEXTLINE(readability-convert-member-functions-to-static) std::vector arguments_t::findAll(const std::string_view &option) const noexcept From ddd5a6b43e111bc8c03cb16bf4e333d788a9823c Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 9 Jan 2024 22:23:14 +0000 Subject: [PATCH 09/11] command_line/arguments: Clean up the operator organisation for arguments_t slightly --- impl/command_line/arguments.cxx | 6 ++---- substrate/command_line/arguments | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/impl/command_line/arguments.cxx b/impl/command_line/arguments.cxx index 4964bc4f..11e32d65 100644 --- a/impl/command_line/arguments.cxx +++ b/impl/command_line/arguments.cxx @@ -476,6 +476,8 @@ namespace substrate::commandLine arguments_t::arguments_t(const arguments_t &arguments) noexcept = default; arguments_t::arguments_t(arguments_t &&arguments) noexcept = default; arguments_t::~arguments_t() noexcept = default; + arguments_t &arguments_t::operator =(const arguments_t &arguments) noexcept = default; + arguments_t &arguments_t::operator =(arguments_t &&arguments) noexcept = default; size_t arguments_t::count() const noexcept { return _arguments.size(); } size_t arguments_t::countMatching(const std::string_view &option) const noexcept @@ -487,10 +489,6 @@ namespace substrate::commandLine arguments_t::iterator_t arguments_t::find(const std::string_view &option) const noexcept { return _arguments.find(option); } - arguments_t &arguments_t::operator =(const arguments_t &arguments) noexcept = default; - - arguments_t &arguments_t::operator =(arguments_t &&arguments) noexcept = default; - // NOLINTNEXTLINE(readability-convert-member-functions-to-static) std::vector arguments_t::findAll(const std::string_view &option) const noexcept { diff --git a/substrate/command_line/arguments b/substrate/command_line/arguments index 202b6409..e179ae16 100644 --- a/substrate/command_line/arguments +++ b/substrate/command_line/arguments @@ -47,7 +47,7 @@ namespace substrate::commandLine using storage_t = std::multiset>; using iterator_t = typename storage_t::const_iterator; - storage_t _arguments; + storage_t _arguments{}; [[nodiscard]] std::optional parseArgument(internal::tokeniser_t &lexer, const options_t &options, const optionsVisited_t &globalOptions, optionsVisited_t &optionsVisited) noexcept; From c5f6f5b5f2af6742f1e995b7e343a6da200ec463 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Tue, 9 Jan 2024 22:28:45 +0000 Subject: [PATCH 10/11] command_line/options: Mark the end of option_t::typeToValue() unreachable --- impl/command_line/options.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/impl/command_line/options.cxx b/impl/command_line/options.cxx index fb2c7ddc..18d60344 100644 --- a/impl/command_line/options.cxx +++ b/impl/command_line/options.cxx @@ -6,6 +6,7 @@ #include #include #include +#include using namespace std::literals::string_literals; using namespace std::literals::string_view_literals; @@ -201,6 +202,7 @@ namespace substrate::commandLine case optionValueType_t::userDefined: return "VAL"sv; } + substrate::unreachable(); } [[nodiscard]] std::string option_t::displayName() const noexcept @@ -220,9 +222,7 @@ namespace substrate::commandLine { [&](const std::string_view &option) { return std::string{option} + typeValue; }, [&](const optionFlagPair_t &option) - { - return std::string{option._shortFlag} + ", "s + std::string{option._longFlag} + typeValue; - }, + { return std::string{option._shortFlag} + ", "s + std::string{option._longFlag} + typeValue; }, [&](const optionValue_t &option) { return std::string{option.metaName()} + (isRepeatable() ? "..."s : ""s); } }, _option); } From b74a01b11b892b09808fb86e0c694d3cbafd212b Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 10 Jan 2024 00:29:30 +0000 Subject: [PATCH 11/11] command_line/options: Adjust the arguments_t copy constructor/operator `noexcept` markings noting that std::multiset can throw when copied --- impl/command_line/arguments.cxx | 4 ++-- substrate/command_line/arguments | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/impl/command_line/arguments.cxx b/impl/command_line/arguments.cxx index 11e32d65..276f766c 100644 --- a/impl/command_line/arguments.cxx +++ b/impl/command_line/arguments.cxx @@ -473,10 +473,10 @@ namespace substrate::commandLine // Implementation of the innards of arguments_t as otherwise we get compile errors arguments_t::arguments_t() noexcept = default; - arguments_t::arguments_t(const arguments_t &arguments) noexcept = default; + arguments_t::arguments_t(const arguments_t &arguments) = default; arguments_t::arguments_t(arguments_t &&arguments) noexcept = default; arguments_t::~arguments_t() noexcept = default; - arguments_t &arguments_t::operator =(const arguments_t &arguments) noexcept = default; + arguments_t &arguments_t::operator =(const arguments_t &arguments) = default; arguments_t &arguments_t::operator =(arguments_t &&arguments) noexcept = default; size_t arguments_t::count() const noexcept { return _arguments.size(); } diff --git a/substrate/command_line/arguments b/substrate/command_line/arguments index e179ae16..f0a5bc15 100644 --- a/substrate/command_line/arguments +++ b/substrate/command_line/arguments @@ -54,10 +54,10 @@ namespace substrate::commandLine public: arguments_t() noexcept; - arguments_t(const arguments_t &arguments) noexcept; + arguments_t(const arguments_t &arguments); arguments_t(arguments_t &&arguments) noexcept; ~arguments_t() noexcept; - arguments_t &operator =(const arguments_t &arguments) noexcept; + arguments_t &operator =(const arguments_t &arguments); arguments_t &operator =(arguments_t &&arguments) noexcept; [[nodiscard]] bool parseFrom(internal::tokeniser_t &lexer, const options_t &options,