1

I am trying to write my own validate function for program boost options. However, I am getting:

" terminate called after throwing an instance of 'boost::exception_detail::clone_impl >' what(): boost::bad_any_cast: failed conversion using boost::any_cast "

I saw similar posts even here on stackoverflow, but I cannot get that working... below is my code. Hmm I suppose, that somehow I have to use lexical_cast and write this casting by myself, but I failed...

In one of the header files I have:

enum class LogSeverityLevel : std::int8_t { E_LOG_TRACE = 0,
                                            E_LOG_DEBUG,
                                            E_LOG_INFO,
                                            E_LOG_WARN,
                                            E_LOG_ERROR};

And in my main.cpp file:

void validate(boost::any& v,
          const std::vector<std::string>& values,
          LogSeverityLevel*, int)
{
    // Make sure no previous assignment to 'a' was made.
    po::validators::check_first_occurrence(v);
    // Extract the first string from 'values'. If there is more than
    // one string, it's an error, and exception will be thrown.
    const std::string& s = po::validators::get_single_string(values);

    const std::string& s_capitalized = boost::to_upper_copy(s);

    if (s_capitalized== "ERROR") {
        v = boost::any(LogSeverityLevel::E_LOG_ERROR);
    } else if (s_capitalized == "WARN") {
        v = boost::any(LogSeverityLevel::E_LOG_WARN);
    } else if (s_capitalized == "INFO") {
        v = boost::any(LogSeverityLevel::E_LOG_INFO);
    } else if (s_capitalized == "DEBUG") {
        v = boost::any(LogSeverityLevel::E_LOG_DEBUG);
    } else if (s_capitalized == "TRACE") {
        v = boost::any(LogSeverityLevel::E_LOG_TRACE);
    } else {
        throw po::validation_error(po::validation_error::invalid_option_value);
    }
}

and then, later on in main.cpp:

    desc.add_options()
    ("help,h", "print this help")
    ("version,v", "show application version")
    ("log-level", po::value<std::string>()->default_value("DEBUG"), "set log level")
    ;

and then:

    if (vm.count("log-level")) {
        setLogSeverityLevel(vm["log-level"].as<LogSeverityLevel>());

I will be thankful for any advice ;>

user1703589
  • 41
  • 1
  • 5
  • If you make your sample self-contained (http://www.sscce.org/) you will find that you get more quality answers. I don't always have time to do the extra work. I have running sample on Coliru in 90% of my answers. – sehe Mar 20 '14 at 14:07

1 Answers1

0

Use the special option type instead of just string when you define your options:

desc.add_options()
("help,h", "print this help")
("version,v", "show application version")
("log-level", po::value<LogSeverityLevel>()
    ->default_value(LogSeverityLevel::E_LOG_DEBUG, "DEBUG"), "set log level")
;
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Thanks for your advice - but with your change I am not even able to compile the code... could be good to start, but i suppose it is still not enough, am i right? `/usr/include/boost/lexical_cast.hpp: In member function ‘bool boost::detail::lexical_stream – user1703589 Mar 20 '14 at 14:05
  • "am I right" - well , you tell me. I probably guessed the `default_value` specification wrong. Try without (or with "DEBUG" as the default value)? – sehe Mar 20 '14 at 14:06
  • i tried different combination and it looks that only `("log-level", po::value(), "set log level")` works. It is not bad, but I would be happy if I also got the default_value option working... `po::value()->default_value("DEBUG")` gives me `error: no matching function for call to ‘boost::program_options::typed_value::default_value(const char [6])’` – user1703589 Mar 20 '14 at 14:22
  • @user1703589 Use `po::value()->default_value(LogSeverityLevel::E_LOG_DEBUG, "DEBUG");` (alternatively specialize `lexical_cast<>` for your type) – sehe Mar 20 '14 at 14:32
  • Wow! no it works ;) thanks! it works but only on one of the platform I am writing for... on the other one it works only with ("log-level", po::value(), "set log level"). Otherwise I get: /usr/include/boost/lexical_cast.hpp: In instantiation of 'bool boost::detail::lexical_stream_limited_src::shr_using_base_class(InputStreamable&) [with InputStreamable' ... – user1703589 Mar 20 '14 at 14:49
  • Then check the differences between your platform (your code or the boost-library version/compiler flags). Otherwise, you can specialize `lexical_cast<>` like I mentioned – sehe Mar 20 '14 at 14:57