Commit 5b714bbfe438b0450965220304cba854d0cb972a
Committed by
GitHub
Merge pull request #15 from CLIUtils/basic-enum
Adding enum support
Showing
6 changed files
with
263 additions
and
16 deletions
CHANGELOG.md
| 1 | ## Version 1.1 (in progress) | 1 | ## Version 1.1 (in progress) |
| 2 | + | ||
| 3 | +* Added simple support for enumerations, allow non-printable objects [#12](https://github.com/CLIUtils/CLI11/issues/12) | ||
| 2 | * Added `app.parse_order()` with original parse order ([#13](https://github.com/CLIUtils/CLI11/issues/13), [#16](https://github.com/CLIUtils/CLI11/pull/16)) | 4 | * Added `app.parse_order()` with original parse order ([#13](https://github.com/CLIUtils/CLI11/issues/13), [#16](https://github.com/CLIUtils/CLI11/pull/16)) |
| 3 | * Added `prefix_command()`, which is like `allow_extras` but instantly stops and returns. ([#8](https://github.com/CLIUtils/CLI11/issues/8), [#17](https://github.com/CLIUtils/CLI11/pull/17)) | 5 | * Added `prefix_command()`, which is like `allow_extras` but instantly stops and returns. ([#8](https://github.com/CLIUtils/CLI11/issues/8), [#17](https://github.com/CLIUtils/CLI11/pull/17)) |
| 4 | * Removed Windows error ([#10](https://github.com/CLIUtils/CLI11/issues/10), [#20](https://github.com/CLIUtils/CLI11/pull/20)) | 6 | * Removed Windows error ([#10](https://github.com/CLIUtils/CLI11/issues/10), [#20](https://github.com/CLIUtils/CLI11/pull/20)) |
| 5 | * Some improvements to CMake, detect Python and no dependencies on Python 2 (like Python 3) ([#18](https://github.com/CLIUtils/CLI11/issues/18), [#21](https://github.com/CLIUtils/CLI11/pull/21)) | 7 | * Some improvements to CMake, detect Python and no dependencies on Python 2 (like Python 3) ([#18](https://github.com/CLIUtils/CLI11/issues/18), [#21](https://github.com/CLIUtils/CLI11/pull/21)) |
| 6 | 8 | ||
| 7 | - | ||
| 8 | ## Version 1.0 | 9 | ## Version 1.0 |
| 9 | * Cleanup using `clang-tidy` and `clang-format` | 10 | * Cleanup using `clang-tidy` and `clang-format` |
| 10 | * Small improvements to Timers, easier to subclass Error | 11 | * Small improvements to Timers, easier to subclass Error |
examples/CMakeLists.txt
| @@ -19,3 +19,4 @@ add_cli_exe(subcommands subcommands.cpp) | @@ -19,3 +19,4 @@ add_cli_exe(subcommands subcommands.cpp) | ||
| 19 | add_cli_exe(groups groups.cpp) | 19 | add_cli_exe(groups groups.cpp) |
| 20 | add_cli_exe(inter_argument_order inter_argument_order.cpp) | 20 | add_cli_exe(inter_argument_order inter_argument_order.cpp) |
| 21 | add_cli_exe(prefix_command prefix_command.cpp) | 21 | add_cli_exe(prefix_command prefix_command.cpp) |
| 22 | +add_cli_exe(enum enum.cpp) |
examples/enum.cpp
0 → 100644
| 1 | +#include <CLI/CLI.hpp> | ||
| 2 | + | ||
| 3 | +enum Level : std::int32_t { | ||
| 4 | + High, | ||
| 5 | + Medium, | ||
| 6 | + Low | ||
| 7 | +}; | ||
| 8 | + | ||
| 9 | +int main(int argc, char** argv) { | ||
| 10 | + CLI::App app; | ||
| 11 | + | ||
| 12 | + Level level; | ||
| 13 | + app.add_set("-l,--level", level, {High, Medium, Low}, "Level settings") | ||
| 14 | + ->set_type_name("enum/Level in {High=0, Medium=1, Low=2}"); | ||
| 15 | + | ||
| 16 | + try { | ||
| 17 | + app.parse(argc, argv); | ||
| 18 | + } catch (CLI::Error const& e) { | ||
| 19 | + app.exit(e); | ||
| 20 | + } | ||
| 21 | + return 0; | ||
| 22 | +} | ||
| 23 | + |
include/CLI/App.hpp
| @@ -225,13 +225,14 @@ class App { | @@ -225,13 +225,14 @@ class App { | ||
| 225 | } else | 225 | } else |
| 226 | throw OptionAlreadyAdded(myopt.get_name()); | 226 | throw OptionAlreadyAdded(myopt.get_name()); |
| 227 | } | 227 | } |
| 228 | + | ||
| 229 | + | ||
| 228 | 230 | ||
| 229 | - /// Add option for non-vectors | 231 | + /// Add option for non-vectors (duplicate copy needed without defaulted to avoid `iostream << value`) |
| 230 | template <typename T, enable_if_t<!is_vector<T>::value, detail::enabler> = detail::dummy> | 232 | template <typename T, enable_if_t<!is_vector<T>::value, detail::enabler> = detail::dummy> |
| 231 | Option *add_option(std::string name, | 233 | Option *add_option(std::string name, |
| 232 | T &variable, ///< The variable to set | 234 | T &variable, ///< The variable to set |
| 233 | - std::string description = "", | ||
| 234 | - bool defaulted = false) { | 235 | + std::string description = "") { |
| 235 | 236 | ||
| 236 | CLI::callback_t fun = [&variable](CLI::results_t res) { | 237 | CLI::callback_t fun = [&variable](CLI::results_t res) { |
| 237 | if(res.size() != 1) | 238 | if(res.size() != 1) |
| @@ -239,6 +240,24 @@ class App { | @@ -239,6 +240,24 @@ class App { | ||
| 239 | return detail::lexical_cast(res[0], variable); | 240 | return detail::lexical_cast(res[0], variable); |
| 240 | }; | 241 | }; |
| 241 | 242 | ||
| 243 | + Option *opt = add_option(name, fun, description, false); | ||
| 244 | + opt->set_custom_option(detail::type_name<T>()); | ||
| 245 | + return opt; | ||
| 246 | + } | ||
| 247 | + | ||
| 248 | + /// Add option for non-vectors with a default print | ||
| 249 | + template <typename T, enable_if_t<!is_vector<T>::value, detail::enabler> = detail::dummy> | ||
| 250 | + Option *add_option(std::string name, | ||
| 251 | + T &variable, ///< The variable to set | ||
| 252 | + std::string description, | ||
| 253 | + bool defaulted) { | ||
| 254 | + | ||
| 255 | + CLI::callback_t fun = [&variable](CLI::results_t res) { | ||
| 256 | + if(res.size() != 1) | ||
| 257 | + return false; | ||
| 258 | + return detail::lexical_cast(res[0], variable); | ||
| 259 | + }; | ||
| 260 | + | ||
| 242 | Option *opt = add_option(name, fun, description, defaulted); | 261 | Option *opt = add_option(name, fun, description, defaulted); |
| 243 | opt->set_custom_option(detail::type_name<T>()); | 262 | opt->set_custom_option(detail::type_name<T>()); |
| 244 | if(defaulted) { | 263 | if(defaulted) { |
| @@ -248,13 +267,34 @@ class App { | @@ -248,13 +267,34 @@ class App { | ||
| 248 | } | 267 | } |
| 249 | return opt; | 268 | return opt; |
| 250 | } | 269 | } |
| 251 | - | 270 | + |
| 271 | + /// Add option for vectors (no default) | ||
| 272 | + template <typename T> | ||
| 273 | + Option *add_option(std::string name, | ||
| 274 | + std::vector<T> &variable, ///< The variable vector to set | ||
| 275 | + std::string description = "") { | ||
| 276 | + | ||
| 277 | + CLI::callback_t fun = [&variable](CLI::results_t res) { | ||
| 278 | + bool retval = true; | ||
| 279 | + variable.clear(); | ||
| 280 | + for(const auto &a : res) { | ||
| 281 | + variable.emplace_back(); | ||
| 282 | + retval &= detail::lexical_cast(a, variable.back()); | ||
| 283 | + } | ||
| 284 | + return (!variable.empty()) && retval; | ||
| 285 | + }; | ||
| 286 | + | ||
| 287 | + Option *opt = add_option(name, fun, description, false); | ||
| 288 | + opt->set_custom_option(detail::type_name<T>(), -1, true); | ||
| 289 | + return opt; | ||
| 290 | + } | ||
| 291 | + | ||
| 252 | /// Add option for vectors | 292 | /// Add option for vectors |
| 253 | template <typename T> | 293 | template <typename T> |
| 254 | Option *add_option(std::string name, | 294 | Option *add_option(std::string name, |
| 255 | std::vector<T> &variable, ///< The variable vector to set | 295 | std::vector<T> &variable, ///< The variable vector to set |
| 256 | - std::string description = "", | ||
| 257 | - bool defaulted = false) { | 296 | + std::string description, |
| 297 | + bool defaulted) { | ||
| 258 | 298 | ||
| 259 | CLI::callback_t fun = [&variable](CLI::results_t res) { | 299 | CLI::callback_t fun = [&variable](CLI::results_t res) { |
| 260 | bool retval = true; | 300 | bool retval = true; |
| @@ -323,13 +363,12 @@ class App { | @@ -323,13 +363,12 @@ class App { | ||
| 323 | return opt; | 363 | return opt; |
| 324 | } | 364 | } |
| 325 | 365 | ||
| 326 | - /// Add set of options | 366 | + /// Add set of options (No default) |
| 327 | template <typename T> | 367 | template <typename T> |
| 328 | Option *add_set(std::string name, | 368 | Option *add_set(std::string name, |
| 329 | T &member, ///< The selected member of the set | 369 | T &member, ///< The selected member of the set |
| 330 | std::set<T> options, ///< The set of posibilities | 370 | std::set<T> options, ///< The set of posibilities |
| 331 | - std::string description = "", | ||
| 332 | - bool defaulted = false) { | 371 | + std::string description = "") { |
| 333 | 372 | ||
| 334 | CLI::callback_t fun = [&member, options](CLI::results_t res) { | 373 | CLI::callback_t fun = [&member, options](CLI::results_t res) { |
| 335 | if(res.size() != 1) { | 374 | if(res.size() != 1) { |
| @@ -341,6 +380,31 @@ class App { | @@ -341,6 +380,31 @@ class App { | ||
| 341 | return std::find(std::begin(options), std::end(options), member) != std::end(options); | 380 | return std::find(std::begin(options), std::end(options), member) != std::end(options); |
| 342 | }; | 381 | }; |
| 343 | 382 | ||
| 383 | + Option *opt = add_option(name, fun, description, false); | ||
| 384 | + std::string typeval = detail::type_name<T>(); | ||
| 385 | + typeval += " in {" + detail::join(options) + "}"; | ||
| 386 | + opt->set_custom_option(typeval); | ||
| 387 | + return opt; | ||
| 388 | + } | ||
| 389 | + | ||
| 390 | + /// Add set of options | ||
| 391 | + template <typename T> | ||
| 392 | + Option *add_set(std::string name, | ||
| 393 | + T &member, ///< The selected member of the set | ||
| 394 | + std::set<T> options, ///< The set of posibilities | ||
| 395 | + std::string description, | ||
| 396 | + bool defaulted) { | ||
| 397 | + | ||
| 398 | + CLI::callback_t fun = [&member, options](CLI::results_t res) { | ||
| 399 | + if(res.size() != 1) { | ||
| 400 | + return false; | ||
| 401 | + } | ||
| 402 | + bool retval = detail::lexical_cast(res[0], member); | ||
| 403 | + if(!retval) | ||
| 404 | + return false; | ||
| 405 | + return std::find(std::begin(options), std::end(options), member) != std::end(options); | ||
| 406 | + }; | ||
| 407 | + | ||
| 344 | Option *opt = add_option(name, fun, description, defaulted); | 408 | Option *opt = add_option(name, fun, description, defaulted); |
| 345 | std::string typeval = detail::type_name<T>(); | 409 | std::string typeval = detail::type_name<T>(); |
| 346 | typeval += " in {" + detail::join(options) + "}"; | 410 | typeval += " in {" + detail::join(options) + "}"; |
| @@ -353,12 +417,11 @@ class App { | @@ -353,12 +417,11 @@ class App { | ||
| 353 | return opt; | 417 | return opt; |
| 354 | } | 418 | } |
| 355 | 419 | ||
| 356 | - /// Add set of options, string only, ignore case | 420 | + /// Add set of options, string only, ignore case (no default) |
| 357 | Option *add_set_ignore_case(std::string name, | 421 | Option *add_set_ignore_case(std::string name, |
| 358 | std::string &member, ///< The selected member of the set | 422 | std::string &member, ///< The selected member of the set |
| 359 | std::set<std::string> options, ///< The set of posibilities | 423 | std::set<std::string> options, ///< The set of posibilities |
| 360 | - std::string description = "", | ||
| 361 | - bool defaulted = false) { | 424 | + std::string description = "") { |
| 362 | 425 | ||
| 363 | CLI::callback_t fun = [&member, options](CLI::results_t res) { | 426 | CLI::callback_t fun = [&member, options](CLI::results_t res) { |
| 364 | if(res.size() != 1) { | 427 | if(res.size() != 1) { |
| @@ -376,6 +439,37 @@ class App { | @@ -376,6 +439,37 @@ class App { | ||
| 376 | } | 439 | } |
| 377 | }; | 440 | }; |
| 378 | 441 | ||
| 442 | + Option *opt = add_option(name, fun, description, false); | ||
| 443 | + std::string typeval = detail::type_name<std::string>(); | ||
| 444 | + typeval += " in {" + detail::join(options) + "}"; | ||
| 445 | + opt->set_custom_option(typeval); | ||
| 446 | + | ||
| 447 | + return opt; | ||
| 448 | + } | ||
| 449 | + | ||
| 450 | + /// Add set of options, string only, ignore case | ||
| 451 | + Option *add_set_ignore_case(std::string name, | ||
| 452 | + std::string &member, ///< The selected member of the set | ||
| 453 | + std::set<std::string> options, ///< The set of posibilities | ||
| 454 | + std::string description, | ||
| 455 | + bool defaulted) { | ||
| 456 | + | ||
| 457 | + CLI::callback_t fun = [&member, options](CLI::results_t res) { | ||
| 458 | + if(res.size() != 1) { | ||
| 459 | + return false; | ||
| 460 | + } | ||
| 461 | + member = detail::to_lower(res[0]); | ||
| 462 | + auto iter = std::find_if(std::begin(options), std::end(options), [&member](std::string val) { | ||
| 463 | + return detail::to_lower(val) == member; | ||
| 464 | + }); | ||
| 465 | + if(iter == std::end(options)) | ||
| 466 | + return false; | ||
| 467 | + else { | ||
| 468 | + member = *iter; | ||
| 469 | + return true; | ||
| 470 | + } | ||
| 471 | + }; | ||
| 472 | + | ||
| 379 | Option *opt = add_option(name, fun, description, defaulted); | 473 | Option *opt = add_option(name, fun, description, defaulted); |
| 380 | std::string typeval = detail::type_name<std::string>(); | 474 | std::string typeval = detail::type_name<std::string>(); |
| 381 | typeval += " in {" + detail::join(options) + "}"; | 475 | typeval += " in {" + detail::join(options) + "}"; |
include/CLI/TypeTools.hpp
| @@ -74,8 +74,10 @@ constexpr const char *type_name() { | @@ -74,8 +74,10 @@ constexpr const char *type_name() { | ||
| 74 | 74 | ||
| 75 | // Lexical cast | 75 | // Lexical cast |
| 76 | 76 | ||
| 77 | -/// Integers | ||
| 78 | -template <typename T, enable_if_t<std::is_integral<T>::value, detail::enabler> = detail::dummy> | 77 | +/// Integers / enums |
| 78 | +template <typename T, enable_if_t<std::is_integral<T>::value | ||
| 79 | + || std::is_enum<T>::value | ||
| 80 | + , detail::enabler> = detail::dummy> | ||
| 79 | bool lexical_cast(std::string input, T &output) { | 81 | bool lexical_cast(std::string input, T &output) { |
| 80 | try { | 82 | try { |
| 81 | output = static_cast<T>(std::stoll(input)); | 83 | output = static_cast<T>(std::stoll(input)); |
| @@ -103,7 +105,9 @@ bool lexical_cast(std::string input, T &output) { | @@ -103,7 +105,9 @@ bool lexical_cast(std::string input, T &output) { | ||
| 103 | /// String and similar | 105 | /// String and similar |
| 104 | template < | 106 | template < |
| 105 | typename T, | 107 | typename T, |
| 106 | - enable_if_t<!std::is_floating_point<T>::value && !std::is_integral<T>::value, detail::enabler> = detail::dummy> | 108 | + enable_if_t<!std::is_floating_point<T>::value |
| 109 | + && !std::is_integral<T>::value | ||
| 110 | + && !std::is_enum<T>::value, detail::enabler> = detail::dummy> | ||
| 107 | bool lexical_cast(std::string input, T &output) { | 111 | bool lexical_cast(std::string input, T &output) { |
| 108 | output = input; | 112 | output = input; |
| 109 | return true; | 113 | return true; |
tests/AppTest.cpp
| @@ -203,6 +203,35 @@ TEST_F(TApp, DefaultOpts) { | @@ -203,6 +203,35 @@ TEST_F(TApp, DefaultOpts) { | ||
| 203 | EXPECT_EQ("9", s); | 203 | EXPECT_EQ("9", s); |
| 204 | } | 204 | } |
| 205 | 205 | ||
| 206 | +TEST_F(TApp, EnumTest) { | ||
| 207 | + enum Level : std::int32_t { | ||
| 208 | + High, | ||
| 209 | + Medium, | ||
| 210 | + Low | ||
| 211 | + }; | ||
| 212 | + Level level = Level::Low; | ||
| 213 | + app.add_option("--level", level); | ||
| 214 | + | ||
| 215 | + args = {"--level", "1"}; | ||
| 216 | + run(); | ||
| 217 | + EXPECT_EQ(level, Level::Medium); | ||
| 218 | +} | ||
| 219 | + | ||
| 220 | +TEST_F(TApp, NewEnumTest) { | ||
| 221 | + enum class Level2 : std::int32_t { | ||
| 222 | + High, | ||
| 223 | + Medium, | ||
| 224 | + Low | ||
| 225 | + }; | ||
| 226 | + Level2 level = Level2::Low; | ||
| 227 | + app.add_option("--level", level); | ||
| 228 | + | ||
| 229 | + args = {"--level", "1"}; | ||
| 230 | + run(); | ||
| 231 | + EXPECT_EQ(level, Level2::Medium); | ||
| 232 | +} | ||
| 233 | + | ||
| 234 | + | ||
| 206 | TEST_F(TApp, RequiredFlags) { | 235 | TEST_F(TApp, RequiredFlags) { |
| 207 | app.add_flag("-a")->required(); | 236 | app.add_flag("-a")->required(); |
| 208 | app.add_flag("-b")->mandatory(); // Alternate term | 237 | app.add_flag("-b")->mandatory(); // Alternate term |
| @@ -391,6 +420,47 @@ TEST_F(TApp, InSet) { | @@ -391,6 +420,47 @@ TEST_F(TApp, InSet) { | ||
| 391 | EXPECT_THROW(run(), CLI::ConversionError); | 420 | EXPECT_THROW(run(), CLI::ConversionError); |
| 392 | } | 421 | } |
| 393 | 422 | ||
| 423 | +TEST_F(TApp, InSetWithDefault) { | ||
| 424 | + | ||
| 425 | + std::string choice = "one"; | ||
| 426 | + app.add_set("-q,--quick", choice, {"one", "two", "three"}, "", true); | ||
| 427 | + | ||
| 428 | + run(); | ||
| 429 | + EXPECT_EQ("one", choice); | ||
| 430 | + app.reset(); | ||
| 431 | + | ||
| 432 | + args = {"--quick", "two"}; | ||
| 433 | + | ||
| 434 | + run(); | ||
| 435 | + EXPECT_EQ("two", choice); | ||
| 436 | + | ||
| 437 | + app.reset(); | ||
| 438 | + | ||
| 439 | + args = {"--quick", "four"}; | ||
| 440 | + EXPECT_THROW(run(), CLI::ConversionError); | ||
| 441 | +} | ||
| 442 | + | ||
| 443 | + | ||
| 444 | +TEST_F(TApp, InCaselessSetWithDefault) { | ||
| 445 | + | ||
| 446 | + std::string choice = "one"; | ||
| 447 | + app.add_set_ignore_case("-q,--quick", choice, {"one", "two", "three"}, "", true); | ||
| 448 | + | ||
| 449 | + run(); | ||
| 450 | + EXPECT_EQ("one", choice); | ||
| 451 | + app.reset(); | ||
| 452 | + | ||
| 453 | + args = {"--quick", "tWo"}; | ||
| 454 | + | ||
| 455 | + run(); | ||
| 456 | + EXPECT_EQ("two", choice); | ||
| 457 | + | ||
| 458 | + app.reset(); | ||
| 459 | + | ||
| 460 | + args = {"--quick", "four"}; | ||
| 461 | + EXPECT_THROW(run(), CLI::ConversionError); | ||
| 462 | +} | ||
| 463 | + | ||
| 394 | TEST_F(TApp, InIntSet) { | 464 | TEST_F(TApp, InIntSet) { |
| 395 | 465 | ||
| 396 | int choice; | 466 | int choice; |
| @@ -462,6 +532,20 @@ TEST_F(TApp, VectorFixedString) { | @@ -462,6 +532,20 @@ TEST_F(TApp, VectorFixedString) { | ||
| 462 | EXPECT_EQ(answer, strvec); | 532 | EXPECT_EQ(answer, strvec); |
| 463 | } | 533 | } |
| 464 | 534 | ||
| 535 | + | ||
| 536 | +TEST_F(TApp, VectorDefaultedFixedString) { | ||
| 537 | + std::vector<std::string> strvec{"one"}; | ||
| 538 | + std::vector<std::string> answer{"mystring", "mystring2", "mystring3"}; | ||
| 539 | + | ||
| 540 | + CLI::Option *opt = app.add_option("-s,--string", strvec, "", true)->expected(3); | ||
| 541 | + EXPECT_EQ(3, opt->get_expected()); | ||
| 542 | + | ||
| 543 | + args = {"--string", "mystring", "mystring2", "mystring3"}; | ||
| 544 | + run(); | ||
| 545 | + EXPECT_EQ((size_t)3, app.count("--string")); | ||
| 546 | + EXPECT_EQ(answer, strvec); | ||
| 547 | +} | ||
| 548 | + | ||
| 465 | TEST_F(TApp, VectorUnlimString) { | 549 | TEST_F(TApp, VectorUnlimString) { |
| 466 | std::vector<std::string> strvec; | 550 | std::vector<std::string> strvec; |
| 467 | std::vector<std::string> answer{"mystring", "mystring2", "mystring3"}; | 551 | std::vector<std::string> answer{"mystring", "mystring2", "mystring3"}; |
| @@ -808,3 +892,43 @@ TEST_F(TApp, CheckSubcomFail) { | @@ -808,3 +892,43 @@ TEST_F(TApp, CheckSubcomFail) { | ||
| 808 | 892 | ||
| 809 | EXPECT_THROW(CLI::detail::AppFriend::parse_subcommand(&app, args), CLI::HorribleError); | 893 | EXPECT_THROW(CLI::detail::AppFriend::parse_subcommand(&app, args), CLI::HorribleError); |
| 810 | } | 894 | } |
| 895 | + | ||
| 896 | +// Added to test defaults on dual method | ||
| 897 | +TEST_F(TApp, OptionWithDefaults) { | ||
| 898 | + int someint=2; | ||
| 899 | + app.add_option("-a", someint, "", true); | ||
| 900 | + | ||
| 901 | + args = {"-a1", "-a2"}; | ||
| 902 | + | ||
| 903 | + EXPECT_THROW(run(), CLI::ConversionError); | ||
| 904 | +} | ||
| 905 | + | ||
| 906 | +// Added to test defaults on dual method | ||
| 907 | +TEST_F(TApp, SetWithDefaults) { | ||
| 908 | + int someint=2; | ||
| 909 | + app.add_set("-a", someint, {1,2,3,4}, "", true); | ||
| 910 | + | ||
| 911 | + args = {"-a1", "-a2"}; | ||
| 912 | + | ||
| 913 | + EXPECT_THROW(run(), CLI::ConversionError); | ||
| 914 | +} | ||
| 915 | + | ||
| 916 | +// Added to test defaults on dual method | ||
| 917 | +TEST_F(TApp, SetWithDefaultsConversion) { | ||
| 918 | + int someint=2; | ||
| 919 | + app.add_set("-a", someint, {1,2,3,4}, "", true); | ||
| 920 | + | ||
| 921 | + args = {"-a", "hi"}; | ||
| 922 | + | ||
| 923 | + EXPECT_THROW(run(), CLI::ConversionError); | ||
| 924 | +} | ||
| 925 | + | ||
| 926 | +// Added to test defaults on dual method | ||
| 927 | +TEST_F(TApp, SetWithDefaultsIC) { | ||
| 928 | + std::string someint="ho"; | ||
| 929 | + app.add_set_ignore_case("-a", someint, {"Hi", "Ho"}, "", true); | ||
| 930 | + | ||
| 931 | + args = {"-aHi", "-aHo"}; | ||
| 932 | + | ||
| 933 | + EXPECT_THROW(run(), CLI::ConversionError); | ||
| 934 | +} |