Как решить "boost:: bad_any_cast: неудачное преобразование с использованием boost:: any_cast" при использовании опций форматирования?
//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;
}
Являются ли введенные значения некорректными?
Вот вывод gdb, кажется, проблема с литьем:
завершение вызова после вызова экземпляра "Повышение:: exception_detail:: clone_impl
" what(): boost:: bad_any_cast: неудачное преобразование с использованием 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();
возникает ошибка; Я пробовал std::string и строку с теми же результатами.
testboostpo -i 192.168.1.10 -p 5000
- это командная строка.
Я попробовал объявить типы, например:
config.add_options()
("IPAddress,i", po::value<std::string>(), "IP Address")
("Port,p", po::value<std::string>(), "Port");
но ошибка все же произошла.
Может ли это быть настоящей ошибкой?
Ответы
Ответ 1
Вы видите исключение boost::bad_any_cast
, выведенное из po::variables_map
, потому что две перегрузки аргумента const char*
po::options_description_easy_init::operator()
не указывают a po::value_semantic
, поэтому преобразование его в std::string
не будет работать. Если вы хотите преобразовать значение в std::string
, и оно требуется для вашего приложения, используйте семантическое значение 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;
}
Обратите внимание на добавленный блок catch, поскольку синтаксический анализ может (и будет, как вы заметили) отбрасывать исключения. Вот пример сеанса:
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$
Вот онлайн-демонстрация, демонстрирующая такое же поведение, любезно предоставленное COmpile LInk RUn (coliru).
Ответ 2
Вам нужно объявить ip-адрес и порт как строки при добавлении опций:
config.add_options()
("IPAddress,i", po::value<std::string>(), "IP Address")
("Port,p", po::value<std::string>(), "Port")
;
Ответ 3
Это же сообщение также может возникнуть, если вы неправильно обрабатываете необязательные аргументы.
Сэм должен найти необходимые аргументы и указать код OP - просто отметьте их. Для дополнительных входов учебник Boost PO дает нам шаблон для проверки наличия опциона перед его преобразованием:
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;
}
Моя проблема - я скопировал/вставил и забыл выровнять тест if с использованием!