mirror of
https://github.com/KeqingMoe/argparse.git
synced 2025-07-03 22:54:39 +00:00
Get arguments in optional<T> with .present<T>()
fixes: p-ranav/argparse#66
This commit is contained in:
parent
4277e68e57
commit
e6c6c9b31c
12
README.md
12
README.md
@ -140,6 +140,18 @@ program.add_argument("-o", "--output")
|
||||
.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
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
/*
|
||||
* 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>
|
||||
static auto any_cast_container(const std::vector<std::any> &aOperand) -> T {
|
||||
using ValueType = typename T::value_type;
|
||||
@ -811,14 +828,25 @@ public:
|
||||
parse_args(arguments);
|
||||
}
|
||||
|
||||
/* Getter enabled for all template types other than std::vector and std::list
|
||||
* @throws std::logic_error in case of an invalid argument name
|
||||
* @throws std::logic_error in case of incompatible types
|
||||
/* Getter for options with default values.
|
||||
* @throws std::logic_error if there is no such option
|
||||
* @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) {
|
||||
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
|
||||
* Used in conjuction with Argument.operator== e.g., parser["foo"] == true
|
||||
* @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");
|
||||
}
|
||||
|
||||
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")) {
|
||||
argparse::ArgumentParser program("test");
|
||||
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);
|
||||
}
|
||||
|
||||
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")) {
|
||||
argparse::ArgumentParser program("test");
|
||||
program.add_argument("--vector")
|
||||
|
Loading…
Reference in New Issue
Block a user