[program_options] Best practices, esp. for multi-app-projects?

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
participants (1)
-
Carlos Franke