Как получить лучшие сообщения об ошибках в опциях программы Boost - PullRequest
9 голосов
/ 08 июня 2011

В приведенном ниже коде я использовал параметры программы для чтения параметров из командной строки или файла. Кроме того, параметры могут быть установлены программно во время выполнения через ConfigProxy :: setConfig

po::options_description desc("Allowed options");
desc.add_options()
    ...
    ("compression", po::value<int>(), "set compression level");

po::variables_map vm;

class ConfigProxy
{
     template< typename T>
     void setConfig( const std::string key, const T value ){
          ... // check if the key exists in variable map "vm"

          // key exists, set the value
          runtimeConfig[key] = po::variable_value( boost::any(value), false);
     }

     po::variable_value& operator[] (const std::string key) const{
          ...
          // if exists in runtimeConfig return the value in runtimeConfig
          // of type program_options::variable_value
          ...
          // else return value in variable map "vm"
     }

     std::map<std::string, boost::program_options::variable_value> runtimeConfig;
}

через ConfigProxy, значение параметра получается

if( vm.count("compression") ){
    int value = proxyConfig["compression"].as<int>();
    ...
}

Однако, если предоставленное пользователем значение параметра «сжатие» имеет значение , неправильный тип , например

configProxy.setConfig("compression", "12" );
...
int value = configProxy["compression"].as<int>(); // was set as string

тогда генерируется исключение

what():  boost::bad_any_cast: failed conversion using boost::any_cast

Исключение ясно показывает проблему приведения типа. Но сообщение кажется не очень полезным для пользователей, чтобы выяснить , какая опция отвечает за ошибку.

Есть ли лучший способ информировать пользователей об этом типе ошибки, вместо того, чтобы выдавать bad_any_cast исключение?

----- Редактировать --------------------------

Благодаря Люку Дантону и Тони я обнаружил, как в параметрах программы отображаются ошибки.

void validate(boost::any& v,
              const std::vector< std::basic_string<charT> >& xs,
              T*, long)
{
    validators::check_first_occurrence(v);
    std::basic_string<charT> s(validators::get_single_string(xs));
    try {
        v = any(lexical_cast<T>(s));
    }
    catch(const bad_lexical_cast&) {
        boost::throw_exception(invalid_option_value(s));
    }
}

Я думаю, что, реализовав логику, я смогу избавиться от исключения bad_any_cast.

Ответы [ 2 ]

4 голосов
/ 08 июня 2011

Вы пробовали это?

("compression", po::value<int>(), "set compression level");

Уведомление po::value<int>(). Здесь вы указываете, что соответствующее значение имеет тип int. Когда пользователь передает что-то, что Boost.ProgramOptions не может преобразовать в int, программа завершается ошибкой с сообщением об ошибке:

error: in option 'compression': invalid option value

В конце концов, это одна из ролей библиотеки.

Причина, по которой делать приходится делать vm["compression"].as<int>(), заключается в том, что тип compression указан в вызове функции (триплет в скобках), что-то в мире времени выполнения. Это не может влиять на тип возвращаемого значения vm["compression"], поэтому это должна быть эмуляция динамического типа. Отсюда исключение boost::any_cast_failed при запросе типа, который вы не указали.

2 голосов
/ 08 июня 2011

Не можете ли вы поставить это:

if( vm.count("compression") ){
    int value = vm["compression"].as<int>();
    ...
}

в блоке try catch, где вы перехватываете исключение bad_any_cast, генерируемое при форсировании, перехватывается и затем показывает сообщение вашему собственному пользователю, либо выбрасывая (retrow) новое исключение созданного вами типа, либо написав сообщение на std::cout, я думаю, многое зависит от вашего приложения.

так:

try {
    if( vm.count("compression") ){
        int value = vm["compression"].as<int>();
        ...
    }
}
catch(const boost::bad_any_cast& ex)
{
//rethrow exception of your own to show to the user or print msg to std::cout
}
...