mirror of
https://github.com/KeqingMoe/argparse.git
synced 2025-07-04 15:14:39 +00:00
Merge pull request #68 from zhihaoy/std-optional
Get arguments in optional<T> with .present<T>()
This commit is contained in:
commit
aed278419d
12
README.md
12
README.md
@ -140,6 +140,18 @@ program.add_argument("-o", "--output")
|
|||||||
.help("specify the output file.");
|
.help("specify the output file.");
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Accessing optional arguments without default values
|
||||||
|
|
||||||
|
If you do not require an optional argument to present but has no good default value for it, you can combine testing and accessing the argument as following:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
if (auto fn = program.present("-o")) {
|
||||||
|
do_something_with(*fn);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Similar to `get`, the `present` method also accepts a template argument. But rather than returning `T`, `parser.present<T>(key)` returns `std::optional<T>`, so that when the user does not provide a value to this parameter, the return value compares equal to `std::nullopt`.
|
||||||
|
|
||||||
### Negative Numbers
|
### Negative Numbers
|
||||||
|
|
||||||
Optional arguments start with ```-```. Can ```argparse``` handle negative numbers? The answer is yes!
|
Optional arguments start with ```-```. Can ```argparse``` handle negative numbers? The answer is yes!
|
||||||
|
@ -702,6 +702,23 @@ private:
|
|||||||
throw std::logic_error("No value provided");
|
throw std::logic_error("No value provided");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get argument value given a type.
|
||||||
|
* @pre The object has no default value.
|
||||||
|
* @returns The stored value if any, std::nullopt otherwise.
|
||||||
|
*/
|
||||||
|
template <typename T> auto present() const -> std::optional<T> {
|
||||||
|
if (mDefaultValue.has_value())
|
||||||
|
throw std::logic_error("Argument with default value always presents");
|
||||||
|
|
||||||
|
if (mValues.empty())
|
||||||
|
return std::nullopt;
|
||||||
|
else if constexpr (details::is_container_v<T>)
|
||||||
|
return any_cast_container<T>(mValues);
|
||||||
|
else
|
||||||
|
return std::any_cast<T>(mValues.front());
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static auto any_cast_container(const std::vector<std::any> &aOperand) -> T {
|
static auto any_cast_container(const std::vector<std::any> &aOperand) -> T {
|
||||||
using ValueType = typename T::value_type;
|
using ValueType = typename T::value_type;
|
||||||
@ -811,14 +828,25 @@ public:
|
|||||||
parse_args(arguments);
|
parse_args(arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Getter enabled for all template types other than std::vector and std::list
|
/* Getter for options with default values.
|
||||||
* @throws std::logic_error in case of an invalid argument name
|
* @throws std::logic_error if there is no such option
|
||||||
* @throws std::logic_error in case of incompatible types
|
* @throws std::logic_error if the option has no value
|
||||||
|
* @throws std::bad_any_cast if the option is not of type T
|
||||||
*/
|
*/
|
||||||
template <typename T = std::string> T get(std::string_view aArgumentName) {
|
template <typename T = std::string> T get(std::string_view aArgumentName) {
|
||||||
return (*this)[aArgumentName].get<T>();
|
return (*this)[aArgumentName].get<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Getter for options without default values.
|
||||||
|
* @pre The option has no default value.
|
||||||
|
* @throws std::logic_error if there is no such option
|
||||||
|
* @throws std::bad_any_cast if the option is not of type T
|
||||||
|
*/
|
||||||
|
template <typename T = std::string>
|
||||||
|
auto present(std::string_view aArgumentName) -> std::optional<T> {
|
||||||
|
return (*this)[aArgumentName].present<T>();
|
||||||
|
}
|
||||||
|
|
||||||
/* Indexing operator. Return a reference to an Argument object
|
/* Indexing operator. Return a reference to an Argument object
|
||||||
* Used in conjuction with Argument.operator== e.g., parser["foo"] == true
|
* Used in conjuction with Argument.operator== e.g., parser["foo"] == true
|
||||||
* @throws std::logic_error in case of an invalid argument name
|
* @throws std::logic_error in case of an invalid argument name
|
||||||
|
@ -19,6 +19,32 @@ TEST_CASE("Parse a string argument with default value" *
|
|||||||
REQUIRE(program.get("--config") == "foo.yml");
|
REQUIRE(program.get("--config") == "foo.yml");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Parse a string argument without default value" *
|
||||||
|
test_suite("parse_args")) {
|
||||||
|
argparse::ArgumentParser program("test");
|
||||||
|
program.add_argument("--config");
|
||||||
|
|
||||||
|
WHEN("no value provided") {
|
||||||
|
program.parse_args({"test"});
|
||||||
|
|
||||||
|
THEN("the option is nullopt") {
|
||||||
|
auto opt = program.present("--config");
|
||||||
|
REQUIRE_FALSE(opt);
|
||||||
|
REQUIRE(opt == std::nullopt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WHEN("a value is provided") {
|
||||||
|
program.parse_args({"test", "--config", ""});
|
||||||
|
|
||||||
|
THEN("the option has a value") {
|
||||||
|
auto opt = program.present("--config");
|
||||||
|
REQUIRE(opt);
|
||||||
|
REQUIRE(opt->empty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("Parse an int argument with value" * test_suite("parse_args")) {
|
TEST_CASE("Parse an int argument with value" * test_suite("parse_args")) {
|
||||||
argparse::ArgumentParser program("test");
|
argparse::ArgumentParser program("test");
|
||||||
program.add_argument("--count")
|
program.add_argument("--count")
|
||||||
@ -103,6 +129,37 @@ TEST_CASE("Parse a vector of float arguments" * test_suite("parse_args")) {
|
|||||||
REQUIRE(vector[4] == 5.5f);
|
REQUIRE(vector[4] == 5.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Parse a vector of float without default value" *
|
||||||
|
test_suite("parse_args")) {
|
||||||
|
argparse::ArgumentParser program("test");
|
||||||
|
program.add_argument("--vector").scan<'f', float>().nargs(3);
|
||||||
|
|
||||||
|
WHEN("no value is provided") {
|
||||||
|
program.parse_args({"test"});
|
||||||
|
|
||||||
|
THEN("the option is nullopt") {
|
||||||
|
auto opt = program.present<std::vector<float>>("--vector");
|
||||||
|
REQUIRE_FALSE(opt.has_value());
|
||||||
|
REQUIRE(opt == std::nullopt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WHEN("a value is provided") {
|
||||||
|
program.parse_args({"test", "--vector", ".3", "1.3", "6"});
|
||||||
|
|
||||||
|
THEN("the option has a value") {
|
||||||
|
auto opt = program.present<std::vector<float>>("--vector");
|
||||||
|
REQUIRE(opt.has_value());
|
||||||
|
|
||||||
|
auto &&vec = opt.value();
|
||||||
|
REQUIRE(vec.size() == 3);
|
||||||
|
REQUIRE(vec[0] == .3f);
|
||||||
|
REQUIRE(vec[1] == 1.3f);
|
||||||
|
REQUIRE(vec[2] == 6.f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("Parse a vector of double arguments" * test_suite("parse_args")) {
|
TEST_CASE("Parse a vector of double arguments" * test_suite("parse_args")) {
|
||||||
argparse::ArgumentParser program("test");
|
argparse::ArgumentParser program("test");
|
||||||
program.add_argument("--vector")
|
program.add_argument("--vector")
|
||||||
|
Loading…
Reference in New Issue
Block a user