Commit 5f43f4cbfee5d92560ece7811a2a44c763f9fb73

Authored by Eyal Rozenberg
Committed by GitHub
1 parent 1b660d56

Fixes #245: Mention the option name when throwing on "no value" (#246)

* Fixes #245:

* Added a new exception type: `option_has_no_value_exception`; throwing it when an option has no value we can cast with `as()`, instead of an `std::domain_error`.
* The `OptionValue` type now holds a pointer to the long option name (in its corresponding key within ParseResults's `m_results` field.
include/cxxopts.hpp
... ... @@ -443,6 +443,18 @@ namespace cxxopts
443 443 }
444 444 };
445 445  
  446 + class option_has_no_value_exception : public OptionException
  447 + {
  448 + public:
  449 + explicit option_has_no_value_exception(const std::string& option)
  450 + : OptionException(
  451 + option.empty() ?
  452 + ("Option " + LQUOTE + option + RQUOTE + " has no value") :
  453 + "Option has no value")
  454 + {
  455 + }
  456 + };
  457 +
446 458 class argument_incorrect_type : public OptionParseException
447 459 {
448 460 public:
... ... @@ -1077,6 +1089,7 @@ namespace cxxopts
1077 1089 ensure_value(details);
1078 1090 ++m_count;
1079 1091 m_value->parse(text);
  1092 + m_long_name = &details->long_name();
1080 1093 }
1081 1094  
1082 1095 void
... ... @@ -1084,6 +1097,7 @@ namespace cxxopts
1084 1097 {
1085 1098 ensure_value(details);
1086 1099 m_default = true;
  1100 + m_long_name = &details->long_name();
1087 1101 m_value->parse();
1088 1102 }
1089 1103  
... ... @@ -1105,7 +1119,8 @@ namespace cxxopts
1105 1119 as() const
1106 1120 {
1107 1121 if (m_value == nullptr) {
1108   - throw_or_mimic<std::domain_error>("No value");
  1122 + throw_or_mimic<option_has_no_value_exception>(
  1123 + m_long_name == nullptr ? "" : *m_long_name);
1109 1124 }
1110 1125  
1111 1126 #ifdef CXXOPTS_NO_RTTI
... ... @@ -1125,6 +1140,9 @@ namespace cxxopts
1125 1140 }
1126 1141 }
1127 1142  
  1143 + const std::string* m_long_name = nullptr;
  1144 + // Holding this pointer is safe, since OptionValue's only exist in key-value pairs,
  1145 + // where the key has the string we point to.
1128 1146 std::shared_ptr<Value> m_value;
1129 1147 size_t m_count = 0;
1130 1148 bool m_default = false;
... ...
test/options.cpp
... ... @@ -94,7 +94,7 @@ TEST_CASE(&quot;Basic options&quot;, &quot;[options]&quot;)
94 94 CHECK(arguments[2].key() == "value");
95 95 CHECK(arguments[3].key() == "av");
96 96  
97   - CHECK_THROWS_AS(result["nothing"].as<std::string>(), std::domain_error&);
  97 + CHECK_THROWS_AS(result["nothing"].as<std::string>(), cxxopts::option_has_no_value_exception&);
98 98 }
99 99  
100 100 TEST_CASE("Short options", "[options]")
... ...