web-dev-qa-db-fra.com

Arguments vectoriels dans les options du programme Boost

J'ai deux questions connexes:

  1. Quelle est la manière la plus simple de permettre le passage d'une série de valeurs, en utilisant les options du programme Boost? Mon objectif est d'éviter prog --opt 1 --opt 2 --opt 3 et avoir prog --opt 1 2 3 au lieu.

  2. Quelle est la façon la plus simple d'avoir une option qui prend exactement deux nombres, par ex. prog --opt 137 42?

(Je n'ai pas besoin de paramètres de programme "gratuits".)

47
Szabolcs

Pour la première partie, cela devrait fonctionner

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

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

La deuxième partie, nécessite un peu plus de travail. La fonction po::value renvoie un po::typed_value< T, charT > sur lequel vous devrez remplacer le comportement de plusieurs fonctions, comme suit

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;
   }
}

qui doit être accompagné de

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; }

Ensuite

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

devrait marcher. Je n'ai pas encore eu l'occasion de le tester, il contient donc probablement quelques bugs. Mais, au minimum, devrait vous donner une idée de ce dont vous avez besoin.

32
rcollyer

C'est une réponse tardive mais j'espère que cela aide quelqu'un. Vous pouvez facilement utiliser la même technique dans l'élément # 1, sauf que vous devez ajouter une autre validation sur le nombre d'éléments dans votre vecteur:

de l'exemple de rcollyer:

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
}
40
Bee