c++ boost types casting boost-program-options

c++ - ¿Cómo resolver "boost:: bad_any_cast: conversión fallida usando boost:: any_cast" cuando se usan las opciones del programa boost?



types casting (3)

Debe declarar la dirección IP y el puerto como cadenas cuando agrega las opciones:

config.add_options() ("IPAddress,i", po::value<std::string>(), "IP Address") ("Port,p", po::value<std::string>(), "Port") ;

//Using boost program options to read command line and config file data #include <boost/program_options.hpp> using namespace std; using namespace boost; namespace po = boost::program_options; int main (int argc, char *argv[]) { po::options_description config("Configuration"); config.add_options() ("IPAddress,i","IP Address") ("Port,p","Port") ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, config),vm); po::notify(vm); cout << "Values/n"; string address = (vm["IPAddress"].as<std::string >()).c_str(); string port = (vm["Port"].as<std::string>()).c_str(); cout << (vm["IPAddress"].as< string >()).c_str(); cout << " " << (vm["Port"].as<string>()).c_str(); return 0; }

¿Los valores ingresados ​​de alguna manera no son imprimibles?

Aquí está la salida de gdb, parece ser problema de lanzamiento:

finalizar llamado después de lanzar una instancia de ''boost :: exception_detail :: clone_impl

''what (): boost :: bad_any_cast: conversión fallida con boost :: any_cast

Program received signal SIGABRT, Aborted. 0x0000003afd835935 in raise () from /lib64/libc.so.6

string address = (vm["IPAddress"].as<std::string >()).c_str();

es donde ocurre el error; He intentado std :: string y string con los mismos resultados.

testboostpo -i 192.168.1.10 -p 5000

es la linea de comando

Intenté declarar los tipos, así:

config.add_options() ("IPAddress,i", po::value<std::string>(), "IP Address") ("Port,p", po::value<std::string>(), "Port");

pero el error todavía ocurrió.

¿Podría ser esto un error genuino?


Verá la excepción boost::bad_any_cast lanzada desde el po::variables_map porque la sobrecarga del argumento dos const char* de po::options_description_easy_init::operator() no especifica un tipo po::value_semantic , por lo que lo convierte a std::string no funcionará Si desea convertir el valor en std::string , y es necesario para su aplicación, use la semántica del valor required() .

#include <boost/program_options.hpp> namespace po = boost::program_options; int main (int argc, char *argv[]) { po::options_description config("Configuration"); config.add_options() ("IPAddress,i", po::value<std::string>()->required(), "IP Address") ("Port,p", po::value<std::string>()->required(), "Port") ; try { po::variables_map vm; po::store(po::parse_command_line(argc, argv, config),vm); po::notify(vm); std::cout << "Values" << std::endl; const std::string address = vm["IPAddress"].as<std::string>(); const std::string port = vm["Port"].as<std::string>(); std::cout << "address: " << address << std::endl; std::cout << "port: " << port << std::endl; } catch ( const std::exception& e ) { std::cerr << e.what() << std::endl; return 1; } return 0; }

Tenga en cuenta el bloque catch añadido ya que el análisis puede (y lo hará, como habrá notado) lanzar excepciones. Aquí hay una sesión de muestra:

samm$ ./a.out the option ''--IPAddress'' is required but missing samm$ ./a.out --IPAddress 127.0.0.1 the option ''--Port'' is required but missing samm$ ./a.out --IPAddress 127.0.0.1 --Port 5000 Values address: 127.0.0.1 port: 5000 samm$

Aquí hay una demostración en línea que muestra el mismo comportamiento, cortesía de COmpile LInk RUn (coliru).


Este mismo mensaje también puede ocurrir si no está manejando los argumentos opcionales correctamente.

Las soluciones de Sam requieren argumentos y el código de OP sugiere que es necesario, simplemente márcalos obligatorios. Para entradas opcionales, el tutorial de Boost PO nos proporciona una plantilla para verificar si la opción existe antes de convertirla:

if(vm.count("address")) { const std::string address = vm["IPAddress"].as<std::string>(); std::cout << "address: " << address << std::endl; } if(vm.count("port")) const std::string port = vm["Port"].as<std::string>(); std::cout << "port: " << port << std::endl; }

Mi problema: ¡copié / pegué y olvidé alinear la prueba si con el uso!