Vector arguments in Boost Program Options

C++BoostBoost Program-Options

C++ Problem Overview


I have two related questions:

  1. What is the simplest way to allow passing a series of values, using Boost Program Options? My aim is to avoid prog --opt 1 --opt 2 --opt 3 and have prog --opt 1 2 3 instead.

  2. What is the simplest way to have an option that takes exactly two numbers, e.g. prog --opt 137 42?

(I don't need any "free" program parameters.)

C++ Solutions


Solution 1 - C++

This is a late answer but I hope it helps someone. You could easily use the same technique in item #1, except you need to add another validation on the number of items in your vector:

from rcollyer's example:

namespace po = boost::program_options;
po::option_descriptions desc("");

desc.add_options()
 ("opt", po::value<std::vector<int> >()->multitoken(), "description");

po::variables_map vm;
po::store(po::parse_command_line(argc, argv, desc), vm);
po::notify(vm); 

vector<int> opts;
if (!vm["opt"].empty() && (opts = vm["opt"].as<vector<int> >()).size() == 2) {
  // good to go
}

Solution 2 - C++

For the first part, this should work

namespace po = boost::program_options;
po::option_descriptions desc("");

desc.add_options()
 ("opt", po::value<std::vector<int> >()->multitoken(), "description");

The second part, requires a bit more work. The function po::value returns a po::typed_value< T, charT > on which you'll have to override the behavior of several functions, as follows

template< typename T, typename charT = char >
class fixed_tokens_typed_value : public po::typed_value< T, charT > {
   unsigned _min, _max;

   typedef po::typed_value< T, charT > base;

 public:
   
   fixed_tokens_typed_value( T * t, unsigned min, unsigned max ) 
     : _min(min), _max(max), base( t ) {
       base::multitoken();
   }

   virtual multi_typed_value* min_tokens( unsigned min ) {
       _min = min;
       return *this;
   }
   unsigned min_tokens() const {return _min;}

   virtual multi_typed_value* max_tokens( unsigned max ) {
       _max = max;
       return *this;
   }
   unsigned max_tokens() const {return _max;}

   base* zero_tokens() {
       _min = _max = 0;
       base::zero_tokens();
       return *this;
   }
}

which needs to be accompanied by

template< typename T >
fixed_tokens_typed_value< T > 
fixed_tokens_value(unsigned min, unsigned max) {
    return fixed_tokens_typed_value< T >(0, min, max ); }

template< typename T >
fixed_tokens_typed_value< T > 
fixed_tokens_value(T * t, unsigned min, unsigned max) {
    fixed_tokens_typed_value< T >* r = new
                   fixed_tokens_typed_value< T >(t, min, max);
    return r; }

Then

desc.add_options()
 ("opt", po::fixed_tokens_value<std::vector<int> >(2,2), "description");

should work. I have not yet had a chance to test it, so it likely contains a few bugs. But, at a minimum, should give you an idea of what you need.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSzabolcsView Question on Stackoverflow
Solution 1 - C++BeeView Answer on Stackoverflow
Solution 2 - C++rcollyerView Answer on Stackoverflow