Index: boost/program_options/errors.hpp =================================================================== --- boost/program_options/errors.hpp (Revision 57350) +++ boost/program_options/errors.hpp (Arbeitskopie) @@ -38,6 +38,14 @@ std::string tokens, msg; }; + /** Class thrown when a required/mandatory option is missing */ + class BOOST_PROGRAM_OPTIONS_DECL required_option : public error { + public: + required_option(const std::string& name) + : error(std::string("missing required option ").append(name)) + {} + }; + /** Class thrown when option name is not recognized. */ class BOOST_PROGRAM_OPTIONS_DECL unknown_option : public error { public: Index: boost/program_options/value_semantic.hpp =================================================================== --- boost/program_options/value_semantic.hpp (Revision 57350) +++ boost/program_options/value_semantic.hpp (Arbeitskopie) @@ -44,6 +44,11 @@ */ virtual bool is_composing() const = 0; + /** Returns true if value must be given. Non-optional value + + */ + virtual bool is_required() const = 0; + /** Parses a group of tokens that specify a value of option. Stores the result in 'value_store', using whatever representation is desired. May be be called several times if value of the same @@ -132,6 +137,8 @@ bool is_composing() const { return false; } + bool is_required() const { return false; } + /** If 'value_store' is already initialized, or new_tokens has more than one elements, throws. Otherwise, assigns the first string from 'new_tokens' to 'value_store', without @@ -177,7 +184,8 @@ the value when it's known. The parameter can be NULL. */ typed_value(T* store_to) : m_store_to(store_to), m_composing(false), - m_multitoken(false), m_zero_tokens(false) + m_multitoken(false), m_zero_tokens(false), + m_required(false) {} /** Specifies default value, which will be used @@ -265,6 +273,12 @@ m_zero_tokens = true; return this; } + + typed_value* required() + { + m_required = true; + return this; + } public: // value semantic overrides @@ -292,7 +306,9 @@ } } + bool is_required() const { return m_required; } + /** Creates an instance of the 'validator' class and calls its operator() to perform the actual conversion. */ void xparse(boost::any& value_store, @@ -335,7 +351,7 @@ 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; + bool m_composing, m_implicit, m_multitoken, m_zero_tokens, m_required; boost::function1 m_notifier; }; Index: boost/program_options/variables_map.hpp =================================================================== --- boost/program_options/variables_map.hpp (Revision 57350) +++ boost/program_options/variables_map.hpp (Arbeitskopie) @@ -120,6 +120,9 @@ */ const variable_value& operator[](const std::string& name) const; + /** Returns number of non-empty value of variable 'name' */ + std::size_t count(const std::string& name) const; + /** Sets next variable map, which will be used to find variables not found in *this. */ void next(abstract_variables_map* next); @@ -147,7 +150,10 @@ // Resolve conflict between inherited operators. const variable_value& operator[](const std::string& name) const { return abstract_variables_map::operator[](name); } - + + std::size_t count(const std::string& name) const + { return abstract_variables_map::count(name); } + private: /** Implementation of abstract_variables_map::get which does 'find' in *this. */ Index: libs/program_options/src/variables_map.cpp =================================================================== --- libs/program_options/src/variables_map.cpp (Revision 57350) +++ libs/program_options/src/variables_map.cpp (Arbeitskopie) @@ -12,6 +12,7 @@ #include #include +#include namespace boost { namespace program_options { @@ -95,7 +96,7 @@ - // Second, apply default values. + // Second, apply default values and required options const vector >& all = desc.options(); for(i = 0; i < all.size(); ++i) { @@ -117,7 +118,15 @@ m[key] = variable_value(def, true); m[key].m_value_semantic = d.semantic(); } - } + } + + // add empty value if this is an required option + if (d.semantic()->is_required()) { + if (m.count(key) == 0) { + m[key] = variable_value(); + m[key].m_value_semantic = d.semantic(); + } + } } } @@ -145,7 +154,20 @@ */ if (k->second.m_value_semantic) k->second.m_value_semantic->notify(k->second.value()); - } + } + + // This checks if all required options occur + for (map::const_iterator k = vm.begin(); + k != vm.end(); + ++k) + { + if (k->second.empty() && k->second.m_value_semantic + && k->second.m_value_semantic->is_required()) { + boost::throw_exception(required_option( + k->first)); + + } + } } abstract_variables_map::abstract_variables_map() @@ -178,6 +200,13 @@ { m_next = next; } + + std::size_t abstract_variables_map::count(const std::string& name) const + { + const variable_value& v = get(name); + std::size_t c = (v.empty() ? 0 : 1); + return (m_next ? (c + (*m_next).count(name)) : c); + } variables_map::variables_map() {} Index: libs/program_options/src/cmdline.cpp =================================================================== --- libs/program_options/src/cmdline.cpp (Revision 57350) +++ libs/program_options/src/cmdline.cpp (Arbeitskopie) @@ -309,7 +309,6 @@ } } result.swap(result2); - // Assign position keys to positional options. int position_key = 0;