2011-11-17 17 views
36

Tengo dos preguntas relacionadas:argumentos vector en Boost opciones de programa

  1. Cuál es la forma más simple para permitir pasar una serie de valores, utilizando Boost opciones de programa? Mi objetivo es evitar prog --opt 1 --opt 2 --opt 3 y tener prog --opt 1 2 3 en su lugar.

  2. ¿Cuál es la forma más simple de tener una opción que toma exactamente dos números, p. prog --opt 137 42?

(no necesito ningún parámetro del programa "libres".)

Respuesta

29

Para la primera parte, esto debería funcionar

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

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

La segunda parte, requiere un poco más de trabajo. La función devuelve un po::valuepo::typed_value< T, charT > en la que tendrá que reemplazar el comportamiento de varias funciones, como sigue

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

que debe ir acompañado 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; } 

Entonces

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

Deberia trabajar. Todavía no he tenido la oportunidad de probarlo, por lo que es probable que contenga algunos errores. Pero, como mínimo, debe darle una idea de lo que necesita.

+0

@Szabolcs, un punto interesante con este El código es que requeriría el uso de vectores por defecto. De lo contrario, ¿cómo vas a almacenar los valores? Por lo tanto, creo que 'po :: typed_value < T, charT >' debe cambiarse a 'po :: typed_value , charT>'. – rcollyer

+0

¿Esto también funciona para 'std :: array's o' std :: lists's en lugar de vectores? – einpoklum

+0

@einpoklum No veo por qué no. Pero, creo que 'std :: array' será un poco complicado ya que no sé qué se usa para insertar en el contenedor, aunque es probable que sea configurable, y su tamaño fijo requerirá cierta adaptación. Por el contrario, 'std :: list' no tiene esas limitaciones, por lo que sospecho que podría usarlo como reemplazo. – rcollyer

37

Esta es una respuesta tardía, pero espero que ayude a alguien. Se podría utilizar simplemente la misma técnica en el punto 1, excepto que se debe añadir otra validación del número de artículos en su vector:

del ejemplo 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 
} 
+0

+1 - Para su información rápida, falta un espacio en la tercera línea de la línea de la plantilla desde la parte inferior. – Hazok

+0

Lo arreglé gracias. Parece que el compilador de VC 10 no es sensible a este problema porque no recibí un error al probarlo en el formato original. – Bee

+0

Debería haberlo pensado. +1 – rcollyer

Cuestiones relacionadas