2012-01-11 27 views

Respuesta

1

He repasado la documentación de Boost.Program_options, y no me resulta obvio si puede hacerlo. Me da la impresión de que a la biblioteca le preocupa principalmente el al analizar la línea de comandos, sin validarlo. Es posible que pueda resolver algo con un custom validator, pero eso implica arrojar excepciones cuando obtiene entradas incorrectas (lo que puede ser un error más grave del que desea). Creo que esa característica está más orientada a asegurarte de que realmente tienes una cuerda, no es que sea "gato" o "perro".

La solución más simple que puedo pensar es dejar que la biblioteca de analizar la línea de comandos como de costumbre, a continuación, añadir su propio código más tarde para verificar --arg se estableció en cat o dog. A continuación, puede imprimir un error y salir, volver a un valor predeterminado adecuado o lo que desee.

17

Puede usar la función custom validator. Defina un tipo distinto para su opción, y luego sobrecargue la función validate en ese tipo.

struct catdog { 
    catdog(std::string const& val): 
    value(val) 
    { } 
    std::string value; 
}; 

void validate(boost::any& v, 
       std::vector<std::string> const& values, 
       catdog* /* target_type */, 
       int) 
{ 
    using namespace boost::program_options; 

    // Make sure no previous assignment to 'v' was made. 
    validators::check_first_occurrence(v); 

    // Extract the first string from 'values'. If there is more than 
    // one string, it's an error, and exception will be thrown. 
    std::string const& s = validators::get_single_string(values); 

    if (s == "cat" || s == "dog") { 
    v = boost::any(catdog(s)); 
    } else { 
    throw validation_error(validation_error::invalid_option_value); 
    } 
} 

Las excepciones producidas a partir de ese código no son diferentes de las excepciones producidas por cualquier otro valor de opción no válida, por lo que ya deben estar preparados para manejarlos.

Usar el tipo de opción especial en lugar de sólo string cuando defina sus opciones:

desc.add_options() 
    ("help", "produce help message") 
    ("arg", po::value<catdog>(), "set animal type") 
; 

He compuesto una live example demonstrating use of this code.

+0

En este ejemplo se ve muy similar a la prevista en el [documentación oficial] (http://www.boost.org/doc/libs/1_55_0/doc/html/program_options/howto.html#idp163429032) . Sin embargo, es necesario implementar una función de operador de extracción demasiado 'std :: istream operador & >> (std :: istream y en, catdog y cd)' '{ ' ' volver en >> in.value;' ' } ' ' – russoue

+1

Sí, @Russoue, mi código se ha adaptado directamente de la documentación, a la que me he vinculado anteriormente. Sin embargo, no sé por qué crees que el código necesita extracción de flujo. He incluido un ejemplo de trabajo que falsifica su reclamo. La documentación usa 'lexical_cast' para convertir de la cadena de entrada al tipo de datos deseado, y si desea utilizar esa misma técnica, entonces deberá implementar' operator >> '. Mi ejemplo usa construcción directa, sin embargo. * Cómo * para crear el tipo personalizado de una cadena está más allá del alcance de esta pregunta. –

5

Un enfoque muy simple es tener "animal" como una cadena normal y después de notificarlo probar y tirar si es necesario.

if (vm.count("animal") && (!(animal == "cat" || animal == "dog"))) 
     throw po::validation_error(po::validation_error::invalid_option_value, "animal"); 
+0

¿No es esto exactamente lo que sugirió Michael? –

+0

@RobKennedy Excepto que Michael dijo "Esto es lo que puedes hacer", mientras que jorgen dijo "Esto es lo que puedes hacer, y así es como se vería" –

Cuestiones relacionadas