Boost logo

Boost Users :

From: Bryan Green (bgreen_at_[hidden])
Date: 2007-07-22 02:05:58


The code I posted (quoted below) for optional arguments has some problems.
Getting general purpose optional argument support to work correctly appears
to require modifications to the library. Just wanted to warn anybody who
decided to use the posted code.

Bryan Green writes:
>
> Here is my (working) extension of program_options to support
> GNU-longopt-style optional arguments.
>
> It requires two components: an 'extra_parser', and an extended 'typed_value'.
>
> It would be nice to see program_options modified in such a way that the
> 'extra_parser' was not necessary here (something I'd be happy to attempt).
>
> I could have overridden the 'validate' function instead of extending
> 'typed_value', but I wanted a solution that was type-independent, and could
> therefore be incorporated into the program_options library.
>
> <code>
> namespace po_ext {
> template <class T, class charT = char>
> class typed_value : public po::typed_value<T,charT>
> {
> public:
> typed_value(T* store_to)
> : po::typed_value<T,charT>(store_to) {}
>
> typed_value* optional_token(const T &v)
> {
> m_optional_default_value = boost::any(v);
> m_optional_default_value_as_text =
> boost::lexical_cast<std::string>(v);
> return this;
> }
>
> typed_value* optional_token(const T &v, const std::string& textual)
> {
> m_optional_default_value = boost::any(v);
> m_optional_default_value_as_text = textual;
> return this;
> }
>
> public: // value semantic overrides
>
> std::string name() const {
> if (!m_optional_default_value.empty() &&
> !m_optional_default_value_as_text.empty())
> {
> return "[=" + m_optional_default_value_as_text + "]";
> }
> else
> return po::typed_value<T,charT>::name();
> }
>
> unsigned min_tokens() const
> {
> if (!m_optional_default_value.empty())
> return 0;
> else
> return po::typed_value<T,charT>::min_tokens();
> }
>
> void xparse(boost::any& value_store,
> const std::vector<std::basic_string<charT> >& new_tokens)
> const
> {
> if (!new_tokens.empty() || m_optional_default_value.empty())
> po::validate(value_store, new_tokens, (T*)0, 0);
> }
>
> bool apply_default(boost::any& value_store) const
> {
> if (!m_optional_default_value.empty())
> return false;
> else
> return po::typed_value<T,charT>::apply_default(value_store);
> }
>
> void notify(const boost::any& value_store) const {
> if (!m_optional_default_value.empty() && value_store.empty())
> po::typed_value<T,charT>::notify(m_optional_default_value);
> else
> po::typed_value<T,charT>::notify(value_store);
> }
>
> private:
> boost::any m_optional_default_value;
> std::string m_optional_default_value_as_text;
> };
>
> template <class T>
> typed_value<T>*
> value(T *v)
> {
> typed_value<T>* r = new typed_value<T>(v);
> return r;
> }
> }
>
> pair<string, string> parse_opt(const string& s)
> {
> if (s.find("--proxy=") == 0) {
> return make_pair(string("proxy"), s.substr(8));
> } else {
> return make_pair(string(), string());
> }
> }
>
> enum { DefaultProxyPort = 8869u };
>
> int main(int argc,char *argv[])
> {
> uint16_t proxy_port;
>
> po::options_description desc("options");
> desc.add_options()
> ("proxy,p",
> po_ext::value<uint16_t>(&proxy_port)->optional_token(DefaultProxyPor
> t),
> "run the proxy service")
> ;
>
> po::variables_map vm;
>
> try {
> po::store(po::command_line_parser(argc, argv).options(desc)
> .extra_parser(parse_opt).run(), vm);
> po::notify(vm);
> } catch (exception &e) {
> cout << e.what() << endl;
> return EXIT_FAILURE;
> }
>
> if (vm.count("proxy"))
> enable_the_proxy(proxy_port);
>
> do_your_thing();
>
> return EXIT_SUCCESS;
> }
> </code>
>


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net