diff --git a/include/argparse.hpp b/include/argparse.hpp index faf1d74..560aaaa 100644 --- a/include/argparse.hpp +++ b/include/argparse.hpp @@ -1899,6 +1899,11 @@ namespace argparse ~ArgumentBuilder() noexcept(false) { + if (is_mutually_exclusive() && !is_allowed_in_mutually_exclusive_group()) + { + throw option_error("mutually exclusive arguments must be optional"); + } + if ((m_options.action == argparse::version) && m_options.help.empty()) { m_options.help = "show program's version number and exit"; @@ -1906,25 +1911,10 @@ namespace argparse if (is_positional()) { - if (m_options.mutually_exclusive_group != nullptr - && (!m_options.nargs.has_value() - || (!std::holds_alternative(*m_options.nargs) - || (std::get(*m_options.nargs) != zero_or_one - && std::get(*m_options.nargs) != zero_or_more)))) - { - throw option_error("mutually exclusive arguments must be optional"); - } - m_arguments.emplace_back(PositionalArgument(std::move(m_options))); } else { - if (m_options.mutually_exclusive_group != nullptr - && m_options.required) - { - throw option_error("mutually exclusive arguments must be optional"); - } - m_arguments.emplace_back(OptionalArgument(std::move(m_options))); } } @@ -2025,6 +2015,40 @@ namespace argparse return !m_options.names.front().starts_with('-'); } + auto is_mutually_exclusive() const -> bool + { + return m_options.mutually_exclusive_group != nullptr; + } + + auto is_allowed_in_mutually_exclusive_group() const -> bool + { + if (is_positional()) + { + return is_optional_by_nargs_option(); + } + else + { + return !m_options.required; + } + } + + auto is_optional_by_nargs_option() const -> bool + { + if (!m_options.nargs.has_value()) + { + return false; + } + + if (!std::holds_alternative(*m_options.nargs)) + { + return false; + } + + auto const nargs = std::get(*m_options.nargs); + + return nargs == zero_or_one || nargs == zero_or_more; + } + private: Arguments & m_arguments; OptString & m_version;