program_options: documentation dead end

I am trying to understand composing, multitoken and zero_tokens methods of the typed_value class. This link http://www.boost.org/doc/html/boost/program_options/typed_value.html#id69860... is to the composing method from the reference page for the typed_value class: it suggests looking at the is_composing documentation, which is unfortunately empty. Can this be fixed for Boost 1.34.1? Also, can someone explain to me what the multitokens method does. The doc states "Specifies that the value can span multiple tokens." What is the definition of a token here? Finally, what does zero_tokens() do? Thanks in advance Steven

Steven Mackenzie wrote: composing: If you gather options from several places such as the command line, system-wide options file, user-specific options file and so on then the tokens gathered from different places will be combined and together they form the final option value. Without the composing property only the first definition encountered will be taken as the value. zero_tokens: As I understand, this property is used with flags that don't get any arguments such as -v [--version] could be. multiple_tokens: For example a string option -E could be given like this: program -E stuff more_stuff even_more_stuff -- file now the value of option -E will be "stuff more_stuff even_more_stuff". Without the multiple_tokens property -E would be just "stuff" and all the other stuff would be given as positional options (and probably fail). niko

Niko Vuokko writes:
Steven Mackenzie wrote:
zero_tokens: As I understand, this property is used with flags that don't get any arguments such as -v [--version] could be.
What then is the difference between these two descriptions: a) ("verbose", value<string>()->zero_token(), "verbosity level") b) ("verbose", "verbosity level") And why is 'value<string>' used? Does the string ever get set to something? ((a) is from the documentation). While I'm on the subject, you sometimes see something like the following: ./prog -vvv or ./prog -v -v -v This would *increment* the verbosity level three times. I can't see how to replicate this in program_options. -Bryan

Bryan Green wrote: [snip]
While I'm on the subject, you sometimes see something like the following:
./prog -vvv or ./prog -v -v -v
This would *increment* the verbosity level three times. I can't see how to replicate this in program_options.
This is something I have asked about before on this list, but at the time there was no response. I would be very interested in knowing how to do this using boost::program_options! Cheers, Ian McCulloch

Ian McCulloch writes:
Bryan Green wrote: [snip]
While I'm on the subject, you sometimes see something like the following:
./prog -vvv or ./prog -v -v -v
This would *increment* the verbosity level three times. I can't see how to replicate this in program_options.
This is something I have asked about before on this list, but at the time there was no response. I would be very interested in knowing how to do this using boost::program_options!
Hmm, I'm starting to see a pattern here. Does there happen to be any development going on in program_options, or is it in need of developers? -Bryan

Bryan Green wrote:
Ian McCulloch writes:
Bryan Green wrote: [snip]
While I'm on the subject, you sometimes see something like the following:
./prog -vvv or ./prog -v -v -v
This would *increment* the verbosity level three times. I can't see how to replicate this in program_options.
This is something I have asked about before on this list, but at the time there was no response. I would be very interested in knowing how to do this using boost::program_options!
Hmm, I'm starting to see a pattern here. Does there happen to be any development going on in program_options, or is it in need of developers?
If you're volunteering, you're most welcome. Speaking about -v -v -v, there's no stock way to achieve that. However, the provided interfaces seem to make it possible: 1. Derive from value_semantics. 2. Define the 'parse' method to add one to already stored value. Compare this to handing of vector<string> -- each new token is *appened* to existing value. In the case of -v -v -v, you need each new token to increment existing value, which is essentially the same. - Volodya

Vladimir Prus writes:
Speaking about -v -v -v, there's no stock way to achieve that. However, the provided interfaces seem to make it possible:
1. Derive from value_semantics.
2. Define the 'parse' method to add one to already stored value.
Thanks for the suggestion - I will give it a try!
If you're volunteering, you're most welcome.
Well, I'd really like to be able to get the functionality of GNU getopt_long's 'optional_argument' feature. Do you have any sense of the feasability of that? If it seems feasable, I might be able to take a crack at it. -Bryan

Bryan Green wrote:
Vladimir Prus writes:
Speaking about -v -v -v, there's no stock way to achieve that. However, the provided interfaces seem to make it possible:
1. Derive from value_semantics.
2. Define the 'parse' method to add one to already stored value.
Thanks for the suggestion - I will give it a try!
If it works out, please post the solution to the list. It would be very useful! Also as an example for how to extend the library. Cheers, Ian

