Fix comparing iterators from a different container.
This commit is contained in:
Jarryd Beck 2023-01-11 17:33:53 +11:00
parent 1bd4786c16
commit 4a3d4dbfe0
2 changed files with 54 additions and 3 deletions

View File

@ -1549,17 +1549,37 @@ class ParseResult
Iterator() = default; Iterator() = default;
Iterator(const Iterator&) = default; Iterator(const Iterator&) = default;
// GCC complains about m_iter not being initialised in the member
// initializer list
CXXOPTS_IGNORE_WARNING("-Weffc++")
Iterator(const ParseResult *pr, bool end=false) Iterator(const ParseResult *pr, bool end=false)
: m_pr(pr) : m_pr(pr)
, m_iter(end? pr->m_defaults.end(): pr->m_sequential.begin())
{ {
if (end)
{
m_sequential = false;
m_iter = m_pr->m_defaults.end();
}
else
{
m_sequential = true;
m_iter = m_pr->m_sequential.begin();
if (m_iter == m_pr->m_sequential.end())
{
m_sequential = false;
m_iter = m_pr->m_defaults.begin();
}
}
} }
CXXOPTS_DIAGNOSTIC_POP
Iterator& operator++() Iterator& operator++()
{ {
++m_iter; ++m_iter;
if(m_iter == m_pr->m_sequential.end()) if(m_sequential && m_iter == m_pr->m_sequential.end())
{ {
m_sequential = false;
m_iter = m_pr->m_defaults.begin(); m_iter = m_pr->m_defaults.begin();
return *this; return *this;
} }
@ -1575,7 +1595,7 @@ class ParseResult
bool operator==(const Iterator& other) const bool operator==(const Iterator& other) const
{ {
return m_iter == other.m_iter; return (m_sequential == other.m_sequential) && (m_iter == other.m_iter);
} }
bool operator!=(const Iterator& other) const bool operator!=(const Iterator& other) const
@ -1596,6 +1616,7 @@ class ParseResult
private: private:
const ParseResult* m_pr; const ParseResult* m_pr;
std::vector<KeyValue>::const_iterator m_iter; std::vector<KeyValue>::const_iterator m_iter;
bool m_sequential = true;
}; };
ParseResult() = default; ParseResult() = default;

View File

@ -1,4 +1,5 @@
#include "catch.hpp" #include "catch.hpp"
#include <iostream>
#include <initializer_list> #include <initializer_list>
@ -923,6 +924,35 @@ TEST_CASE("Iterator", "[iterator]") {
REQUIRE(++iter == result.end()); REQUIRE(++iter == result.end());
} }
TEST_CASE("Iterator no args", "[iterator]") {
cxxopts::Options options("tester", " - test iterating over parse result");
options.add_options()
("value", "an option with a value", cxxopts::value<std::string>())
("default", "an option with default value", cxxopts::value<int>()->default_value("42"))
("nothing", "won't exist", cxxopts::value<std::string>())
;
Argv argv({
"tester",
});
auto** actual_argv = argv.argv();
auto argc = argv.argc();
auto result = options.parse(argc, actual_argv);
auto iter = result.begin();
REQUIRE(iter != result.end());
CHECK(iter->key() == "default");
CHECK(iter->value() == "42");
++iter;
CHECK(iter == result.end());
}
TEST_CASE("No Options help", "[options]") TEST_CASE("No Options help", "[options]")
{ {
std::vector<std::string> positional; std::vector<std::string> positional;