Commit 8010e06952858276d31ddf4e90497c87a919aca6
1 parent
d8458a8c
Move parse result to an immutable object
This is far from ideal, but it's the first step in moving the parse result to an immutable object so that the parser can be reused.
Showing
4 changed files
with
155 additions
and
145 deletions
CHANGELOG.md
0 → 100644
include/cxxopts.hpp
| @@ -34,6 +34,7 @@ THE SOFTWARE. | @@ -34,6 +34,7 @@ THE SOFTWARE. | ||
| 34 | #include <regex> | 34 | #include <regex> |
| 35 | #include <sstream> | 35 | #include <sstream> |
| 36 | #include <string> | 36 | #include <string> |
| 37 | +#include <unordered_map> | ||
| 37 | #include <unordered_set> | 38 | #include <unordered_set> |
| 38 | #include <vector> | 39 | #include <vector> |
| 39 | 40 | ||
| @@ -893,6 +894,77 @@ namespace cxxopts | @@ -893,6 +894,77 @@ namespace cxxopts | ||
| 893 | std::vector<HelpOptionDetails> options; | 894 | std::vector<HelpOptionDetails> options; |
| 894 | }; | 895 | }; |
| 895 | 896 | ||
| 897 | + class ParseResult | ||
| 898 | + { | ||
| 899 | + public: | ||
| 900 | + | ||
| 901 | + template <typename Iterator> | ||
| 902 | + ParseResult( | ||
| 903 | + Iterator, | ||
| 904 | + Iterator, | ||
| 905 | + std::vector<std::string>, | ||
| 906 | + int&, char**&); | ||
| 907 | + | ||
| 908 | + int | ||
| 909 | + count(const std::string& o) const | ||
| 910 | + { | ||
| 911 | + auto iter = m_options.find(o); | ||
| 912 | + if (iter == m_options.end()) | ||
| 913 | + { | ||
| 914 | + return 0; | ||
| 915 | + } | ||
| 916 | + | ||
| 917 | + return iter->second->count(); | ||
| 918 | + } | ||
| 919 | + | ||
| 920 | + const OptionDetails& | ||
| 921 | + operator[](const std::string& option) const | ||
| 922 | + { | ||
| 923 | + auto iter = m_options.find(option); | ||
| 924 | + | ||
| 925 | + if (iter == m_options.end()) | ||
| 926 | + { | ||
| 927 | + throw option_not_present_exception(option); | ||
| 928 | + } | ||
| 929 | + | ||
| 930 | + return *iter->second; | ||
| 931 | + } | ||
| 932 | + | ||
| 933 | + private: | ||
| 934 | + | ||
| 935 | + void | ||
| 936 | + parse(int& argc, char**& argv); | ||
| 937 | + | ||
| 938 | + void | ||
| 939 | + add_to_option(const std::string& option, const std::string& arg); | ||
| 940 | + | ||
| 941 | + bool | ||
| 942 | + consume_positional(std::string a); | ||
| 943 | + | ||
| 944 | + void | ||
| 945 | + parse_option | ||
| 946 | + ( | ||
| 947 | + std::shared_ptr<OptionDetails> value, | ||
| 948 | + const std::string& name, | ||
| 949 | + const std::string& arg = "" | ||
| 950 | + ); | ||
| 951 | + | ||
| 952 | + void | ||
| 953 | + checked_parse_arg | ||
| 954 | + ( | ||
| 955 | + int argc, | ||
| 956 | + char* argv[], | ||
| 957 | + int& current, | ||
| 958 | + std::shared_ptr<OptionDetails> value, | ||
| 959 | + const std::string& name | ||
| 960 | + ); | ||
| 961 | + | ||
| 962 | + std::unordered_map<std::string, std::shared_ptr<OptionDetails>> m_options; | ||
| 963 | + std::vector<std::string> m_positional; | ||
| 964 | + std::vector<std::string>::iterator m_next_positional; | ||
| 965 | + std::unordered_set<std::string> m_positional_set; | ||
| 966 | + }; | ||
| 967 | + | ||
| 896 | class Options | 968 | class Options |
| 897 | { | 969 | { |
| 898 | public: | 970 | public: |
| @@ -912,7 +984,7 @@ namespace cxxopts | @@ -912,7 +984,7 @@ namespace cxxopts | ||
| 912 | return *this; | 984 | return *this; |
| 913 | } | 985 | } |
| 914 | 986 | ||
| 915 | - void | 987 | + ParseResult |
| 916 | parse(int& argc, char**& argv); | 988 | parse(int& argc, char**& argv); |
| 917 | 989 | ||
| 918 | OptionAdder | 990 | OptionAdder |
| @@ -929,31 +1001,6 @@ namespace cxxopts | @@ -929,31 +1001,6 @@ namespace cxxopts | ||
| 929 | std::string arg_help | 1001 | std::string arg_help |
| 930 | ); | 1002 | ); |
| 931 | 1003 | ||
| 932 | - int | ||
| 933 | - count(const std::string& o) const | ||
| 934 | - { | ||
| 935 | - auto iter = m_options.find(o); | ||
| 936 | - if (iter == m_options.end()) | ||
| 937 | - { | ||
| 938 | - return 0; | ||
| 939 | - } | ||
| 940 | - | ||
| 941 | - return iter->second->count(); | ||
| 942 | - } | ||
| 943 | - | ||
| 944 | - const OptionDetails& | ||
| 945 | - operator[](const std::string& option) const | ||
| 946 | - { | ||
| 947 | - auto iter = m_options.find(option); | ||
| 948 | - | ||
| 949 | - if (iter == m_options.end()) | ||
| 950 | - { | ||
| 951 | - throw option_not_present_exception(option); | ||
| 952 | - } | ||
| 953 | - | ||
| 954 | - return *iter->second; | ||
| 955 | - } | ||
| 956 | - | ||
| 957 | //parse positional arguments into the given option | 1004 | //parse positional arguments into the given option |
| 958 | void | 1005 | void |
| 959 | parse_positional(std::string option); | 1006 | parse_positional(std::string option); |
| @@ -979,30 +1026,6 @@ namespace cxxopts | @@ -979,30 +1026,6 @@ namespace cxxopts | ||
| 979 | std::shared_ptr<OptionDetails> details | 1026 | std::shared_ptr<OptionDetails> details |
| 980 | ); | 1027 | ); |
| 981 | 1028 | ||
| 982 | - bool | ||
| 983 | - consume_positional(std::string a); | ||
| 984 | - | ||
| 985 | - void | ||
| 986 | - add_to_option(const std::string& option, const std::string& arg); | ||
| 987 | - | ||
| 988 | - void | ||
| 989 | - parse_option | ||
| 990 | - ( | ||
| 991 | - std::shared_ptr<OptionDetails> value, | ||
| 992 | - const std::string& name, | ||
| 993 | - const std::string& arg = "" | ||
| 994 | - ); | ||
| 995 | - | ||
| 996 | - void | ||
| 997 | - checked_parse_arg | ||
| 998 | - ( | ||
| 999 | - int argc, | ||
| 1000 | - char* argv[], | ||
| 1001 | - int& current, | ||
| 1002 | - std::shared_ptr<OptionDetails> value, | ||
| 1003 | - const std::string& name | ||
| 1004 | - ); | ||
| 1005 | - | ||
| 1006 | String | 1029 | String |
| 1007 | help_one_group(const std::string& group) const; | 1030 | help_one_group(const std::string& group) const; |
| 1008 | 1031 | ||
| @@ -1053,24 +1076,6 @@ namespace cxxopts | @@ -1053,24 +1076,6 @@ namespace cxxopts | ||
| 1053 | std::string m_group; | 1076 | std::string m_group; |
| 1054 | }; | 1077 | }; |
| 1055 | 1078 | ||
| 1056 | - // A helper function for setting required arguments | ||
| 1057 | - inline | ||
| 1058 | - void | ||
| 1059 | - check_required | ||
| 1060 | - ( | ||
| 1061 | - const Options& options, | ||
| 1062 | - const std::vector<std::string>& required | ||
| 1063 | - ) | ||
| 1064 | - { | ||
| 1065 | - for (auto& r : required) | ||
| 1066 | - { | ||
| 1067 | - if (options.count(r) == 0) | ||
| 1068 | - { | ||
| 1069 | - throw option_required_exception(r); | ||
| 1070 | - } | ||
| 1071 | - } | ||
| 1072 | - } | ||
| 1073 | - | ||
| 1074 | namespace | 1079 | namespace |
| 1075 | { | 1080 | { |
| 1076 | constexpr int OPTION_LONGEST = 30; | 1081 | constexpr int OPTION_LONGEST = 30; |
| @@ -1188,6 +1193,18 @@ namespace cxxopts | @@ -1188,6 +1193,18 @@ namespace cxxopts | ||
| 1188 | } | 1193 | } |
| 1189 | } | 1194 | } |
| 1190 | 1195 | ||
| 1196 | +template <typename Iterator> | ||
| 1197 | +ParseResult::ParseResult(Iterator begin, Iterator end, | ||
| 1198 | + std::vector<std::string> positional, | ||
| 1199 | + int& argc, char**& argv | ||
| 1200 | +) | ||
| 1201 | +: m_options(begin, end) | ||
| 1202 | +, m_positional(std::move(positional)) | ||
| 1203 | +, m_next_positional(m_positional.begin()) | ||
| 1204 | +{ | ||
| 1205 | + parse(argc, argv); | ||
| 1206 | +} | ||
| 1207 | + | ||
| 1191 | inline | 1208 | inline |
| 1192 | OptionAdder | 1209 | OptionAdder |
| 1193 | Options::add_options(std::string group) | 1210 | Options::add_options(std::string group) |
| @@ -1255,7 +1272,7 @@ OptionAdder::operator() | @@ -1255,7 +1272,7 @@ OptionAdder::operator() | ||
| 1255 | 1272 | ||
| 1256 | inline | 1273 | inline |
| 1257 | void | 1274 | void |
| 1258 | -Options::parse_option | 1275 | +ParseResult::parse_option |
| 1259 | ( | 1276 | ( |
| 1260 | std::shared_ptr<OptionDetails> value, | 1277 | std::shared_ptr<OptionDetails> value, |
| 1261 | const std::string& /*name*/, | 1278 | const std::string& /*name*/, |
| @@ -1267,7 +1284,7 @@ Options::parse_option | @@ -1267,7 +1284,7 @@ Options::parse_option | ||
| 1267 | 1284 | ||
| 1268 | inline | 1285 | inline |
| 1269 | void | 1286 | void |
| 1270 | -Options::checked_parse_arg | 1287 | +ParseResult::checked_parse_arg |
| 1271 | ( | 1288 | ( |
| 1272 | int argc, | 1289 | int argc, |
| 1273 | char* argv[], | 1290 | char* argv[], |
| @@ -1303,7 +1320,7 @@ Options::checked_parse_arg | @@ -1303,7 +1320,7 @@ Options::checked_parse_arg | ||
| 1303 | 1320 | ||
| 1304 | inline | 1321 | inline |
| 1305 | void | 1322 | void |
| 1306 | -Options::add_to_option(const std::string& option, const std::string& arg) | 1323 | +ParseResult::add_to_option(const std::string& option, const std::string& arg) |
| 1307 | { | 1324 | { |
| 1308 | auto iter = m_options.find(option); | 1325 | auto iter = m_options.find(option); |
| 1309 | 1326 | ||
| @@ -1317,7 +1334,7 @@ Options::add_to_option(const std::string& option, const std::string& arg) | @@ -1317,7 +1334,7 @@ Options::add_to_option(const std::string& option, const std::string& arg) | ||
| 1317 | 1334 | ||
| 1318 | inline | 1335 | inline |
| 1319 | bool | 1336 | bool |
| 1320 | -Options::consume_positional(std::string a) | 1337 | +ParseResult::consume_positional(std::string a) |
| 1321 | { | 1338 | { |
| 1322 | while (m_next_positional != m_positional.end()) | 1339 | while (m_next_positional != m_positional.end()) |
| 1323 | { | 1340 | { |
| @@ -1368,9 +1385,17 @@ Options::parse_positional(std::vector<std::string> options) | @@ -1368,9 +1385,17 @@ Options::parse_positional(std::vector<std::string> options) | ||
| 1368 | } | 1385 | } |
| 1369 | 1386 | ||
| 1370 | inline | 1387 | inline |
| 1371 | -void | 1388 | +ParseResult |
| 1372 | Options::parse(int& argc, char**& argv) | 1389 | Options::parse(int& argc, char**& argv) |
| 1373 | { | 1390 | { |
| 1391 | + ParseResult result(m_options.begin(), m_options.end(), m_positional, argc, argv); | ||
| 1392 | + return result; | ||
| 1393 | +} | ||
| 1394 | + | ||
| 1395 | +inline | ||
| 1396 | +void | ||
| 1397 | +ParseResult::parse(int& argc, char**& argv) | ||
| 1398 | +{ | ||
| 1374 | int current = 1; | 1399 | int current = 1; |
| 1375 | 1400 | ||
| 1376 | int nextKeep = 1; | 1401 | int nextKeep = 1; |
src/example.cpp
| @@ -63,9 +63,9 @@ int main(int argc, char* argv[]) | @@ -63,9 +63,9 @@ int main(int argc, char* argv[]) | ||
| 63 | 63 | ||
| 64 | options.parse_positional({"input", "output", "positional"}); | 64 | options.parse_positional({"input", "output", "positional"}); |
| 65 | 65 | ||
| 66 | - options.parse(argc, argv); | 66 | + auto result = options.parse(argc, argv); |
| 67 | 67 | ||
| 68 | - if (options.count("help")) | 68 | + if (result.count("help")) |
| 69 | { | 69 | { |
| 70 | std::cout << options.help({"", "Group"}) << std::endl; | 70 | std::cout << options.help({"", "Group"}) << std::endl; |
| 71 | exit(0); | 71 | exit(0); |
| @@ -73,18 +73,18 @@ int main(int argc, char* argv[]) | @@ -73,18 +73,18 @@ int main(int argc, char* argv[]) | ||
| 73 | 73 | ||
| 74 | if (apple) | 74 | if (apple) |
| 75 | { | 75 | { |
| 76 | - std::cout << "Saw option ‘a’ " << options.count("a") << " times " << | 76 | + std::cout << "Saw option ‘a’ " << result.count("a") << " times " << |
| 77 | std::endl; | 77 | std::endl; |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | - if (options.count("b")) | 80 | + if (result.count("b")) |
| 81 | { | 81 | { |
| 82 | std::cout << "Saw option ‘b’" << std::endl; | 82 | std::cout << "Saw option ‘b’" << std::endl; |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | - if (options.count("f")) | 85 | + if (result.count("f")) |
| 86 | { | 86 | { |
| 87 | - auto& ff = options["f"].as<std::vector<std::string>>(); | 87 | + auto& ff = result["f"].as<std::vector<std::string>>(); |
| 88 | std::cout << "Files" << std::endl; | 88 | std::cout << "Files" << std::endl; |
| 89 | for (const auto& f : ff) | 89 | for (const auto& f : ff) |
| 90 | { | 90 | { |
| @@ -92,36 +92,36 @@ int main(int argc, char* argv[]) | @@ -92,36 +92,36 @@ int main(int argc, char* argv[]) | ||
| 92 | } | 92 | } |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | - if (options.count("input")) | 95 | + if (result.count("input")) |
| 96 | { | 96 | { |
| 97 | - std::cout << "Input = " << options["input"].as<std::string>() | 97 | + std::cout << "Input = " << result["input"].as<std::string>() |
| 98 | << std::endl; | 98 | << std::endl; |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | - if (options.count("output")) | 101 | + if (result.count("output")) |
| 102 | { | 102 | { |
| 103 | - std::cout << "Output = " << options["output"].as<std::string>() | 103 | + std::cout << "Output = " << result["output"].as<std::string>() |
| 104 | << std::endl; | 104 | << std::endl; |
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | - if (options.count("positional")) | 107 | + if (result.count("positional")) |
| 108 | { | 108 | { |
| 109 | std::cout << "Positional = {"; | 109 | std::cout << "Positional = {"; |
| 110 | - auto& v = options["positional"].as<std::vector<std::string>>(); | 110 | + auto& v = result["positional"].as<std::vector<std::string>>(); |
| 111 | for (const auto& s : v) { | 111 | for (const auto& s : v) { |
| 112 | std::cout << s << ", "; | 112 | std::cout << s << ", "; |
| 113 | } | 113 | } |
| 114 | std::cout << "}" << std::endl; | 114 | std::cout << "}" << std::endl; |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | - if (options.count("int")) | 117 | + if (result.count("int")) |
| 118 | { | 118 | { |
| 119 | - std::cout << "int = " << options["int"].as<int>() << std::endl; | 119 | + std::cout << "int = " << result["int"].as<int>() << std::endl; |
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | - if (options.count("float")) | 122 | + if (result.count("float")) |
| 123 | { | 123 | { |
| 124 | - std::cout << "float = " << options["float"].as<float>() << std::endl; | 124 | + std::cout << "float = " << result["float"].as<float>() << std::endl; |
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | std::cout << "Arguments remain = " << argc << std::endl; | 127 | std::cout << "Arguments remain = " << argc << std::endl; |
test/options.cpp
| @@ -71,17 +71,17 @@ TEST_CASE("Basic options", "[options]") | @@ -71,17 +71,17 @@ TEST_CASE("Basic options", "[options]") | ||
| 71 | char** actual_argv = argv.argv(); | 71 | char** actual_argv = argv.argv(); |
| 72 | auto argc = argv.argc(); | 72 | auto argc = argv.argc(); |
| 73 | 73 | ||
| 74 | - options.parse(argc, actual_argv); | ||
| 75 | - | ||
| 76 | - CHECK(options.count("long") == 1); | ||
| 77 | - CHECK(options.count("s") == 1); | ||
| 78 | - CHECK(options.count("value") == 1); | ||
| 79 | - CHECK(options.count("a") == 1); | ||
| 80 | - CHECK(options["value"].as<std::string>() == "value"); | ||
| 81 | - CHECK(options["a"].as<std::string>() == "b"); | ||
| 82 | - CHECK(options.count("6") == 1); | ||
| 83 | - CHECK(options.count("p") == 2); | ||
| 84 | - CHECK(options.count("space") == 2); | 74 | + auto result = options.parse(argc, actual_argv); |
| 75 | + | ||
| 76 | + CHECK(result.count("long") == 1); | ||
| 77 | + CHECK(result.count("s") == 1); | ||
| 78 | + CHECK(result.count("value") == 1); | ||
| 79 | + CHECK(result.count("a") == 1); | ||
| 80 | + CHECK(result["value"].as<std::string>() == "value"); | ||
| 81 | + CHECK(result["a"].as<std::string>() == "b"); | ||
| 82 | + CHECK(result.count("6") == 1); | ||
| 83 | + CHECK(result.count("p") == 2); | ||
| 84 | + CHECK(result.count("space") == 2); | ||
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | TEST_CASE("Short options", "[options]") | 87 | TEST_CASE("Short options", "[options]") |
| @@ -96,36 +96,15 @@ TEST_CASE("Short options", "[options]") | @@ -96,36 +96,15 @@ TEST_CASE("Short options", "[options]") | ||
| 96 | auto actual_argv = argv.argv(); | 96 | auto actual_argv = argv.argv(); |
| 97 | auto argc = argv.argc(); | 97 | auto argc = argv.argc(); |
| 98 | 98 | ||
| 99 | - options.parse(argc, actual_argv); | 99 | + auto result = options.parse(argc, actual_argv); |
| 100 | 100 | ||
| 101 | - CHECK(options.count("a") == 1); | ||
| 102 | - CHECK(options["a"].as<std::string>() == "value"); | 101 | + CHECK(result.count("a") == 1); |
| 102 | + CHECK(result["a"].as<std::string>() == "value"); | ||
| 103 | 103 | ||
| 104 | REQUIRE_THROWS_AS(options.add_options()("", "nothing option"), | 104 | REQUIRE_THROWS_AS(options.add_options()("", "nothing option"), |
| 105 | cxxopts::invalid_option_format_error); | 105 | cxxopts::invalid_option_format_error); |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | -TEST_CASE("Required arguments", "[options]") | ||
| 109 | -{ | ||
| 110 | - cxxopts::Options options("required", " - test required options"); | ||
| 111 | - options.add_options() | ||
| 112 | - ("one", "one option") | ||
| 113 | - ("two", "second option") | ||
| 114 | - ; | ||
| 115 | - | ||
| 116 | - Argv argv({ | ||
| 117 | - "required", | ||
| 118 | - "--one" | ||
| 119 | - }); | ||
| 120 | - | ||
| 121 | - auto aargv = argv.argv(); | ||
| 122 | - auto argc = argv.argc(); | ||
| 123 | - | ||
| 124 | - options.parse(argc, aargv); | ||
| 125 | - REQUIRE_THROWS_AS(cxxopts::check_required(options, {"two"}), | ||
| 126 | - cxxopts::option_required_exception); | ||
| 127 | -} | ||
| 128 | - | ||
| 129 | TEST_CASE("No positional", "[positional]") | 108 | TEST_CASE("No positional", "[positional]") |
| 130 | { | 109 | { |
| 131 | cxxopts::Options options("test_no_positional", | 110 | cxxopts::Options options("test_no_positional", |
| @@ -135,7 +114,7 @@ TEST_CASE("No positional", "[positional]") | @@ -135,7 +114,7 @@ TEST_CASE("No positional", "[positional]") | ||
| 135 | 114 | ||
| 136 | char** argv = av.argv(); | 115 | char** argv = av.argv(); |
| 137 | auto argc = av.argc(); | 116 | auto argc = av.argc(); |
| 138 | - options.parse(argc, argv); | 117 | + auto result = options.parse(argc, argv); |
| 139 | 118 | ||
| 140 | REQUIRE(argc == 4); | 119 | REQUIRE(argc == 4); |
| 141 | CHECK(strcmp(argv[1], "a") == 0); | 120 | CHECK(strcmp(argv[1], "a") == 0); |
| @@ -158,7 +137,7 @@ TEST_CASE("All positional", "[positional]") | @@ -158,7 +137,7 @@ TEST_CASE("All positional", "[positional]") | ||
| 158 | 137 | ||
| 159 | options.parse_positional("positional"); | 138 | options.parse_positional("positional"); |
| 160 | 139 | ||
| 161 | - options.parse(argc, argv); | 140 | + auto result = options.parse(argc, argv); |
| 162 | 141 | ||
| 163 | REQUIRE(argc == 1); | 142 | REQUIRE(argc == 1); |
| 164 | REQUIRE(positional.size() == 3); | 143 | REQUIRE(positional.size() == 3); |
| @@ -186,14 +165,14 @@ TEST_CASE("Some positional explicit", "[positional]") | @@ -186,14 +165,14 @@ TEST_CASE("Some positional explicit", "[positional]") | ||
| 186 | char** argv = av.argv(); | 165 | char** argv = av.argv(); |
| 187 | auto argc = av.argc(); | 166 | auto argc = av.argc(); |
| 188 | 167 | ||
| 189 | - options.parse(argc, argv); | 168 | + auto result = options.parse(argc, argv); |
| 190 | 169 | ||
| 191 | CHECK(argc == 1); | 170 | CHECK(argc == 1); |
| 192 | - CHECK(options.count("output")); | ||
| 193 | - CHECK(options["input"].as<std::string>() == "b"); | ||
| 194 | - CHECK(options["output"].as<std::string>() == "a"); | 171 | + CHECK(result.count("output")); |
| 172 | + CHECK(result["input"].as<std::string>() == "b"); | ||
| 173 | + CHECK(result["output"].as<std::string>() == "a"); | ||
| 195 | 174 | ||
| 196 | - auto& positional = options["positional"].as<std::vector<std::string>>(); | 175 | + auto& positional = result["positional"].as<std::vector<std::string>>(); |
| 197 | 176 | ||
| 198 | REQUIRE(positional.size() == 2); | 177 | REQUIRE(positional.size() == 2); |
| 199 | CHECK(positional[0] == "c"); | 178 | CHECK(positional[0] == "c"); |
| @@ -234,10 +213,10 @@ TEST_CASE("Empty with implicit value", "[implicit]") | @@ -234,10 +213,10 @@ TEST_CASE("Empty with implicit value", "[implicit]") | ||
| 234 | char** argv = av.argv(); | 213 | char** argv = av.argv(); |
| 235 | auto argc = av.argc(); | 214 | auto argc = av.argc(); |
| 236 | 215 | ||
| 237 | - options.parse(argc, argv); | 216 | + auto result = options.parse(argc, argv); |
| 238 | 217 | ||
| 239 | - REQUIRE(options.count("implicit") == 1); | ||
| 240 | - REQUIRE(options["implicit"].as<std::string>() == ""); | 218 | + REQUIRE(result.count("implicit") == 1); |
| 219 | + REQUIRE(result["implicit"].as<std::string>() == ""); | ||
| 241 | } | 220 | } |
| 242 | 221 | ||
| 243 | TEST_CASE("Integers", "[options]") | 222 | TEST_CASE("Integers", "[options]") |
| @@ -252,11 +231,11 @@ TEST_CASE("Integers", "[options]") | @@ -252,11 +231,11 @@ TEST_CASE("Integers", "[options]") | ||
| 252 | auto argc = av.argc(); | 231 | auto argc = av.argc(); |
| 253 | 232 | ||
| 254 | options.parse_positional("positional"); | 233 | options.parse_positional("positional"); |
| 255 | - options.parse(argc, argv); | 234 | + auto result = options.parse(argc, argv); |
| 256 | 235 | ||
| 257 | - REQUIRE(options.count("positional") == 6); | 236 | + REQUIRE(result.count("positional") == 6); |
| 258 | 237 | ||
| 259 | - auto& positional = options["positional"].as<std::vector<int>>(); | 238 | + auto& positional = result["positional"].as<std::vector<int>>(); |
| 260 | CHECK(positional[0] == 5); | 239 | CHECK(positional[0] == 5); |
| 261 | CHECK(positional[1] == 6); | 240 | CHECK(positional[1] == 6); |
| 262 | CHECK(positional[2] == -6); | 241 | CHECK(positional[2] == -6); |
| @@ -294,11 +273,11 @@ TEST_CASE("Integer bounds", "[integer]") | @@ -294,11 +273,11 @@ TEST_CASE("Integer bounds", "[integer]") | ||
| 294 | auto argc = av.argc(); | 273 | auto argc = av.argc(); |
| 295 | 274 | ||
| 296 | options.parse_positional("positional"); | 275 | options.parse_positional("positional"); |
| 297 | - options.parse(argc, argv); | 276 | + auto result = options.parse(argc, argv); |
| 298 | 277 | ||
| 299 | - REQUIRE(options.count("positional") == 5); | 278 | + REQUIRE(result.count("positional") == 5); |
| 300 | 279 | ||
| 301 | - auto& positional = options["positional"].as<std::vector<int8_t>>(); | 280 | + auto& positional = result["positional"].as<std::vector<int8_t>>(); |
| 302 | CHECK(positional[0] == 127); | 281 | CHECK(positional[0] == 127); |
| 303 | CHECK(positional[1] == -128); | 282 | CHECK(positional[1] == -128); |
| 304 | CHECK(positional[2] == 0x7f); | 283 | CHECK(positional[2] == 0x7f); |
| @@ -350,14 +329,14 @@ TEST_CASE("Floats", "[options]") | @@ -350,14 +329,14 @@ TEST_CASE("Floats", "[options]") | ||
| 350 | auto argc = av.argc(); | 329 | auto argc = av.argc(); |
| 351 | 330 | ||
| 352 | options.parse_positional("positional"); | 331 | options.parse_positional("positional"); |
| 353 | - options.parse(argc, argv); | 332 | + auto result = options.parse(argc, argv); |
| 354 | 333 | ||
| 355 | - REQUIRE(options.count("double") == 1); | ||
| 356 | - REQUIRE(options.count("positional") == 4); | 334 | + REQUIRE(result.count("double") == 1); |
| 335 | + REQUIRE(result.count("positional") == 4); | ||
| 357 | 336 | ||
| 358 | - CHECK(options["double"].as<double>() == 0.5); | 337 | + CHECK(result["double"].as<double>() == 0.5); |
| 359 | 338 | ||
| 360 | - auto& positional = options["positional"].as<std::vector<float>>(); | 339 | + auto& positional = result["positional"].as<std::vector<float>>(); |
| 361 | CHECK(positional[0] == 4); | 340 | CHECK(positional[0] == 4); |
| 362 | CHECK(positional[1] == -4); | 341 | CHECK(positional[1] == -4); |
| 363 | CHECK(positional[2] == 1.5e6); | 342 | CHECK(positional[2] == 1.5e6); |