Boost logo

Boost :

From: Vladimir Prus (ghost_at_[hidden])
Date: 2003-05-29 06:16:28


Gennadiy Rozental wrote:

>> OK, I understand your opinion. I'm probably misusing "you don't pay for
> what
>> you don't use" principle, but I find that 'options_and_argument' class is
>> important. Sometimes you really don't need typed storage.
>
> Then just use default std::string type for parameter types - you got your
> string to string parser.
> IMO options_and_arguments is redundant.

Hmm.. and what will you do with multiple occurences of the same option? Use
std::vector< std::string> > as default type? And should I still support
'notify' functions, validators and the like.

You can view options_and_arguments as an interface user by parsers to
provide *syntactic only* information --- which I find important. For
example, command line parser should not care about what's default value of
an option, or what it's type. It should only return (string,string) pair.
The same applies to config file.

And I think this interface will be usefull for users, as well. If practice
shows me to be wrong --- well, this interface will be moved into
implementation part.

>> It's possible to link several variables_map instances in a chain, which
>> handles the primary need: different preference of options from different
>> sources. It's true that different naming of options is not handled,
> however
>> I'm still considering if it's better to do that in parsers.
>
> I do not say it should be done in parsers. But this is only one conflict
> resolution strategy. There may be many more. And what important different
> parameters may have different strategy: for trace level we prefer CL value
> to the environment. For debug/release mode switch we may want to use "and"
> or "or" logic.

I think it's better to consider what is really desired.

>> > In my terms above would look like this:
>> >
>> > parameter<std::string>( "output" )
>> > << place_to( output_file_name )
>> > << default_value( "/tmp/abc" )
>> > << description( "output file name" )
>> >
>> > You do not need to know anything in addition about how parser works.
>> > Moreover it's unifies and easily extendable to adopt different
> modifiers.
>>
>> It seems we'll make no progress with this question. I find your syntax
> more
>> verbose, and it still leaves questions. What if I have "--output foo
>> --output bar" or
>
> Parameter above is not declared multipliable.

I don't think anything in the above code suggests there are "multipliable"
parameters ;-) Really, shouldn't I look in docs to find that out?

>> when does default value plays: can I write simply
>> "--output", without any value?
>
> No. This is parameter. It's required to have a value. Seems obvious to me.
> If not parser will generate the error.

It's only obvious if you provide the definition of 'parameter', which you
can provide only in docs.

>> > I may have several if statements:
>> > if( cla_parser.parse(...) ) ...
>> > if( config_file.parse(...) ) ...
>> > ...
>> >
>> > It's not worse than several catch clauses. Try/catch seems redundant
> when
>> > used right aroung the function that throw an exception.
>>
>> But it's worse than *one* catch clause --- which can be the 'catch'
>> clause already present in your 'main' function (at least in my 'main'
>> functions).
>
> It's unfair comparison. I could also write one if:
>
> if( ! cla_parser.parse(...) || ! config_file.parse(...) ) ...
>
> But I most probably would not want to do so, cause I want to show
> different messages depends on what failed.
>
> To be more close to the topic, could you show any practical usage for the
> exception classes you defined in error.hpp.

For example

catch(const po::unknown_option& e) {
        cout << e.what() << "\n"; // output the error
        cout << desc << \n"; // print the list of all options to help user
}
catch(const po::ambiguous_option& e) {
        cout << e.what() << "\n"; // output the error
        cout << "...."; // describe how options can be abbreviated.
                        // maybe print the list of all alternatives.
}
catch(const std::exception& e) {
        cout << e.what() << "\n";
}

>> > I don't get it. What long name would I use if it only have short name.
>>
>> Whatever long name you like. You've been talking about maintenance
>> programmer previously. Now imagine he looks at
>>
>> vm["-u"].as<int>()
>>
>> Fine, what does it mean? Would anyone like to write such cryptic code? A
>> better idea is write
>>
>> vm["unified_context_lines"].as<int>()
>>
>> Now, "unified_context_lines" is the long name, used in program. You can
> have
>> only "-u" in command line, no problem.
>
> But parameters definition does not contain "unified_context_lines" name at
> all.

What's "parameter definition"? You'll have

  desc.add_options()
     ("unified_context_lines,u", ....

So the long name is declared. Yes, it's not allowed in command line, but
that's not concern of whoever accesses the value.

>> > What would you return when user call short name method?
>>
>> You mean option_description::short_name()? Empty string will be returned.
>> What's wrong with that?
>
> This methods is redundant in this case. IMO there should not be redundant
> methods in any way library is used.

I don't understand you. Do you mean that no matter who users the library, he
must call all methods of all classes? Return of empty string to indicate
"no short option" is none the worse then not using validator, if it's not
needed.

- Volodya


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk