Commit fce82fb0350c5c334c9593800dd55a6c2c797f9e

Authored by Jarryd Beck
1 parent 6e31c227

Fix duplicate default option

Fixes #197. Don't parse default options twice when there is a short and
long option.
CHANGELOG.md
@@ -9,6 +9,7 @@ options. The project adheres to semantic versioning. @@ -9,6 +9,7 @@ options. The project adheres to semantic versioning.
9 9
10 * Only search for a C++ compiler in CMakeLists.txt. 10 * Only search for a C++ compiler in CMakeLists.txt.
11 * Allow for exceptions to be disabled. 11 * Allow for exceptions to be disabled.
  12 +* Fix duplicate default options when there is a short and long option.
12 13
13 ## 2.2 14 ## 2.2
14 15
include/cxxopts.hpp
@@ -1086,15 +1086,23 @@ namespace cxxopts @@ -1086,15 +1086,23 @@ namespace cxxopts
1086 parse_default(std::shared_ptr<const OptionDetails> details) 1086 parse_default(std::shared_ptr<const OptionDetails> details)
1087 { 1087 {
1088 ensure_value(details); 1088 ensure_value(details);
  1089 + m_default = true;
1089 m_value->parse(); 1090 m_value->parse();
1090 } 1091 }
1091 1092
1092 size_t 1093 size_t
1093 - count() const 1094 + count() const noexcept
1094 { 1095 {
1095 return m_count; 1096 return m_count;
1096 } 1097 }
1097 1098
  1099 + // TODO: maybe default options should count towards the number of arguments
  1100 + bool
  1101 + has_default() const noexcept
  1102 + {
  1103 + return m_default;
  1104 + }
  1105 +
1098 template <typename T> 1106 template <typename T>
1099 const T& 1107 const T&
1100 as() const 1108 as() const
@@ -1126,6 +1134,7 @@ namespace cxxopts @@ -1126,6 +1134,7 @@ namespace cxxopts
1126 1134
1127 std::shared_ptr<Value> m_value; 1135 std::shared_ptr<Value> m_value;
1128 size_t m_count = 0; 1136 size_t m_count = 0;
  1137 + bool m_default = false;
1129 }; 1138 };
1130 1139
1131 class KeyValue 1140 class KeyValue
@@ -1989,7 +1998,7 @@ ParseResult::parse(int&amp; argc, char**&amp; argv) @@ -1989,7 +1998,7 @@ ParseResult::parse(int&amp; argc, char**&amp; argv)
1989 1998
1990 auto& store = m_results[detail]; 1999 auto& store = m_results[detail];
1991 2000
1992 - if(!store.count() && value.has_default()){ 2001 + if(value.has_default() && !store.count() && !store.has_default()){
1993 parse_default(detail); 2002 parse_default(detail);
1994 } 2003 }
1995 } 2004 }
test/options.cpp
@@ -315,8 +315,10 @@ TEST_CASE(&quot;Default values&quot;, &quot;[default]&quot;) @@ -315,8 +315,10 @@ TEST_CASE(&quot;Default values&quot;, &quot;[default]&quot;)
315 { 315 {
316 cxxopts::Options options("defaults", "has defaults"); 316 cxxopts::Options options("defaults", "has defaults");
317 options.add_options() 317 options.add_options()
318 - ("default", "Has implicit", cxxopts::value<int>()  
319 - ->default_value("42")); 318 + ("default", "Has implicit", cxxopts::value<int>()->default_value("42"))
  319 + ("v,vector", "Default vector", cxxopts::value<std::vector<int>>()
  320 + ->default_value("1,4"))
  321 + ;
320 322
321 SECTION("Sets defaults") { 323 SECTION("Sets defaults") {
322 Argv av({"implicit"}); 324 Argv av({"implicit"});
@@ -327,6 +329,11 @@ TEST_CASE(&quot;Default values&quot;, &quot;[default]&quot;) @@ -327,6 +329,11 @@ TEST_CASE(&quot;Default values&quot;, &quot;[default]&quot;)
327 auto result = options.parse(argc, argv); 329 auto result = options.parse(argc, argv);
328 CHECK(result.count("default") == 0); 330 CHECK(result.count("default") == 0);
329 CHECK(result["default"].as<int>() == 42); 331 CHECK(result["default"].as<int>() == 42);
  332 +
  333 + auto& v = result["vector"].as<std::vector<int>>();
  334 + REQUIRE(v.size() == 2);
  335 + CHECK(v[0] == 1);
  336 + CHECK(v[1] == 4);
330 } 337 }
331 338
332 SECTION("When values provided") { 339 SECTION("When values provided") {