Как решить проблему: boost :: bad_any_cast: сбой конвертации с использованием boost :: any_cast & quot; при использовании опций программы повышения?

//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 и 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");

но ошибка все-таки произошла.

Может ли это быть подлинной ошибкой?

12

Решение

Вы видите boost::bad_any_cast исключение, выброшенное из po::variables_map потому что два const char* перегрузка аргумента po::options_description_easy_init::operator() не указывает 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).

13

Другие решения

Вам нужно объявить IP-адрес и порт как строки, когда вы добавляете опции:

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

Это же сообщение может также появиться, если вы неправильно обрабатываете необязательные аргументы.

Решение Сэма требует обязательных аргументов, а код ОП предлагает обязательные — просто отметьте их как обязательные. Для дополнительных входов пособие по ускорению ПО дает нам шаблон для проверки существования опции перед ее преобразованием:

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 с использованием!

2

Не обязательно та же проблема, что и у этого парня, но вот что-то, что застало меня:

Если вы поместите ваш тип в анонимное пространство имен, будут два класса с одинаковыми именами, но разными экземплярами, и приведение не будет выполнено. Например:

a.hpp:

namespace {
class MyClass {...};
}

b.cpp:

#include "a.hpp"cli_options.add_options()("test", po::value<MyClass>(), "test desc");

c.cpp:

#include "a.hpp" // THIS WILL MAKE A DIFFERENT "MyClass"vm["test"].as<MyClass>();  // Fails at runtime.

Это не удается, потому что MyClass в b.cpp и тот, в c.cpp не тот же класс. Из-за анонимного пространства имен.

Удаление анонимного пространства имен решает проблему.

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector