Skip to content

Commit

Permalink
Extend cxxopts API to support as_optional in addition to as query of …
Browse files Browse the repository at this point in the history
…values (#421)

Co-authored-by: Nigel Stewart <[email protected]>
  • Loading branch information
nigels-com and Nigel Stewart authored Feb 29, 2024
1 parent 4bf61f0 commit 70fb4e4
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
27 changes: 27 additions & 0 deletions include/cxxopts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1538,6 +1538,15 @@ CXXOPTS_DIAGNOSTIC_POP
return CXXOPTS_RTTI_CAST<const values::standard_value<T>&>(*m_value).get();
}

#ifdef CXXOPTS_HAS_OPTIONAL
template <typename T>
std::optional<T>
as_optional() const
{
return as<T>();
}
#endif

private:
void
ensure_value(const std::shared_ptr<const OptionDetails>& details)
Expand Down Expand Up @@ -1750,6 +1759,24 @@ CXXOPTS_DIAGNOSTIC_POP
return viter->second;
}

#ifdef CXXOPTS_HAS_OPTIONAL
template <typename T>
std::optional<T>
as_optional(const std::string& option) const
{
auto iter = m_keys.find(option);
if (iter != m_keys.end())
{
auto viter = m_values.find(iter->second);
if (viter != m_values.end())
{
return viter->second.as_optional<T>();
}
}
return std::nullopt;
}
#endif

const std::vector<KeyValue>&
arguments() const
{
Expand Down
51 changes: 51 additions & 0 deletions test/options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,57 @@ TEST_CASE("Options empty", "[options]") {
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::exceptions::no_such_option);
}

#ifdef CXXOPTS_HAS_OPTIONAL
TEST_CASE("Optional value", "[optional]")
{
cxxopts::Options options("options", "query as std::optional");
options.add_options()
("int", "Integer", cxxopts::value<int>())
("float", "Float", cxxopts::value<float>())
("string", "String", cxxopts::value<std::string>())
;

SECTION("Available") {
Argv av({
"--int",
"42",
"--float",
"3.141",
"--string",
"Hello"
});

auto** argv = av.argv();
auto argc = av.argc();

auto result = options.parse(argc, argv);

CHECK(result.as_optional<int>("int"));
CHECK(result.as_optional<float>("float"));
CHECK(result.as_optional<string>("string"));

CHECK(*result.as_optional<int>("int") == 42);
CHECK(*result.as_optional<float>("float") == 3.141);
CHECK(*result.as_optional<string>("string") == "Hello");
}

SECTION("Unavailable") {
Argv av({
});

auto** argv = av.argv();
auto argc = av.argc();

auto result = options.parse(argc, argv);

CHECK(!result.as_optional<int>("int"));
CHECK(!result.as_optional<float>("float"));
CHECK(!result.as_optional<string>("string"));
}

}
#endif

TEST_CASE("Initializer list with group", "[options]") {
cxxopts::Options options("Initializer list group", " - test initializer list with group");

Expand Down

0 comments on commit 70fb4e4

Please sign in to comment.