vSMC
vSMC: Scalable Monte Carlo
Program option

Introduction

Basic example

int main (int argc, char **argv)
{
double Value;
ProgramOptionMap Map;
Map.add("option_name", "option description", &Value);
Map.process(argc, argv)
if (Map.count("help")) // Option --help are specified
return 0;
std::cout << Value << std::endl;
}

And if on the command line,

1 ./prog --option_name 0.5

This program will produce the output

0.5

In the source, options are added using ProgramOptionMap::add. The first argument is the option name, say option_name. The second is a description of the option. And the third is an pointer points to the destination of the value. On the command line the option is specified with --option_name followed by values.

Add options

The general form of the member function ProgramOptionMap::add is

template <typename T, typename Dest, typename V>
ProgramOptionMap &add (const std::string &name, const std::string &desc, Dest *dest, V val);

where T is the value type of the option. If the fourth (optional) argument is present, it is taken to be the default value of the option. The second template argument, Dest is the type of the destination pointer.

If T is the same as Dest, then the option is a scalar option that can store a single value. Otherwise, Dest is taken to be a container type, e.g., std::vector<T>, and the option can store multiple values. The behavior differs when multiple values are specified in the command line. Therefore, if Dest is a container type and is intended to be used as such, the first template argument needs to be specified explicity. The only exception is when Dest is std::vector<T>, in which case no template argument needs to be specified. The value type T needs to support input stream operator>>. The container type needs to support push_back(T &), in other words, it needs to be a sequential container.

To summary, the template argument deduction is shown in the following example,

double sOpt;
std::vector<double> vOpt;
std::list<double> lOpt;
Map.add("sName", "desc", &sOpt); // OK, single value option. T: double, Dest: double
Map.add("vName", "desc", &vOpt); // OK, multi-value option. T: double, Dest: std::vector<double>
Map.add<double>("name", "desc", &lOpt); // OK, multi-value option. T: double, Dest: std::list<double>
Map.add("lName", "desc", &lOpt); // Error! T: std::list<double>, Dest: std::list<double>, no operator>>

Process option

Options can be processed by calling Map.process(argc, argv), where argc and argv are the typical arguments of the main function.

After processing, one can use ProgramOptionMap::count to obtain the number of a certain option being specified on the command line. For example,

Map.count("name");

Specify options on the command line

On the command line, each option can be specified multiple times. After each option name, zero or more values can be specified. Multiple values shall be seperated by white spaces. Optionally comma can be added after each value. For example,

1 ./prog --sName val # OK
2 ./prog --sName val1 --sName val2 # OK
3 ./prog --sName val1 val2 # OK
4 ./prog --sName val1, val2 # OK
5 ./prog --sName val1,val2 # Error, white space required after comma

Note that any values specified before the first option are ignored. Any unknown options are also ignored. For example,

1 ./prog val1 val2 --sName val --nName val3 # "val1 val2" and "--nName val3" ignored

Specify an option multiple times,

If the option is a single value option, it is as if only the last one is used. If the option is a multi-value option, then each of them are processed. Continue the example,

1 ./prog --sName val # sOpt => val
2 ./prog --sName val1 --sName val2 # sOpt => val2
3 ./prog --vName val1 --vName val2 # vOpt => {val1, val2}

Specify multiple values

After each option, multiple value can be specified. For each value, first trailing white spaces and comma are stripped. Then, if it is a single value option, values are joint into a single string, separated by a single white space, and processed as a single value. If it is a multi-value option, then each value are processed separately, as if they are specified multiple times. For example,

1 ./prog --sName val1, val2 # Equivalent to ./prog --sName "val1 val2"
2 ./prog --vName val1, val2 # Equivalent to ./prog --vName val1 --vName val2

A more useful example is as the following,

vsmc::cxx11::uniform_real_distribution<double> runif;
Map.add("runif", "desc", &runif);
1 ./prog --runif -1, 1 # OK. Uniform distribution on (-1, 1]
2 ./prog --runif -1 --runif 1 # Error! uniform_real_distribution operator>> requires two values

If for a multi-value option, each value needs to contain multiple sub values, proper shell quoting is required. For example

std::vector<vsmc::cxx11::uniform_real_distribution<double> > vrunif;
Map.add("vrunif", "desc", &vrunif);
1 ./prog --vrunif -1, 1 # Error! Equivalent to ./prog --vrunif -1 --vrunif 1
2 ./prog --vrunif "-1 1" # OK.
3 ./prog --vrunif "-1 1", "-2 2" # OK. vrunif now has two uniform distributions.

Boolean options

If the value type of an option is bool, then it is treated specially. If no values are specified, it is treated as true. For example,

bool Flag;
Map.add("flag", "desc", &Flag);
1 ./prog --flag # Flag => true

If values are specified, then the following are treated as true: non-zero decimal integer values, e.g., 1, 23. y, Y, yes, Yes, YES, t, T, True, TRUE. The following are treated as false: zero, e.g., 0, 00, n, N, no, No, NO, f, F, false, False, FALSE. In other words, for values formed entirely of digits, it is treated as an integer and tested as in C/C++; if it is a string, then the common yes and no and their short forms, lower/upper case variants are treated as true and false, respectively. And common boolean literal in programming languages (not only true and false as in C++) are accepted.

Special option --help

Each option has a description string. If on the command line, the --help option is specified, then help informations will be printed. User does not need to add this option. However, the user can add this option manually to suppress the default printing of help informations. The default --help is a boolean option.