1

Stupid question (but I don't find anything on boost.org): how do I catch exceptions from boost::program_options? Invoking

#include <boost/program_options.hpp> #include <iostream> int main(int argc, char** argv){ bool opt; namespace bpo = boost::program_options; bpo::options_description options("Allowed options"); options.add_options() ("opt", bpo::bool_switch(&opt)); bpo::variables_map options_vm; try { bpo::store(bpo::parse_command_line(argc, argv, options), options_vm); bpo::notify(options_vm); } catch(const std::exception &e){ std::cerr << e.what() << std::endl; return 1; } return 0; } 

with any option but --opt yields

libc++abi: terminating due to uncaught exception of type boost::wrapexcept<boost::program_options::unknown_option>: unrecognised option '--optnsdf' 

Why doesn't catch(const std::exception &e) catch the exception? How do I properly catch catch(const boost::wrapexceptboost::program_options::unknown_option& e)is not intended, also because there can be other program options-related exceptions, such asboost::wrapexceptboost::program_options::invalid_command_line_syntax`, and probably others.

Is there any class hierarchy for boost program options exceptions available online?

9
  • 1
    Boost isn't inheriting std::exception. As for how, the error message tells you exactly what exception gets thrown. Commented Feb 6, 2024 at 16:24
  • If you don't care what you're catching, you can catch(...). Commented Feb 6, 2024 at 16:25
  • The bigger issue appears to be that you are attempting to use an option that you never added. Commented Feb 6, 2024 at 16:32
  • @sweenish What do you mean? It is standard behaviour that programs display a help message if one specifies invalid command line arguments. I want to provide the same behaviour. Commented Feb 6, 2024 at 16:33
  • 1
    Now we're getting close to duplicate territory: stackoverflow.com/questions/8136534/… Commented Feb 6, 2024 at 16:36

1 Answer 1

2

You can catch the base exception class program_options::error by reference:

Live On Coliru

#include <array> #include <iostream> #include <boost/program_options.hpp> namespace po = boost::program_options; int main() { std::array argv{"demo", "--oops", static_cast<char const*>(nullptr)}; po::options_description options("Allowed options"); bool opt; options.add_options()("opt", po::bool_switch(&opt)); po::variables_map vm; try { store(parse_command_line(argv.size() - 1, argv.data(), options), vm); notify(vm); } catch (po::error const& e) { std::cerr << e.what() << std::endl; options.print(std::cerr); return 1; } } 

Printing

unrecognised option '--oops' Allowed options: --opt 

Although there's no diagram there is a kind of error reference: https://www.boost.org/doc/libs/1_84_0/doc/html/program_options/reference.html#header.boost.program_options.errors_hpp

The individual types do mention purpose e.g.: "Base class for all errors in the library")

Sign up to request clarification or add additional context in comments.

3 Comments

The fact that this did not work on my machine (Mac with Homebrew llvm) brought me to the real issue: when linking with -L/usr/local/opt/llvm/lib/c++, your code fails. When linking without this (which libc++ am I linking to then?), then your (and my) code runs as expected. Do you know what's going on?
Addendum:" I have little knowledge of how linking works. Is it possible that libboost_program_options.a is built for one libc++, and then linking my program against another libc++ breaks inheritance?
@Bubaya Probably ODR violations (including conflicting RTTI records in different linked objects). There may be more instances of UB as a consequence, so check your build methods closely! Technically it's not "breaking inheritance", just UB

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.