diff --git a/include/argparse.hpp b/include/argparse.hpp index d30643a..4ac2468 100644 --- a/include/argparse.hpp +++ b/include/argparse.hpp @@ -1897,7 +1897,7 @@ namespace argparse m_options.mutually_exclusive_group = group; } - ~ArgumentBuilder() + ~ArgumentBuilder() noexcept(false) { if ((m_options.action == argparse::version) && m_options.help.empty()) { @@ -1906,6 +1906,15 @@ 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 diff --git a/test/unittest/test_argument_parser.cpp b/test/unittest/test_argument_parser.cpp index ec69ec7..e8a9062 100644 --- a/test/unittest/test_argument_parser.cpp +++ b/test/unittest/test_argument_parser.cpp @@ -350,6 +350,23 @@ TEST_CASE("ArgumentParser supports mutually exclusive groups") CHECK_NOTHROW(parser.add_mutually_exclusive_group()); } +TEST_CASE("Adding a positional argument to a mutually exclusive group results in error") +{ + auto parser = argparse::ArgumentParser(); + auto group = parser.add_mutually_exclusive_group(); + + CHECK_THROWS_WITH_AS(group.add_argument("pos"), "mutually exclusive arguments must be optional", argparse::option_error); +} + +TEST_CASE("Adding a non-required positional argument to a mutually exclusive group does not result in error") +{ + auto parser = argparse::ArgumentParser(); + auto group = parser.add_mutually_exclusive_group(); + + CHECK_NOTHROW(group.add_argument("pos").nargs(argparse::zero_or_one)); + CHECK_NOTHROW(group.add_argument("pos").nargs(argparse::zero_or_more)); +} + TEST_CASE("Adding an optional argument to a mutually exclusive group does not result in error") { auto parser = argparse::ArgumentParser();