Fix parsing of std::vector and add test, example and documentation (#182)
Improve parsing into std::vector so that a single argument can take a list.
This commit is contained in:
parent
1eca210edc
commit
7b14d5f60b
12
README.md
12
README.md
@ -116,6 +116,18 @@ There is no way to disambiguate positional arguments from the value following
|
||||
a boolean, so we have chosen that they will be positional arguments, and
|
||||
therefore, `-o false` does not work.
|
||||
|
||||
## `std::vector<T>` values
|
||||
|
||||
Parsing of list of values in form of an `std::vector<T>` is also supported, as long as `T`
|
||||
can be parsed. To separate single values in a list the definition `CXXOPTS_VECTOR_DELIMITER`
|
||||
is used, which is ',' by default. Ensure that you use no whitespaces between values because
|
||||
those would be interpreted as the next command line option. Example for a command line option
|
||||
that can be parsed as a `std::vector<double>`:
|
||||
|
||||
~~~
|
||||
--my_list=1,-2.1,3,4.5
|
||||
~~~
|
||||
|
||||
## Custom help
|
||||
|
||||
The string after the program name on the first line of the help can be
|
||||
|
@ -44,6 +44,10 @@ THE SOFTWARE.
|
||||
#define CXXOPTS_HAS_OPTIONAL
|
||||
#endif
|
||||
|
||||
#ifndef CXXOPTS_VECTOR_DELIMITER
|
||||
#define CXXOPTS_VECTOR_DELIMITER ','
|
||||
#endif
|
||||
|
||||
#define CXXOPTS__VERSION_MAJOR 2
|
||||
#define CXXOPTS__VERSION_MINOR 2
|
||||
#define CXXOPTS__VERSION_PATCH 0
|
||||
@ -715,9 +719,13 @@ namespace cxxopts
|
||||
void
|
||||
parse_value(const std::string& text, std::vector<T>& value)
|
||||
{
|
||||
T v;
|
||||
parse_value(text, v);
|
||||
value.push_back(v);
|
||||
std::stringstream in(text);
|
||||
std::string token;
|
||||
while(in.eof() == false && std::getline(in, token, CXXOPTS_VECTOR_DELIMITER)) {
|
||||
T v;
|
||||
parse_value(token, v);
|
||||
value.emplace_back(std::move(v));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CXXOPTS_HAS_OPTIONAL
|
||||
|
@ -56,6 +56,7 @@ parse(int argc, char* argv[])
|
||||
("help", "Print help")
|
||||
("int", "An integer", cxxopts::value<int>(), "N")
|
||||
("float", "A floating point number", cxxopts::value<float>())
|
||||
("vector", "A list of doubles", cxxopts::value<std::vector<double>>())
|
||||
("option_that_is_too_long_for_the_help", "A very long option")
|
||||
#ifdef CXXOPTS_USE_UNICODE
|
||||
("unicode", u8"A help option with non-ascii: à. Here the size of the"
|
||||
@ -130,6 +131,16 @@ parse(int argc, char* argv[])
|
||||
std::cout << "float = " << result["float"].as<float>() << std::endl;
|
||||
}
|
||||
|
||||
if (result.count("vector"))
|
||||
{
|
||||
std::cout << "vector = ";
|
||||
const auto values = result["vector"].as<std::vector<double>>();
|
||||
for (const auto& v : values) {
|
||||
std::cout << v << ", ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "Arguments remain = " << argc << std::endl;
|
||||
|
||||
return result;
|
||||
|
@ -512,6 +512,26 @@ TEST_CASE("Booleans", "[boolean]") {
|
||||
REQUIRE(result.count("others") == 1);
|
||||
}
|
||||
|
||||
TEST_CASE("std::vector", "[vector]") {
|
||||
std::vector<double> vector;
|
||||
cxxopts::Options options("vector", " - tests vector");
|
||||
options.add_options()
|
||||
("vector", "an vector option", cxxopts::value<std::vector<double>>(vector));
|
||||
|
||||
Argv av({"vector", "--vector", "1,-2.1,3,4.5"});
|
||||
|
||||
char** argv = av.argv();
|
||||
auto argc = av.argc();
|
||||
|
||||
options.parse(argc, argv);
|
||||
|
||||
REQUIRE(vector.size() == 4);
|
||||
CHECK(vector[0] == 1);
|
||||
CHECK(vector[1] == -2.1);
|
||||
CHECK(vector[2] == 3);
|
||||
CHECK(vector[3] == 4.5);
|
||||
}
|
||||
|
||||
#ifdef CXXOPTS_HAS_OPTIONAL
|
||||
TEST_CASE("std::optional", "[optional]") {
|
||||
std::optional<std::string> optional;
|
||||
|
Loading…
Reference in New Issue
Block a user