Reputation: 608
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 catch
able 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.
Upvotes: 1
Views: 1289
Reputation:
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)
Upvotes: 4
Reputation: 89
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.
Upvotes: -1