1

I would like to introduce a hierarchy of my custom exception classes, derived both from boost::exception and std::runtime_error so that what() returns something meaningful.

So far I had no luck:

#include <iostream>
#include <stdexcept>

#include <boost/exception/all.hpp>

typedef boost::error_info<struct tag_foo_info, unsigned long> foo_info;

struct foo_error : virtual boost::exception, virtual std::runtime_error
{
  explicit foo_error(const char *const what)
    : std::runtime_error(what)
  { }
};

static void foo()
{
  BOOST_THROW_EXCEPTION(foo_error("foo error") << foo_info(100500));
}

int main(int argc, char *argv[])
{
  try
  {
    foo();
  }
  catch (const std::exception& e)
  {
    std::cerr << boost::diagnostic_information(e);
    return 1;
  }

  return 0;
}

just keeps complaining that there are no appropriate default constructor available for std::runtime_error.

The closest I can get is to throw an actual std::runtime_error using

BOOST_THROW_EXCEPTION(boost::enable_error_info(std::runtime_error("foo error")) << foo_info(100500)))

but that's not really what I want. Basically, I want an exception class being catchable by catch (const std::exception& e), catch (const std::runtime_error& e), catch (const boost::exception& e) and catch (const foo_error& e). Is that possible? Thank you in advance.

2 Answers 2

4

You need public inheritance

struct Exception : public boost::exception, public std::runtime_error
{
    Exception()
    :   std::runtime_error("Hello World")
    {}
};

int main()
{
    try {
        try {
            throw Exception();
        }
        catch(const std::runtime_error&) {
            std::cout << "std::runtime_error" << std::endl;
            throw;
        }
    }
    catch(const boost::exception&) {
        std::cout << "boost::exceptionr" << std::endl;
    }
    return 0;
}

Your code will work if you replace the two virtual:

Throw in function void foo()
Dynamic exception type: boost::exception_detail::clone_impl<foo_error>
std::exception::what: foo error
[tag_foo_info*] = 100500

The boost exception library has a class deriving from your exception:

// Curiously recurring template pattern (exception.hpp:419:20)
class clone_impl: public Exception, public clone_base;

Due to virtual inheritance the most derived class is responsible to initialize the base classes (clone_impl does not)

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

3 Comments

Could you please explain why and how does this work? My brain hurts.
I mean, you just replaced virtual with public. What is the difference? Why does it work now? What are the consequences? I'm struggling to understand.
The boost exception library has a class deriving from your exception.
-1

std::runtime_error already inherits from std::exception. So you only need inherit std::runtime_error and you'll get both.

UPDATE: I meant inheriting only std::runtime_error. What if you try this:

#include <iostream>
#include <stdexcept>

struct foo_error : public std::runtime_error
{
    explicit foo_error(const char *const what)
        : std::runtime_error(what)
    { }
};

static void foo()
{
    throw foo_error("foo error");
}

int main(int argc, char *argv[])
{
    try
    {
        foo();
    }
    catch (const std::exception& e)
    {
        std::cerr << boost::diagnostic_information(e);
        return 1;
    }
    return 0;
}

left out the boost stuff for simplicity.

2 Comments

I'm in fact inhereting from std::runtime_error on the example posted, but it won't compile. What am I doing wrong?
This answer seems to confuse std::exception and boost::exception. They're not the same things. Inheriting std::runtime_error does not automatically inherit from boost::exception.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.