Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Marked copy and move constructors as deleted #304

Merged
merged 1 commit into from
Nov 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
* [Positional Arguments with Compound Toggle Arguments](#positional-arguments-with-compound-toggle-arguments)
* [Restricting the set of values for an argument](#restricting-the-set-of-values-for-an-argument)
* [Using `option=value` syntax](#using-optionvalue-syntax)
* [Developer Notes](#developer-notes)
* [Copying and Moving](#copying-and-moving)
* [CMake Integration](#cmake-integration)
* [Building, Installing, and Testing](#building-installing-and-testing)
* [Supported Toolchains](#supported-toolchains)
Expand Down Expand Up @@ -1198,7 +1200,7 @@ foo@bar:/home/dev/$ ./main 6
Invalid argument "6" - allowed options: {0, 1, 2, 3, 4, 5}
```

## Using `option=value` syntax
### Using `option=value` syntax

```cpp
#include "argparse.hpp"
Expand Down Expand Up @@ -1234,6 +1236,12 @@ foo@bar:/home/dev/$ ./test --bar=BAR --foo
--bar: BAR
```

## Developer Notes

### Copying and Moving

`argparse::ArgumentParser` is intended to be used in a single function - setup everything and parse arguments in one place. Attempting to move or copy invalidates internal references (issue #260). Thus, starting with v3.0, `argparse::ArgumentParser` copy and move constructors are marked as `delete`.

## CMake Integration

Use the latest argparse in your CMake project without copying any content.
Expand Down
65 changes: 13 additions & 52 deletions include/argparse/argparse.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1395,53 +1395,18 @@ class ArgumentParser {
}
}

ArgumentParser(ArgumentParser &&) noexcept = default;
ArgumentParser &operator=(ArgumentParser &&) = default;

ArgumentParser(const ArgumentParser &other)
: m_program_name(other.m_program_name), m_version(other.m_version),
m_description(other.m_description), m_epilog(other.m_epilog),
m_prefix_chars(other.m_prefix_chars),
m_assign_chars(other.m_assign_chars), m_is_parsed(other.m_is_parsed),
m_positional_arguments(other.m_positional_arguments),
m_optional_arguments(other.m_optional_arguments),
m_parser_path(other.m_parser_path), m_subparsers(other.m_subparsers),
m_suppress(other.m_suppress) {
for (auto it = std::begin(m_positional_arguments);
it != std::end(m_positional_arguments); ++it) {
index_argument(it);
}
for (auto it = std::begin(m_optional_arguments);
it != std::end(m_optional_arguments); ++it) {
index_argument(it);
}
for (auto it = std::begin(m_subparsers); it != std::end(m_subparsers);
++it) {
m_subparser_map.insert_or_assign(it->get().m_program_name, it);
m_subparser_used.insert_or_assign(it->get().m_program_name, false);
}

for (const auto &g : other.m_mutually_exclusive_groups) {
MutuallyExclusiveGroup group(*this, g.m_required);
for (const auto &arg : g.m_elements) {
// Find argument in argument map and add reference to it
// in new group
// argument_it = other.m_argument_map.find("name")
auto first_name = arg->m_names[0];
auto it = m_argument_map.find(first_name);
group.m_elements.push_back(&(*it->second));
}
m_mutually_exclusive_groups.push_back(std::move(group));
}
}

~ArgumentParser() = default;

ArgumentParser &operator=(const ArgumentParser &other) {
auto tmp = other;
std::swap(*this, tmp);
return *this;
}
// ArgumentParser is meant to be used in a single function.
// Setup everything and parse arguments in one place.
//
// ArgumentParser internally uses std::string_views,
// references, iterators, etc.
// Many of these elements become invalidated after a copy or move.
ArgumentParser(const ArgumentParser &other) = delete;
ArgumentParser &operator=(const ArgumentParser &other) = delete;
ArgumentParser(ArgumentParser &&) noexcept = delete;
ArgumentParser &operator=(ArgumentParser &&) = delete;

explicit operator bool() const {
auto arg_used = std::any_of(m_argument_map.cbegin(), m_argument_map.cend(),
Expand Down Expand Up @@ -1749,10 +1714,8 @@ class ArgumentParser {
}

bool has_visible_subcommands = std::any_of(
parser.m_subparser_map.begin(),
parser.m_subparser_map.end(),
[] (auto &p) { return !p.second->get().m_suppress; }
);
parser.m_subparser_map.begin(), parser.m_subparser_map.end(),
[](auto &p) { return !p.second->get().m_suppress; });

if (has_visible_subcommands) {
stream << (parser.m_positional_arguments.empty()
Expand Down Expand Up @@ -1842,9 +1805,7 @@ class ArgumentParser {
m_subparser_used.insert_or_assign(parser.m_program_name, false);
}

void set_suppress(bool suppress) {
m_suppress = suppress;
}
void set_suppress(bool suppress) { m_suppress = suppress; }

private:
bool is_valid_prefix_char(char c) const {
Expand Down
2 changes: 0 additions & 2 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ file(GLOB ARGPARSE_TEST_SOURCES
test_choices.cpp
test_compound_arguments.cpp
test_container_arguments.cpp
test_const_correct.cpp
test_default_args.cpp
test_default_value.cpp
test_error_reporting.cpp
Expand All @@ -51,7 +50,6 @@ file(GLOB ARGPARSE_TEST_SOURCES
test_required_arguments.cpp
test_scan.cpp
test_stringstream.cpp
test_value_semantics.cpp
test_version.cpp
test_subparsers.cpp
test_parse_known_args.cpp
Expand Down
31 changes: 0 additions & 31 deletions test/test_const_correct.cpp

This file was deleted.

17 changes: 0 additions & 17 deletions test/test_mutually_exclusive_group.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,23 +52,6 @@ TEST_CASE(
std::runtime_error);
}

TEST_CASE(
"Create mutually exclusive group with 2 arguments, then copy the parser" *
test_suite("mutex_args")) {
argparse::ArgumentParser program("test");

auto &group = program.add_mutually_exclusive_group();
group.add_argument("--first");
group.add_argument("--second");

auto program_copy(program);

REQUIRE_THROWS_WITH_AS(
program_copy.parse_args({"test", "--first", "1", "--second", "2"}),
"Argument '--second VAR' not allowed with '--first VAR'",
std::runtime_error);
}

TEST_CASE("Create mutually exclusive group with 3 arguments" *
test_suite("mutex_args")) {
argparse::ArgumentParser program("test");
Expand Down
100 changes: 0 additions & 100 deletions test/test_value_semantics.cpp

This file was deleted.

Loading