Ian McCulloch writes:
Bryan Green wrote:
Vladimir Prus writes:
Speaking about -v -v -v, there's no stock way to achieve that. However, the provided interfaces seem to make it possible:
1. Derive from value_semantics.
2. Define the 'parse' method to add one to already stored value.
Thanks for the suggestion - I will give it a try!
If it works out, please post the solution to the list. It would be very useful! Also as an example for how to extend the library.
Done! That wasn't so bad after all. It's pretty cool to see it working. Hurrah for extensibility! I created an 'accumulating_value' class, with a 'accum_value()' function. Here is the usage: desc.add_options() ("verbose,v", po_ext::accum_value<int>(), "print extra information") ; ... if (vm.count("verbose")) { verbose = vm["verbose"].as<int>(); It also supports the 'default_value()' method the way I think it should. Here is the code: ========================================================================== namespace po_ext { template <class T, class charT = char> class accumulating_value : public po::typed_value<T,charT> { public: accumulating_value(T* store_to=0) : po::typed_value<T,charT>(store_to), origin(0) { (void) po::typed_value<T,charT>::zero_tokens(); } accumulating_value* default_value(const T &v) { // setting a default value sets the origin to that value origin = v; (void) po::typed_value<T,charT>::default_value(v); return this; } accumulating_value* default_value(const T &v,const std::string& textual) { // setting a default value sets the origin to that value origin = v; (void) po::typed_value<T,charT>::default_value(v, textual); return this; } void xparse(boost::any& value_store, const std::vector<std::basic_string<charT> >& new_tokens) const { // if this is the first occurrence of the option, initialize it // to the origin. if (value_store.empty()) value_store = boost::any(origin); ++boost::any_cast<T&>(value_store); } private: T origin; // the numeric origin from which to increment upward. }; template <class T> accumulating_value<T>* accum_value(T *v) { accumulating_value<T>* r = new accumulating_value<T>(v); return r; } template <class T> accumulating_value<T>* accum_value() { return accum_value<T>(0); } } ==========================================================================

Bryan Green wrote:
Vladimir Prus writes:
Speaking about -v -v -v, there's no stock way to achieve that. However, the provided interfaces seem to make it possible:
1. Derive from value_semantics.
2. Define the 'parse' method to add one to already stored value.
Thanks for the suggestion - I will give it a try!
If you're volunteering, you're most welcome.
Well, I'd really like to be able to get the functionality of GNU getopt_long's 'optional_argument' feature. Do you have any sense of the feasability of that? If it seems feasable, I might be able to take a crack at it.
I assume you mean that, for example --foobar=10 explicitly provides a value of 'foobar', and --foobar provides some default value of 'foobar'. Something like that was actually supported, but it was somewhat messy. First of all, it requires two default values -- default value if the option is not provided at all, and value that is used when the option is provided, but without any explicit value. This is already nasty interface. Further, given --foo -1 what is '-1'? Is it value to '--foo'? Or is it separate option? So, I decided that optional options are not really needed. I'm open to other opinions, but there should be some nice solution to the above problems. - Volodya

Vladimir Prus writes:
I assume you mean that, for example
--foobar=10
explicitly provides a value of 'foobar', and
--foobar
Precisely.
provides some default value of 'foobar'. Something like that was actually supported, but it was somewhat messy. First of all, it requires two default values -- default value if the option is not provided at all, and value that is used when the option is provided, but without any explicit value. This is already nasty interface.
Would it not be that, if not given, vm.count("arg") == 0; and if it was given, vm["arg"] would either be user-specified, or a default? Something like this perhaps: desc.add_options() ("listen,l", po::value<int>()->optional_token()->default_value(5555), "listen on a port") ; ... bool do_listening = false; if (vm.count() != 0) { do_listening = true; listen_port = vm["listen"].as<int>(); }
Further, given
--foo -1
what is '-1'? Is it value to '--foo'? Or is it separate option?
I don't see the relationship here. In terms of GNU's optional_argument feature, the optional token must be appended with an '=', so that it is unambiguous. Your example above is therefore unambiguous: -1 is a separate option. -Bryan

Bryan Green writes:
Vladimir Prus writes:
I assume you mean that, for example
--foobar=10
explicitly provides a value of 'foobar', and
--foobar
Precisely.
Would it not be that, if not given, vm.count("arg") == 0; and if it was given, vm["arg"] would either be user-specified, or a default? Something like this perhaps:
desc.add_options() ("listen,l", po::value<int>()->optional_token()->default_value(5555), "listen on a port") ; ... bool do_listening = false; if (vm.count() != 0) { do_listening = true; listen_port = vm["listen"].as<int>(); }
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(DefaultProxyPort), "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>

Bryan Green writes:
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()); } }
This function could of course be made general-purpose, by detecting the '--.*=' pattern. -Bryan

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>

Vladimir Prus writes:
Bryan Green wrote:
Vladimir Prus writes:
If you're volunteering, you're most welcome.
Well, I'd really like to be able to get the functionality of GNU getopt_long's 'optional_argument' feature. Do you have any sense of the feasability of that? If it seems feasable, I might be able to take a crack at it.
I assume you mean that, for example
--foobar=10
explicitly provides a value of 'foobar', and
--foobar
provides some default value of 'foobar'. Something like that was actually supported, but it was somewhat messy. First of all, it requires two default values -- default value if the option is not provided at all, and value that is used when the option is provided, but without any explicit value. This is already nasty interface. Further, given
--foo -1
what is '-1'? Is it value to '--foo'? Or is it separate option? So, I decided that optional options are not really needed. I'm open to other opinions, but there should be some nice solution to the above problems.
- Volodya
Vladimir, have you had a chance to look at the patch I submitted to the mailing list for program_options optional ("implicit") arguments? Do you have any issues with the solution? It would be great if this feature could get incorporated into boost. I'd like to know what you think of it. -Bryan

Vladimir, have you had a chance to look at the patch I submitted to the mailing list for program_options optional ("implicit") arguments? Do you have any issues with the solution? It would be great if this feature could get incorporated into boost. I'd like to know what you think of it.
YOu might want to submit it to trac, so it isn't lost on the mailing list. Chris

On 7/27/07, Chris Weed <chrisweed@gmail.com> wrote:
Vladimir, have you had a chance to look at the patch I submitted to the mailing list for program_options optional ("implicit") arguments? Do you have any issues with the solution? It would be great if this feature could get incorporated into boost. I'd like to know what you think of it.
YOu might want to submit it to trac, so it isn't lost on the mailing list. Chris
Where are the links to Trac from http://boost.org/? I've been trying to find Trac before but didn't succeed.

On 7/27/07, Olaf van der Spek <olafvdspek@gmail.com> wrote:
On 7/27/07, Chris Weed <chrisweed@gmail.com> wrote:
Vladimir, have you had a chance to look at the patch I submitted to the mailing list for program_options optional ("implicit") arguments? Do you have any issues with the solution? It would be great if this feature could get incorporated into boost. I'd like to know what you think of it.
YOu might want to submit it to trac, so it isn't lost on the mailing list. Chris
Where are the links to Trac from http://boost.org/? I've been trying to find Trac before but didn't succeed.
Report Bugs -> Bug tracking facility http://svn.boost.org/trac/boost/report Chris

"Chris Weed" writes:
Vladimir, have you had a chance to look at the patch I submitted to the mailing list for program_options optional ("implicit") arguments? Do you have any issues with the solution? It would be great if this feature could get incorporated into boost. I'd like to know what you think of it.
YOu might want to submit it to trac, so it isn't lost on the mailing list.
Thanks for the suggestion. I just tried that and got rejected: Internal Error Submission rejected as potential spam (Akismet says content is spam) ???? -Bryan

Ian McCulloch wrote:
Bryan Green wrote: [snip]
While I'm on the subject, you sometimes see something like the following:
./prog -vvv or ./prog -v -v -v
This would *increment* the verbosity level three times. I can't see how to replicate this in program_options.
This is something I have asked about before on this list, but at the time there was no response. I would be very interested in knowing how to do this using boost::program_options!
One complete solution has already been posted, but just for diversity, setting a notifier function on the variable involves less typing. Something like int verbosityLevel; ... verbosityLevel = 0; ... void VerbosityWatcher( bool val ) { ++verbosityLevel; } ... desc.add_options() ("verbose,v", po::bool_switch() ->notifier( &VerbosityWatcher ), "print extra information") ; Disadvantages are that the value isn't available through vm, the default value isn't set by the usual ->default method or constructor option, ... Probably some some of those could be coded around. Personally I think a simple -v 3 is nicer; the -v -v -v style of syntax seems a bit verbose to me :-)

