2013-03-20 4 views
11
//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; 

} 

I valori immessi sono in qualche modo non stampabili?Come risolvere "boost :: bad_any_cast: conversione fallita usando boost :: any_cast" quando si usano le opzioni del programma boost?

Ecco uscita gdb, sembra essere essere gettato problema:

Termina chiamata dopo aver lanciato un'istanza di 'boost :: :: exception_detail clone_impl

' cosa(): boost :: bad_any_cast: fallito conversione utilizzando 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(); 

è dove si verifica l'errore; Ho provato std :: string e string con gli stessi risultati.

testboostpo -i 192.168.1.10 -p 5000 

è la riga di comando.

Ho provato dichiarare i tipi, in questo modo:

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

ma l'errore ancora verificato.

Potrebbe essere un bug reale?

+0

Si prega di inviare gli argomenti della riga di comando che si sta passando al programma. – Praetorian

+0

nit: è superfluo convertire il risultato da 'std :: string :: c_str()' a 'std :: string' –

risposta

13

vedete l'eccezione boost::bad_any_cast gettato dalla po::variables_map perché il sovraccarico di due const char* argomento po::options_description_easy_init::operator() non specifica un Tipo po::value_semantic, quindi la conversione in un std::string non funzionerà. Se si desidera convertire il valore in std::string ed è necessario per l'applicazione, utilizzare la semantica valore 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; 
} 

Nota il blocco catch aggiunto poiché l'analisi può (e, come avrai notato) generare eccezioni. Ecco un esempio di sessione:

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$ 

Ecco un online demo che mostra lo stesso comportamento, per gentile concessione di compilare collegamento Esegui (coliru).

4

è necessario dichiarare l'indirizzo IP e la porta come stringhe quando si aggiungono le opzioni:

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

parzialmente corretto, un'eccezione' boost :: bad_any_cast' [verrà comunque generata] (http : //coliru.stacked-crooked.com/view? id = f50049b76d804061b926500aa6953033-57c67fe4b82106f02cd504259a9a9be3) quando si lancia un'opzione che non è presente in 'po :: variables_map' in un' std :: string'. –

2

Questo stesso messaggio può verificarsi anche se non si gestiscono correttamente argomenti opzionali.

I chiodi per soluzione Sam hanno richiesto argomenti e il codice OP suggerisce necessario - basta contrassegnarli richiesti. Per gli ingressi opzionali, the Boost PO tutorial ci dà un modello per verificare se esiste la possibilità prima di convertirlo:

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

Il mio problema - avevo copiato/incollato e dimenticato per allineare il caso di test con l'uso!