Class used to encapsulate options belonging an options group.
This class offers two ways to access the options and their values in an options group. These two methods differ in their convience, the cost of performing them and the level of validation possible. In the following discussion, n_total is the total number of options being checked for and n_set is the number of options set.
1) Looking up the values directly.
Here the software client just looks up the value directly. If the option with the given name does not exist then the function option_exists( ... )
will return false
.
In the following example, the lookup of the option named "tol" is attempted on the OptionsGroup
object optgrp
.
const std::string& val = optgrp.option_value( "tol" );
if( OptionsGroup::option_exists( val ) )
std::cout << "\ntol = " << val;
The total cost of this way of looking up option values is:
O(n_total*log(n_set)).
The disadvantage of using this method is that if the user misspelled the name of the option then the option will not be found or set. In the above example, if the user misspelled the option "tol" as "tal" then OptionsGroup::option_exists( val )
would return false and the option value would not be accessed.
2) Setting options by iterating through options present.
In this method the software client must keep a map to translate from an options name to an id representing the option. Then a switch can be used to take action.
In the following example (see the example from {OptionsFromStream} , three possible options are looked for. Here the client has defined an enum for the options and initialized a {StringToIntMap}.
const char optgrp_name[] = "MySolverOptions";
const int num_opt = 3;
enum EOptions {
TOL
,MAX_ITER
,PROB_TYPE
};
const char* SOptions[num_opt] = {
"tol"
,"max_iter"
,"prob_type"
};
StringToIntMap opt_map( optgrp_name, num_opt, SOptions );
OptionsGroup::const_iterator
itr = optgrp.begin(),
itr_end = optgrp.end();
for( ; itr != itr_end; ++itr ) {
switch( (EOptions)opt_map(option_name(itr)) ) {
case TOL:
std::cout << "\noption tol = " << option_value(itr);
break;
case MAX_ITER:
std::cout << "\noption max_iter = " << option_value(itr);
break;
case PROB_TYPE:
std::cout << "\noption prob_type = " << option_value(itr);
break;
default:
std::cout << "\nThe option " << option_name(itr) << " is not valid";
exit(-1);
}
}
The above code terminates the program in case the option with the name returned from option_name(itr)
is not expected. This option could be ignored (as would have been in method 1) or some other action could be taken. It is a good idea to use the above method to validate that all of the options that the user sets for an options_group are known by the client software so that misspellings are caught. For example, if the user misspelled "tol" as "tal" then the "opt_map" object above would not find this option name an the default:
case above would be executed.
The total cost of this way off looking up option values is:
O(n_set*log(n_total))
As it can be clearly seen, method 2 will be faster since n_total >= n_set. Method 1 takes less overhead for the client (no map or enum needed) and is easier to maintain. The real advantage of Method 2 though is that if a user misspells an option then Method 1 will not catch this while Method 2 will. For this reason alone Method 2 is to be preferred.
Definition at line 229 of file OptionsFromStreamPack_OptionsFromStream.hpp.