Steven Mackenzie wrote:
Ian McCulloch wrote:
Bryan Green wrote: [snip]
While I'm on the subject, you sometimes see something like the following:
./prog -vvv or ./prog -v -v -v
This would *increment* the verbosity level three times. I can't see how to replicate this in program_options.
This is something I have asked about before on this list, but at the time there was no response. I would be very interested in knowing how to do this using boost::program_options!
One complete solution has already been posted, but just for diversity, setting a notifier function on the variable involves less typing. Something like
int verbosityLevel; ... verbosityLevel = 0; ... void VerbosityWatcher( bool val ) { ++verbosityLevel; } ... desc.add_options() ("verbose,v", po::bool_switch() ->notifier( &VerbosityWatcher ), "print extra information") ;
Does this actually work? I think the plan is for notifier functions to be called only when you call 'notify' on variables_map. So, notifier will be called only once. Of course, I might have forgotten how the library actually works, or there might be a bug. - Volodya

Vladimir Prus wrote:
Steven Mackenzie wrote:
Ian McCulloch wrote:
Bryan Green wrote: [snip]
While I'm on the subject, you sometimes see something like the following:
./prog -vvv or ./prog -v -v -v
Something like
void VerbosityWatcher( bool val ) { ++verbosityLevel; } ... desc.add_options() ("verbose,v", po::bool_switch() ->notifier( &VerbosityWatcher ), "print extra information") ;
Does this actually work? I think the plan is for notifier functions to be called only when you call 'notify' on variables_map. So, notifier will be called only once.
No, it doesn't. In fact, with program_options from 1.34.1 I can't even construct an options_descripton which allows multiple bool_switch arguments in the command line. The closest I could come up with is support for ./prog -v 1 -v 1 -v 1 by using value<vector<bool> >. Using the notifier approach for this is quick and simple, but of course doesn't actually meet the original requirement (unless the optional arguments code that Bryan Green suggested could actually be implemented!). I'm not expressing an opinion about command lines that accept that syntax! === // silly example showing a notifier for multiple values of an option void ActionObserverBool( vector<bool >const & val ) { if( val.size() ) { cout << "We received an option value " << val.size() << " times." << endl; } } int main(int argc, char **argv) { ... actionOptions.add_options() ( "verbosity,v", // collecting the command line input in to a vector // type allows multiple occurence of the option on // command line. po::value< vector< bool > >() ->notifier( ActionObserverBool ) , "Progressively increase the diagnostic detail." ) ; store(po::command_line_parser(argc, argv). options(actionOptions).run(), vm); // run the notifier commands and store values in args. notify(vm); }

