Index: boost/program_options/detail/value_semantic.hpp =================================================================== --- boost/program_options/detail/value_semantic.hpp (revision 38498) +++ boost/program_options/detail/value_semantic.hpp (working copy) @@ -16,7 +16,13 @@ std::string typed_value::name() const { - if (!m_default_value.empty() && !m_default_value_as_text.empty()) { + if (!m_implicit_value.empty() && !m_implicit_value_as_text.empty()) { + std::string msg = "[=arg(=" + m_implicit_value_as_text + ")]"; + if (!m_default_value.empty() && !m_default_value_as_text.empty()) + msg += " (=" + m_default_value_as_text + ")"; + return msg; + } + else if (!m_default_value.empty() && !m_default_value_as_text.empty()) { return arg + " (=" + m_default_value_as_text + ")"; } else { return arg; @@ -155,7 +161,13 @@ xparse(boost::any& value_store, const std::vector >& new_tokens) const { - validate(value_store, new_tokens, (T*)0, 0); + // If no tokens were given, and the option accepts an implicit + // value, then assign the implicit value as the stored value; + // otherwise, validate the user-provided token(s). + if (new_tokens.empty() && !m_implicit_value.empty()) + value_store = m_implicit_value; + else + validate(value_store, new_tokens, (T*)0, 0); } template Index: boost/program_options/value_semantic.hpp =================================================================== --- boost/program_options/value_semantic.hpp (revision 38498) +++ boost/program_options/value_semantic.hpp (working copy) @@ -204,6 +204,38 @@ return this; } + /** Specifies an implicit value, which will be used + if the option is given, but without an adjacent value. + Using this implies that an explicit value is optional, but if + given, must be strictly adjacent to the option, i.e.: '-ovalue' + or '--option=value'. Giving '-o' or '--option' will cause the + implicit value to be applied. + */ + typed_value* implicit_value(const T &v) + { + m_implicit_value = boost::any(v); + m_implicit_value_as_text = + boost::lexical_cast(v); + return this; + } + + /** Specifies an implicit value, which will be used + if the option is given, but without an adjacent value. + Using this implies that an explicit value is optional, but if + given, must be strictly adjacent to the option, i.e.: '-ovalue' + or '--option=value'. Giving '-o' or '--option' will cause the + implicit value to be applied. + Unlike the above overload, the type 'T' need not provide + operator<< for ostream, but textual representation of default + value must be provided by the user. + */ + typed_value* implicit_value(const T &v, const std::string& textual) + { + m_implicit_value = boost::any(v); + m_implicit_value_as_text = textual; + return this; + } + /** Specifies a function to be called when the final value is determined. */ typed_value* notifier(function1 f) @@ -243,7 +275,7 @@ unsigned min_tokens() const { - if (m_zero_tokens) { + if (m_zero_tokens || !m_implicit_value.empty()) { return 0; } else { return 1; @@ -301,6 +333,8 @@ // as boost::optional to avoid unnecessary instantiations. boost::any m_default_value; std::string m_default_value_as_text; + boost::any m_implicit_value; + std::string m_implicit_value_as_text; bool m_composing, m_implicit, m_multitoken, m_zero_tokens; boost::function1 m_notifier; }; Index: libs/program_options/test/variable_map_test.cpp =================================================================== --- libs/program_options/test/variable_map_test.cpp (revision 38498) +++ libs/program_options/test/variable_map_test.cpp (working copy) @@ -102,6 +102,25 @@ BOOST_CHECK(vm3["vee"].as() == "42"); BOOST_CHECK(vm3["voo"].as() == "1"); BOOST_CHECK(vm3["iii"].as() == 123); + + options_description desc3; + desc3.add_options() + ("imp", po::value()->implicit_value(100)) + ("iim", po::value()->implicit_value(200)->default_value(201)) + ("mmp,m", po::value()->implicit_value(123)->default_value(124)) + ; + char* cmdline6_[] = { "--imp=1 -m" }; + vector cmdline6 = sv(cmdline6_, + sizeof(cmdline6_)/sizeof(cmdline6_[0])); + parsed_options a6 = command_line_parser(cmdline6).options(desc3).run(); + + variables_map vm4; + store(a6, vm4); + notify(vm4); + BOOST_REQUIRE(vm4.size() == 3); + BOOST_CHECK(vm4["imp"].as() == 1); + BOOST_CHECK(vm4["iim"].as() == 201); + BOOST_CHECK(vm4["mmp"].as() == 123); } int stored_value; Index: libs/program_options/src/cmdline.cpp =================================================================== --- libs/program_options/src/cmdline.cpp (revision 38498) +++ libs/program_options/src/cmdline.cpp (working copy) @@ -329,6 +329,14 @@ max_tokens -= opt.value.size(); + // A value is optional if min_tokens == 0, but max_tokens > 0. + // If a value is optional, it must appear in opt.value (because + // it was 'adjacent'. Otherwise, remove the expectation of a + // non-adjacent value. (For now, we just check max_tokens == 1, + // as there is no current support for max_tokens>1) + if (min_tokens == 0 && max_tokens == 1 && opt.value.empty()) + --max_tokens; + // Everything's OK, move the values to the result. for(;!other_tokens.empty() && max_tokens--; ) { opt.value.push_back(other_tokens[0]); Index: libs/program_options/example/options_description.cpp =================================================================== --- libs/program_options/example/options_description.cpp (revision 38498) +++ libs/program_options/example/options_description.cpp (working copy) @@ -26,11 +26,17 @@ { try { int opt; + int portnum; po::options_description desc("Allowed options"); desc.add_options() ("help", "produce help message") ("optimization", po::value(&opt)->default_value(10), "optimization level") + ("verbose,v", po::value()->implicit_value(1), + "enable verbosity (optionally specify level)") + ("listen,l", po::value(&portnum)->implicit_value(1001) + ->default_value(0,"no"), + "listen on a port.") ("include-path,I", po::value< vector >(), "include path") ("input-file", po::value< vector >(), "input file") @@ -62,7 +68,14 @@ << vm["input-file"].as< vector >() << "\n"; } + if (vm.count("verbose")) { + cout << "Verbosity enabled. Level is " << vm["verbose"].as() + << "\n"; + } + cout << "Optimization level is " << opt << "\n"; + + cout << "Listen port is " << portnum << "\n"; } catch(exception& e) {