$include_dir="/home/hyper-archives/boost-users/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-users] [program_options] Best practices, esp. for multi-app-projects?
From: Carlos Franke (carlos_franke_at_[hidden])
Date: 2011-08-02 16:27:33
I am wondering if there is a recommended way how the  
boost::program_options library should be integrated in a (relatively)  
complex project. To be more specific, these are my situation and my  
requirements:
  â A C++ project consisting of several applications, which are to  
share many, but not all options.
  â The interface to the options used in each app's code should be as  
boost-unspecific (i. e. abstract) as possible, so that I could later  
switch to another option library without having to edit much more than  
one file.
  â The option data should be somehow encapsulated.
After pondering on this task for quite some time, I came up with this:
  â A single header file "options.h" shared by all the applications,  
providing a function
    read_options(int argc, char* argv[], const po::options_description&  
local_options = 0) ,
which  scans the command line and the usual configuration files* for  
the common options (which are defined in the same header file, of  
course) as well asoptional app-specific options, and saves them (next  
paragraph).
*(There is of course the problem of each app's name being part of its  
config-file's name. I found a solution for this, but I am not sure if  
it is relevant here. Or is it?)
  â Regarding the encapsulation, I found any kind of class or struct  
containing the options (possibly with get and set methods) unsuitable  
or overkill, as I would have to deal with instantiation and possible  
problems of multiple instantiation (singleton?). Also, I did not feel  
the need for the security provided by get and set methods. So what I  
did is: put all option variables in one namespace, like this:
    namespace options
    {
       int option1;
       std::string option2;
       ///...
    }
A namespace has the further great advantage of being extendable after  
creation. Programme-specific options can be added easily.
So in the end, in each programme I only have to do:
    //optional: define local options
    namespace options
    { /* . . . */ }
    po::options_description my_options
    /* . . . */ ;
    //read and save options:
    options::read_options(argc, argv, my_options)
    //from now on access the options' values by
    //options::option1;
As I see it, this approach has only two drawbacks:
  â In each programme's code I have to deal with options twice: 1)  
declare the storage variables in the options namespace (globally); 2)  
declare local options_description and call read_options (in the main  
function).
  â There is no way to tell if the option variables are in a valid  
state, unless one is sure that read_options has been called and has set  
all values (at least to valid default values).
I am inclined to tolerate the first issue and resolve the second by:
  â not using "default_value" in any po::options_description
  â instead intializing the option variables with their default values.
That way, at any time each option variable either stores its default  
value or the assigned to it from the command line or a configuration  
file.
Oh my, that ended up much longer than I expected. Those of you who read  
this far: What are your thoughts about using boost::program_options in  
general and about my particular approach?
Regards!
Carlos Franke