Steven Mackenzie writes:
Ian McCulloch wrote:
Bryan Green wrote: [snip]
While I'm on the subject, you sometimes see something like the following:
./prog -vvv or ./prog -v -v -v
This would *increment* the verbosity level three times. I can't see how to replicate this in program_options.
This is something I have asked about before on this list, but at the time there was no response. I would be very interested in knowing how to do this using boost::program_options!
One complete solution has already been posted, but just for diversity, settin g a notifier function on the variable involves less typing. Something like
int verbosityLevel; ... verbosityLevel = 0; ... void VerbosityWatcher( bool val ) { ++verbosityLevel; } ... desc.add_options() ("verbose,v", po::bool_switch() ->notifier( &VerbosityWatcher ), "print extra information") ;
Disadvantages are that the value isn't available through vm, the default valu e isn't set by the usual ->default method or constructor option, ... Probably s ome some of those could be coded around.
Personally I think a simple -v 3 is nicer; the -v -v -v style of syntax seems a bit verbose to me :-)
Allowing '-v 3' precludes allowing just '-v', which is the common case. As for notifier, does it really work that way? I am interested in a way to track multiple occurrences, but I thought the notifier only got called once at the end. -Bryan

Bryan Green wrote:
Steven Mackenzie writes:
Ian McCulloch wrote:
Bryan Green wrote: [snip]
While I'm on the subject, you sometimes see something like the following:
./prog -vvv or ./prog -v -v -v
This would *increment* the verbosity level three times. I can't see how to replicate this in program_options.
This is something I have asked about before on this list, but at the time there was no response. I would be very interested in knowing how to do this using boost::program_options!
One complete solution has already been posted, but just for diversity, settin g a notifier function on the variable involves less typing. Something like
int verbosityLevel; ... verbosityLevel = 0; ... void VerbosityWatcher( bool val ) { ++verbosityLevel; } ... desc.add_options() ("verbose,v", po::bool_switch() ->notifier( &VerbosityWatcher ), "print extra information") ;
Disadvantages are that the value isn't available through vm, the default valu e isn't set by the usual ->default method or constructor option, ... Probably s ome some of those could be coded around.
Personally I think a simple -v 3 is nicer; the -v -v -v style of syntax seems a bit verbose to me :-)
Allowing '-v 3' precludes allowing just '-v', which is the common case.
As for notifier, does it really work that way? I am interested in a way to track multiple occurrences, but I thought the notifier only got called once at the end.
-Bryan
Aren't -vvv and -v -v -v non-standard, and therefore to be deprecated? These smack of smart-arse programming[1] to me. Surely, as has been suggested, the standard approach (which is already supported by program_options) is to do -v <argument> (or --verbose <argument>). If you want to increase the verbosity to 10, just use -v 10, for crying out loud, rather than demanding that the hapless user types -v -v -v -v -v -v -v -v -v -v or -vvvvvvvvvv and then has to check twice to see whether they've put the right number of v's in. In short, IMO, anyone wanting to be too clever by half should not expect Boost to bend over backwards to support them. Paul [1] Non-standard computing term that you won't find in FOLDOC.

