Calling method from own exception class catched by its base class - c++

I have two functions a() and b(), which are having own exception classes (consecutively a_exc and b_exc) that inherit from std::logic_error.
void a() { (...) throw a_exc(some_val) }
void b() { (...) throw b_exc(some_val) }
class a_exc : public std::logic_error
{
private:
int foo;
public:
a_exc(int val, const std::string& what_msg="Msg.")
: std::logic_error(what_msg), foo(val) {}
void show() { //show foo }
}
class b_exc : public std::logic_error
{
private:
std::string bar;
public:
a_exc(std::string val, const std::string& what_msg="Msg.")
: std::logic_error(what_msg), bar(val) {}
void show() { //show bar }
}
Let's say I have following part of code:
try {
a();
b();
}
catch (const std::logic_error& e)
{
e.what();
// e.show();
}
catch (const std::logic_error& e) catches both a_exc and b_exc. Of course this block cannot use e.show(), because catched obj is std::logic_error.
And here's my problem. I wonder if there is any chance to call show() method in std::logic_error catch block when catched exception was a_exc or b_exc. I know, calling show() is possible if I create separate catch blocks for a_exc and b_exc, but I want to call this method with using just one catch block. Is it possible?

You can, provided that show() is a const member function:
catch (const std::logic_error& e)
{
e.what();
if(const a_exc* a = dynamic_cast<const a_exc*>(&e))
a->show();
else if(const b_exc* b = dynamic_cast<const b_exc*>(&e))
b->show();
}
See it Live on Coliru. Though, it's usually a bad idea to call other functions that may throw in your catch exception handler.

Some thoughts on design.
Querying the type of exception within the catch block is logically no different to simply providing two catch blocks.
To be clear:
catch(X& x)
{
if (dynamic_cast<Y*>(&x)) {
// it's a Y
}
if (dynamic_cast<Z*>(&z)) {
// it's a Z
}
else {
// it's an X
}
}
is logically the same as:
catch(Y& t)
{
// it's a Y
}
catch(Z& z)
{
// it's a Z
}
catch(X& x)
{
// it's an X
}
Except that the second is clearer, more maintainable and resistant to inadvertent slicing on a subsequent copy.
The first is using "code to find code", which is always a maintenance disaster waiting to happen.
Your question raises more questions of its own:
Are a_exc and b_exc two kinds of the same error? If so, this argues for a polymorphic base class, which you can catch in preference to std::logic_error
Do you really need the show() method? Can you simply build the what string in the constructor, and pass this string to the constructor of std::logic_error? If this is at all possible, it is the route I would recommend. The moment you start adding special interfaces to exceptions, you pollute your entire code base with the necessity of knowing about this interface. If you're writing a library, you've now polluted every application that uses your library.
Assuming you do need show, and a_exc and b_exc really are two kinds of the same error, we can still avoid polymorphism. Perhaps we can shore the 'show' message as a string, and build it in the constructor. Now it's just data. No fuss, no complication.
(complete) example using polymorphic base class (a_exc an b_exc are kinds of the same thing)
#include <stdexcept>
#include <string>
struct showable_logic_error : std::logic_error
{
using std::logic_error::logic_error;
virtual void show() const = 0;
};
class a_exc : public showable_logic_error
{
private:
int foo;
public:
a_exc(int val, const std::string& what_msg="Msg.")
: showable_logic_error(what_msg)
, foo(val)
{}
void show() const override
{
//show foo
}
};
class b_exc : public showable_logic_error
{
private:
std::string bar;
public:
b_exc(std::string val, const std::string& what_msg="Msg.")
: showable_logic_error(what_msg)
, bar(val)
{}
void show() const override
{ //show bar
}
};
void a() { throw a_exc(1); }
void b() { throw b_exc("b"); }
int main()
{
try
{
a();
}
catch(showable_logic_error const& e)
{
e.show();
}
}
complete example in which no polymorphism is required:
#include <stdexcept>
#include <string>
#include <sstream>
struct message_builder
{
template<class T>
static std::string build_what(const std::string& whatstr, T&& info)
{
std::ostringstream ss;
ss << whatstr << " : " << info;
return ss.str();
}
};
class a_exc
: public std::logic_error
, private message_builder
{
public:
a_exc(int val, const std::string& what_msg="Msg.")
: std::logic_error(build_what(what_msg, val))
{}
};
class b_exc
: public std::logic_error
, private message_builder
{
private:
std::string bar;
public:
b_exc(std::string val, const std::string& what_msg="Msg.")
: std::logic_error(build_what(what_msg, std::move(val)))
, bar(val)
{}
};
void a() { throw a_exc(1); }
void b() { throw b_exc("b"); }
int main()
{
try
{
a();
}
catch(std::logic_error const& e)
{
e.show();
}
}

You should consider creating a derived type:
struct show_exc : public std::logic_error
{
virtual void show() = 0;
};
class a_exc : public show_exc
{
int foo_;
public:
virtual void show() override { /*...*/ };
};
and then use a distinguishing catch:
catch (const show_exc& e) {
// ..
}
catch (const std::logic_error& e) {
// ..
}

Related

Can one exception trigger multiple catch blocks? [duplicate]

Suppose the following example. There are classes A-C derived from std::exception:
#include <exception>
#include <string>
#include <iostream>
class A : public std::exception {
std::string a_text;
public:
A(const std::string & a_text_) : a_text(a_text_) {}
virtual ~A() throw() { }
};
class B : public A {
const std::string b_text;
public:
B(const std::string &a_text_, const std::string & b_text_) : A(a_text_), b_text(b_text_) {}
virtual ~B() throw() {}
};
template <typename T>
class C : public B {
T x;
public:
C(const std::string & a_text_, const std::string & b_text_, const T x_) :
B (b_text_, a_text_), x(x_) { }
virtual ~C() throw() {};
};
So far I have been convinced that generalizing pattern catches the exception of the derived class in multiple blocks.
int main() {
try {
throw C<double>("a", "b", 10);
}
catch (C<double> &c1) {
std::cout << " C";
}
catch (B &b1) {
std::cout << " B";
}
}
Unfortunately, the second block referring to B is skipped. Where is the problem? Thanks for your help.
Only the first catch block that matches is going to execute. You can re-throw the existing exception with the "throw;" statement but I am not sure if that will continue the search at the next catch block or only in a outer try-catch.

C++, catch user-defined exceptions in multiple blocks

Suppose the following example. There are classes A-C derived from std::exception:
#include <exception>
#include <string>
#include <iostream>
class A : public std::exception {
std::string a_text;
public:
A(const std::string & a_text_) : a_text(a_text_) {}
virtual ~A() throw() { }
};
class B : public A {
const std::string b_text;
public:
B(const std::string &a_text_, const std::string & b_text_) : A(a_text_), b_text(b_text_) {}
virtual ~B() throw() {}
};
template <typename T>
class C : public B {
T x;
public:
C(const std::string & a_text_, const std::string & b_text_, const T x_) :
B (b_text_, a_text_), x(x_) { }
virtual ~C() throw() {};
};
So far I have been convinced that generalizing pattern catches the exception of the derived class in multiple blocks.
int main() {
try {
throw C<double>("a", "b", 10);
}
catch (C<double> &c1) {
std::cout << " C";
}
catch (B &b1) {
std::cout << " B";
}
}
Unfortunately, the second block referring to B is skipped. Where is the problem? Thanks for your help.
Only the first catch block that matches is going to execute. You can re-throw the existing exception with the "throw;" statement but I am not sure if that will continue the search at the next catch block or only in a outer try-catch.

What is the proper way to create an exception hierarchy?

I understand that to properly catch exceptions using multiple inheritance I need to use virtual inheritance.
I'm not necessarily advocating the controversial use of multiple inheritance, but I do not want to design systems that make its usage impossible. Please do not distract from this question to advocate or attack the use of multiple inheritance.
So let's say I have the following base exception type:
class BaseException : public virtual std::exception {
public:
explicit BaseException(std::string msg)
: msg_storage(std::make_shared<std::string>(std::move(msg))) { }
virtual const char* what() const noexcept { return msg_storage->c_str(); }
private:
// shared_ptr to make copy constructor noexcept.
std::shared_ptr<std::string> msg_storage;
};
What is the proper way to create an exception hierarchy from BaseException?
My problem lies with constructing the exception types. Ideally every exception just constructs its parent, but this is impossible due to virtual inheritance. One solution would be to construct every parent up the chain:
struct A : public virtual BaseException {
explicit A(const std::string& msg) : BaseException(msg) { }
};
struct B : public virtual A {
explicit B(const std::string& msg, int code)
: BaseException(msg), A(msg), code_(code) { }
virtual int code() const { return code_; }
private:
int code_;
};
struct C : public virtual B {
explicit C(const std::string& msg, int code)
: BaseException(msg), A(msg), B(msg, code) { }
};
But this seems very repetitive and error-prone. Furthermore, this makes it impossible for constructors of exception types to add/change information passed in by their children before passing through to their respective parents.
I have found a reasonable solution that's not broken as far as I can see. It uses a slightly modified base exception type:
struct BaseException : virtual std::exception {
explicit BaseException(std::string msg)
: msg_storage(std::make_shared<std::string>(std::move(msg))) { }
virtual const char* what() const noexcept { return msg_storage->c_str(); }
protected:
BaseException();
private:
std::shared_ptr<std::string> msg_storage;
};
Then the rules are:
Every exception inherits publicly and virtually from its parent exceptions.
Every exception declares a protected default constructor and defines a protected constructor initializing all data members.
Every exception that is supposed to be Constructible defines a public constructor that directly calls the constructors defined in 2 for every ancestor.
All copy constructors should be noexcept.
An example hierarchy using this:
// A regular derived exception.
struct RuntimeError : virtual BaseException {
RuntimeError(std::string msg) : BaseException(std::move(msg)) { }
protected: RuntimeError() { }
};
// Derived exception with data member.
struct OSError : virtual RuntimeError {
OSError(std::string msg, int e) : BaseException(std::move(msg)), e(e) { }
virtual int error_code() const noexcept { return e; }
protected:
OSError();
OSError(int e) : e(e) { }
private:
int e;
};
// Non-constructible exception type.
struct FatalError : virtual RuntimeError {
protected: FatalError() { }
};
// A composed exception type.
struct FatalOSError : virtual FatalError, virtual OSError {
FatalOSError(std::string msg, int e)
: BaseException(std::move(msg)), OSError(e) { }
protected: FatalOSError() { }
};

Inherit custom exception class from both boost::exception and std::runtime_error

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.
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)
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.

What's the simplest way to satisfy a pure abstract method with methods from other base classes

Edit: Per some comments, by simple I mean a) less code, b) easy to maintain, and c) hard to get wrong.
Edit #2: Also, using containment instead of private inheritance is not objectionable if it does indeed simplify the implementation of InterfaceImpl.
Currently, the only way I know to do this is to have the implementer define the abstract method and delegate the call to the target base type's method. Example:
#include <iostream>
#include <memory>
class Interface
{
public:
virtual void method1() = 0;
virtual void method2(int x) = 0;
};
class MethodOneImpl
{
private:
void method1(int x)
{ std::cout << "MethodOneImpl::method1() " << x << std::endl; }
public:
void method1() { method1(0); }
};
class MethodTwoImpl
{
public:
void myFunc(int x)
{ std::cout << "MethodTwoImpl::myFunc(x)" << x << std::endl; }
};
class InterfaceImpl : public Interface
, private MethodOneImpl
, private MethodTwoImpl
{
public:
virtual void method1() { MethodOneImpl::method1(); }
virtual void method2(int x) { MethodTwoImpl::myFunc(x); }
};
int main()
{
std::unique_ptr<Interface> inf;
inf.reset(new InterfaceImpl);
inf->method1();
inf->method2(0);
// This should be disallowed!
// std::unique_ptr<MethodOneImpl> moi;
// moi.reset(new InterfaceImpl);
}
At first, I thought that perhaps this might solve the problem:
class InterfaceImpl : public Interface
, private MethodOneImpl
, private MethodTwoImpl
{
public:
using MethodOneImpl::method1;
// Obviously this wouldn't work as the method names don't match.
//using MethodTwoImpl::???
};
The first using statement will make both MethodOneImpl::method1 methods be public, but it actually doesn't fulfill the contract with Interface, and it modifies the accessibility of MethodOneImpl::method1(int). And obviously we couldn't use this solution with method2 as the names don't match up.
FWIW, I have what I think is a solution, but it is not part of the standard at all (in other words it won't compile). I was thinking of making a proposal to the C++ committee; if anyone has any advice, I'd appreciate any comments below (but please dont' submit the advice as an answer).
An other option (at least if using MS VC++) is to use virtual inheritance:
struct MyInterface
{
virtual void Method1() = 0;
virtual void Method2() = 0;
};
class Method1Impl : public virtual MyInterface
{
virtual void Method1() { _tprintf( _T("Method1\n") ); }
};
class Method2Impl : public virtual MyInterface
{
virtual void Method2() { _tprintf( _T("Method2\n") ); }
};
class InterfaceImpl : public virtual MyInterface,
private Method1Impl,
private Method2Impl
{
};
void TestWeirdInterfaceImpl()
{
MyInterface* pItf = new InterfaceImpl();
pItf->Method1();
pItf->Method2();
}
While this seems to work and satisfy what you are looking for (asside from C4250 warning that you will have to suppress with a #pragma), this wouldn't be my approach. (I believe virtual inheritance is still not something that supported across all compilers, but I could be wrong).
I would probably go with containment and once boilerplate code is identifier, wrap it into some kind of macro map (similar to maps in ATL or MFC) that would make it really, really difficult to ever screw it up.
So this would be my macro approach:
struct MyInterface
{
virtual float Method1( int x ) = 0;
virtual int Method2( float a, float b ) = 0;
virtual void Method3( const TCHAR* sz ) = 0;
};
class Method1Impl
{
public:
float Method1( int x ) {
_tprintf( _T("Method1: %d\n"), x ); return 5.0;
}
};
class Method2and3Impl
{
public:
int Method2( float a, float b ) {
_tprintf( _T("Method2: %f, %f\n"), a, b ); return 666;
}
void Method3( const TCHAR* sz ) {
_tprintf( _T("Method3: %s"), sz );
}
};
#define DECLARE_METHOD0( MethodName, Obj, R ) \
virtual R MethodName() { return Obj.MethodName(); }
#define DECLARE_METHOD1( MethodName, Obj, R, A1 ) \
virtual R MethodName( A1 a1 ) { return Obj.MethodName( a1 ); }
#define DECLARE_METHOD2( MethodName, Obj, R, A1, A2 ) \
virtual R MethodName( A1 a1, A2 a2 ) { return Obj.MethodName( a1, a2 ); }
class InterfaceImpl : public MyInterface
{
public:
DECLARE_METHOD1( Method1, m_method1Impl, float, int );
DECLARE_METHOD2( Method2, m_method2and3Impl, int, float, float );
DECLARE_METHOD1( Method3, m_method2and3Impl, void, const TCHAR* );
private:
Method1Impl m_method1Impl;
Method2and3Impl m_method2and3Impl;
};
void TestWeirdInterfaceImpl()
{
MyInterface* pItf = new InterfaceImpl();
pItf->Method1( 86 );
pItf->Method2( 42.0, 24.0 );
pItf->Method3( _T("hi") );
}
Until C++ gods grace us with variadic macros, you'll have to declare one for each number of parameters you have. Also if you used multiple inheritance, potentially you wouldn't need the second "Obj" param, but as I've said before, I'd avoid multiple inheritance if there's another solution, which in this case is one extra param.
Yet a third option could be something that authors of Pragmatic Programmer seem to advocate a lot. If you have a ton of cookie cutter code that you don't want to repeat because, as you pointed out, it introduces human error. Define your own language and write a code generator script (python, perl...) to auto-create the actual code. In this case you could almost point at an interface, and have the script write the text out for you. I haven't tried doing this kind of thing myself, but lately have been wanting to use it somewhere just to see and evaluate the outcome.
This is sort of ugly and may bloat the executable size, but what about
#include <iostream>
class Interface
{
public:
virtual void method1() = 0;
virtual void method2(int x) = 0;
};
template<typename T>
class MethodOneImpl : public T
{
private:
void method1(int x)
{ std::cout << "MethodOneImpl::method1() " << x << std::endl; }
public:
void method1() { method1(0); }
};
template<typename T>
class MethodTwoImpl : public T
{
public:
void method2(int x)
{ std::cout << "MethodTwoImpl::myFunc(x)" << x << std::endl; }
};
class InterfaceImpl : public MethodTwoImpl<MethodOneImpl<Interface> >
{
};
int main()
{
InterfaceImpl impl;
impl.method1();
impl.method2(0);
}
class AbsInterface
{
// this is a simple interface class.
public:
virtual void Method1() = 0;
virtual void Method2() = 0;
};
class Functor1
{
public:
void operator () ()
{
printf("This Is Void Functor1");
}
};
class Functor2
{
public:
void operator () ()
{
printf("This Is void Functor2");
}
};
template <class T1, class T2>
class DerivedTemplateClass : public AbsInterface
{
public:
virtual void Method1() { T1()(); }
virtual void Method2() { T2()(); }
};
void main()
{
DerivedTemplateClass<Stratege1, Stratege2> instance;
instance.Method1();
instance.Method2();
}
as you can see, I used Functor.
You could work with template and functor.
It seems impossible to bring MethodOneImpl / MethodTwoImpl into the scope of Interface without having them inherit from Interface because they will not fill the Virtual Table if they don't. C++ misses something like the keyword implements from other languages.
So you are stuck with the virtual inheritence thing unless realize/accept that what you are looking for is just a bridge pattern, which does not satisfy requirement a) (you shall write more code), midly b) (code not necessarly difficult to maintain) and may satisfy c).
Here (another) possible solution (with only method though to reduce bloat)
class Interface
{ public:
virtual void method1() {return impl_->method1();}
private:
Interface() {}
protected:
struct Impl {
virtual void method1() = 0; };
std::shared_ptr<Impl> impl_;
Interface(const std::shared_ptr<Impl> &impl) : impl_(impl) {}
};
class InterfaceImpl : public Interface
{
struct Impl : public Interface::Impl {
void method1() { std::cout << "InterfaceImpl::method1() " << std::endl; } } ;
public:
InterfaceImpl() : Interface(std::shared_ptr<Impl> (new Impl)) {}
};
template <class T>
class GenericInterfaceImpl : public Interface {
struct Impl : public Interface::Impl {
Impl( T &t) : t_(t) {}
void method1() { t_.method1() ; }
T t_; };
public:
GenericInterfaceImpl() : Interface(std::shared_ptr<Impl> (new Impl(T()))) {}
};
struct AMethod1Impl {
void method1() { std::cout << "AMethod1Impl::method1() " << std::endl; } } ;
struct AnotherMethod1Impl_not_working {
void method1_not_present() { std::cout << "AnotherMethod1Impl_not_working ::method1_not_present() " << std::endl; } } ;
int main() {
// compilation of next line would fail
// (lame attempt to simulate ompilation fail when pure function not implemented)
// Interface inf;
std::unique_ptr<Interface> inf;
inf.reset(new InterfaceImpl);
inf->method1();
inf.reset(new GenericInterfaceImpl<AMethod1Impl>() );
inf->method1();
// compilation of next line would fail
// inf.reset(new GenericInterfaceImpl<AnotherMethod1Impl_not_working>() );
}
Does this serve your purpose?
It maintains the interface relationship and gives you maintainable code without having any consideration of client code.
Separating each method in functionoid and giving you the power to control the prototype of each method of the different base class.
#include <iostream>
#include <memory>
using namespace std;
//No Control over this.
class MethodOneImpl
{
private:
void method1(int x)
{ std::cout << "MethodOneImpl::method1() " << x << std::endl; }
public:
void method1() { method1(0); }
};
class MethodTwoImpl
{
public:
void myFunc(int x)
{ std::cout << "MethodTwoImpl::myFunc(x)" << x << std::endl; }
};
//*************************//
class Interface
{
public:
virtual void method1() = 0;
virtual void method2(int x) = 0;
};
//This is what i would do. //
class BaseFuncType
{
//no pure virtual
void Call()
{
throw "error";
}
void Call(int x)
{
throw "error";
}
};
class Method1: public BaseFuncType
{
auto_ptr<MethodOneImpl> MethodPtr;
public:
Method1()
{
MethodPtr.reset(new MethodOneImpl());
}
virtual int Call()
{
MethodPtr->method1();
}
};
class Method2: public BaseFuncType
{
auto_ptr<MethodTwoImpl> MethodPtr;
public:
Method2()
{
MethodPtr.reset(new MethodTwoImpl());
}
virtual int Call(int x)
{
MethodPtr->myFunc(x);
}
};
template <class T1>
class MethodFactory
{
private:
T1 methodObj;
public:
void CallMethod()
{
methodObj.Call();
}
void CallMethod(int x)
{
methodObj.Call(x);
}
};
class InterfaceImpl : public Interface
{
auto_ptr<MethodFactory> factory;
public:
virtual void method1()
{
factory.reset(new MethodFactory<Method1>());
factory->CallMethod();
}
virtual void method2(int x)
{
factory.reset(new MethodFactory<Method2>());
factory->CallMethod(x);
}
};
int main()
{
auto_ptr<Interface> inf;
inf.reset(new InterfaceImpl);
inf->method1();
inf->method2(10);
// This should be disallowed!
// std::unique_ptr<MethodOneImpl> moi;
// moi.reset(new InterfaceImpl);
}