Boost logo

Boost Users :

Subject: [Boost-users] [program_options] copy option_description from one options_description to another
From: Ghyslain Leclerc (ghleclerc_at_[hidden])
Date: 2013-06-28 14:20:14


Hello.

First post here. Not a programmer by trade, but a medical physicist, so my apologies
if my question seems too much of a newbie question. And hopefully, my programing
jargon won’t be too bad.

I have searched on Google and played with my code all day yesterday and I have not
found the answer to my problem, so I thought I would try the mailing list.

We have a number of small command line utilities (approx. 10) that we are developing
for our clinic. We want to try and make a base class that would contain all our usual
program options in it and would allow customization for our various little programs.

Thus, I need to store a options_description object with our usual options and a
function in the class to add options to the stored object.

That way, the interfaces would be more homogeneous and we would not need to recode
all the logic of option handling for every application and maintain them all. Simply create
a derived class and add a few options_description to it. Then use that class for our application.

My first approach was to store a options_description object directly, but I can't seem
to assign to it. So if I want to reset the object to a completely new one, for instance
in a special case where the usual options don't make any sense, I run into problems.

I switched to holding a pointer to it (tr1 shared_ptr). That allows me to easily change
the object all together if I need to.

In either case (pointer or object), my actual problem comes when I want to add options
to a options_description. I can easily use the add function :
  myOptionsDescriptionObject.add( theOtherOptionsDescriptionObject );

but that adds empty lines in the output format and creates artificial grouping of options,
which I would like to avoid if possible. That being said, given the current state of our code,
I will implement this version now as this is the "best" solution that works.

The way I am trying to get around that is to extract for each option_description
contained in the options_description object the name, the description and the
value_semantic and then use these three extracted values with the add_options()
function like so:
  muOptionsDescriptionObject.add_options()( other.options()->name(),
                                            other.options()->semantic().get(),
                                            other.options()->description() );

Works perfectly for name and description, but fails for value_semantic. It compiles, but
generates a "The program has unexpectedly finished." message. My hypothesis for what is
happening is that I am using the .get() to extract the raw pointer from the shared_ptr
returned, but the shared_ptr somehow deletes the memory and my pointer becomes invalid.

Here is a short version of what I came up with. The problem is probably in the implementation
of the function addGenOpts().

Can anybody help with this? Sorry if this is a ridiculous question or if my post makes no sense.
English is not my first language.

In advance, thanks.
Ghyslain

---------------------------

namespace bpo = boost::program_options;

class BaseCli
{
public:
   BaseCli();
   virtual ~BaseCli() {}

   void parseCmdLineOpts( int argc, const char* argv[] );
   void parseCfgFileOpts();
   void run();

   bool checkPresent( const std::string& optionStrg );

   const bpo::options_description& genOpts( );

   void addGenOpts( const bpo::options_description& opts );

   void setGenOpts( const bpo::options_description& opts );

private:
   bpo::variables_map optionsMap_;

   std::tr1::shared_ptr< bpo::options_description > genOpts_;

   //virtual void runNoInteraction_() = 0;
   //virtual void runWithInteraction_() = 0;
};

void BaseCli::addGenOpts( const bpo::options_description& opts )
{
   using std::vector;
   using std::string;

   // Loop through every option in opts
   for( auto optIter = opts.options().begin(); optIter != opts.options().end(); ++optIter )
   {
      
      ... CODE REMOVED TO SAVE SPACE ...
      ... SIMPLE STRING MANIPULATION STUFF ...

      // Combine names into program_options option string
      string combinedName( longName );
      if ( !shortName.empty() )
      { combinedName += string( "," ) + shortName; }

      genOpts_->add_options()( combinedName.c_str(),
                               (*optIter)->semantic().get(),
                               (*optIter)->description().c_str() );
   }
}

---------------------------


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net