Paul Giaccone writes:
Bryan Green wrote:
Steven Mackenzie writes:
Ian McCulloch wrote:
Bryan Green wrote: [snip]
While I'm on the subject, you sometimes see something like the following :
./prog -vvv or ./prog -v -v -v
This would *increment* the verbosity level three times. I can't see how to replicate this in program_options.
This is something I have asked about before on this list, but at the time there was no response. I would be very interested in knowing how to do this using boost::program_options!
One complete solution has already been posted, but just for diversity, set tin g a notifier function on the variable involves less typing. Something like
int verbosityLevel; ... verbosityLevel = 0; ... void VerbosityWatcher( bool val ) { ++verbosityLevel; } ... desc.add_options() ("verbose,v", po::bool_switch() ->notifier( &VerbosityWatcher ), "print extra information") ;
Disadvantages are that the value isn't available through vm, the default v alu e isn't set by the usual ->default method or constructor option, ... Probabl y s ome some of those could be coded around.
Personally I think a simple -v 3 is nicer; the -v -v -v style of syntax se ems a bit verbose to me :-)
Allowing '-v 3' precludes allowing just '-v', which is the common case.
As for notifier, does it really work that way? I am interested in a way to track multiple occurrences, but I thought the notifier only got called once at the end.
-Bryan
Aren't -vvv and -v -v -v non-standard, and therefore to be deprecated?
I don't know about that, but my goal is to convert from use of GNU longopt to boost::program_options, without breaking compatibility (for users or preexisting scripts).
These smack of smart-arse programming[1] to me. Surely, as has been suggested, the standard approach (which is already supported by program_options) is to do -v <argument> (or --verbose <argument>). If you want to increase the verbosity to 10, just use -v 10, for crying out loud, rather than demanding that the hapless user types -v -v -v -v -v -v -v -v -v -v or -vvvvvvvvvv and then has to check twice to see whether they've put the right number of v's in.
Suggesting -v 10 is quite extreme. I've never known a program to go beyond three. Typing -vvv seems reasonable to me. As for the "standard approach", I believe that is to support '-v'. And as I said:
Allowing '-v 3' precludes allowing just '-v', which is the common case.
Actually, I'm wondering, what constitutes "standard" for option parsing? On Unix at least, you see many variations. Just consider gcc. -Bryan

Niko Vuokko wrote:
multiple_tokens: For example a string option -E could be given like this:
program -E stuff more_stuff even_more_stuff -- file
Niko, Others, Thanks for your descriptions, they were very helpful, as was the discussion generated. It seems like zero_tokens and multiple_tokens can't be mixed? I would like to define a command line syntax like this ./prog --export --export name.bin binary --export "another name.txt" text transposed --etc where --export can occour multiple times as above, with between 0 and 3 parameters. If --export appears with no arguments then the export action is performed, but with no output to disk; if it has arguments then they should either be parsed in to a custom structure, or vector<string>. So I suppose one definition of the export option would be struct ExportConfig { enum FileFmt { TEXT, BINARY, }; string name; FileFmt format; bool isTransposed; }; desc.add_options() ("export", po::value< vector < ExportConfig > >(), "Export data for processing, with output to the named disk file") ; I understand that allowing the zero argument version of --export is conceptually difficult, but if I split that option out as --exportNoFile, could I use program_options to parse the remaining 1 - 3 argument version? Steven
participants (8)
-
Bryan Green
-
Chris Weed
-
Ian McCulloch
-
Niko Vuokko
-
Olaf van der Spek
-
Paul Giaccone
-
Steven Mackenzie
-
Vladimir Prus