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(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)
: 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++()
{
++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();
return *this;
}
@ -1575,7 +1595,7 @@ class ParseResult
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
@ -1596,6 +1616,7 @@ class ParseResult
private:
const ParseResult* m_pr;
std::vector<KeyValue>::const_iterator m_iter;
bool m_sequential = true;
};
ParseResult() = default;

View File

@ -1,4 +1,5 @@
#include "catch.hpp"
#include <iostream>
#include <initializer_list>
@ -923,6 +924,35 @@ TEST_CASE("Iterator", "[iterator]") {
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]")
{
std::vector<std::string> positional;