Added parsing of general types. (#63)

Adds generic parsing of types using `operator>>`, in particular allows
parsing of floats and doubles.
This commit is contained in:
Hannah Rittich 2017-08-16 09:55:06 +02:00 committed by jarro2783
parent da9210d41e
commit 2aed1ce41b
3 changed files with 53 additions and 0 deletions

View File

@ -533,6 +533,16 @@ namespace cxxopts
} }
} }
template <typename T>
void stringstream_parser(const std::string& text, T& value)
{
std::stringstream in(text);
in >> value;
if (!in) {
throw argument_incorrect_type(text);
}
}
inline inline
void void
parse_value(const std::string& text, uint8_t& value) parse_value(const std::string& text, uint8_t& value)
@ -605,6 +615,15 @@ namespace cxxopts
value = text; value = text;
} }
// The fallback parser. It uses the stringstream parser to parse all types
// that have not been overloaded explicitly. It has to be placed in the
// source code before all other more specialized templates.
template <typename T>
void
parse_value(const std::string& text, T& value) {
stringstream_parser(text, value);
}
template <typename T> template <typename T>
void void
parse_value(const std::string& text, std::vector<T>& value) parse_value(const std::string& text, std::vector<T>& value)

View File

@ -49,6 +49,7 @@ int main(int argc, char* argv[])
"thisisareallylongwordthattakesupthewholelineandcannotbebrokenataspace") "thisisareallylongwordthattakesupthewholelineandcannotbebrokenataspace")
("help", "Print help") ("help", "Print help")
("int", "An integer", cxxopts::value<int>(), "N") ("int", "An integer", cxxopts::value<int>(), "N")
("float", "A floating point number", cxxopts::value<float>())
("option_that_is_too_long_for_the_help", "A very long option") ("option_that_is_too_long_for_the_help", "A very long option")
#ifdef CXXOPTS_USE_UNICODE #ifdef CXXOPTS_USE_UNICODE
("unicode", u8"A help option with non-ascii: à. Here the size of the" ("unicode", u8"A help option with non-ascii: à. Here the size of the"
@ -118,6 +119,11 @@ int main(int argc, char* argv[])
std::cout << "int = " << options["int"].as<int>() << std::endl; std::cout << "int = " << options["int"].as<int>() << std::endl;
} }
if (options.count("float"))
{
std::cout << "float = " << options["float"].as<float>() << std::endl;
}
std::cout << "Arguments remain = " << argc << std::endl; std::cout << "Arguments remain = " << argc << std::endl;
} catch (const cxxopts::OptionException& e) } catch (const cxxopts::OptionException& e)

View File

@ -336,3 +336,31 @@ TEST_CASE("Integer overflow", "[options]")
options.parse_positional("positional"); options.parse_positional("positional");
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::argument_incorrect_type); CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::argument_incorrect_type);
} }
TEST_CASE("Floats", "[options]")
{
cxxopts::Options options("parses_floats", "parses floats correctly");
options.add_options()
("double", "Double precision", cxxopts::value<double>())
("positional", "Floats", cxxopts::value<std::vector<float>>());
Argv av({"floats", "--double", "0.5", "--", "4", "-4", "1.5e6", "-1.5e6"});
char** argv = av.argv();
auto argc = av.argc();
options.parse_positional("positional");
options.parse(argc, argv);
REQUIRE(options.count("double") == 1);
REQUIRE(options.count("positional") == 4);
CHECK(options["double"].as<double>() == 0.5);
auto& positional = options["positional"].as<std::vector<float>>();
CHECK(positional[0] == 4);
CHECK(positional[1] == -4);
CHECK(positional[2] == 1.5e6);
CHECK(positional[3] == -1.5e6);
}