1

I have a few exceptions that look like this

class ExceptionType1Base : public std::runtime_error {

};

class ExceptionType1Derived1 : public ExceptionType1Base {

};

class ExceptionType1Derived2 : public ExceptionType1Base {

};

And another exception type

class ExceptionType2Base : public std::runtime_error {
   public:
    int type;
};

class ExceptionType2Derived1 : public ExceptionType2Base {
    ExceptionType2Derived1() {
       type = 1;
    }  

};

class ExceptionType2Derived2 : public ExceptionType2Base {
    ExceptionType2Derived2() {
       type = 2;
    }  
};

I would like to convert one type of exception to another when I catch it, with something like

ExceptionType1Base convertToType1Exception(ExceptionType2Base& ex) {
     if(ex.type == 1) {
        return ExceptionType1Derived1();
     }

     return ExceptionType1Derived2();
}

Then when I catch exceptions, it would be like

try {
    ... some code .... 
} catch (const ExceptionType2Base& ex) {
    throw convertToType1Exception(ex);
}

The problem with that is I lost the derived type of the converted exception and the exception that ends up being thrown is ExceptionType1Base, any better way of handling this ? I thought of using macros for exception type converting but I'm wondering if there is a better way.

Mike Loury
  • 11
  • 1
  • `ExceptionType1Base convertToType1Exception()` -> Please, look for object slicing. Your function `convertToType1Exception()` returns an instance of `ExceptionType1Base` always. (The implicit conversion happens in each of the `return`s. Hence, you can never catch something else than `ExceptionType1Base`. – Scheff's Cat May 18 '21 at 05:24
  • FYI: [SO: What is object slicing?](https://stackoverflow.com/q/274626/7478597) – Scheff's Cat May 18 '21 at 05:25
  • You are looking for one to one mapping between two objects. I don't think there is a way where you can logically determine return type of a function(for your requirement here) even with templates. You can catch both type1 objects in separate catch block and throw corresponding type2 objects. This should scale as long as you don't have lots of such mappings. – chandola May 18 '21 at 05:36
  • Thanks for the details. So if I want to implement such usecase. Imagine 10 different exceptions and this method is needed to be called in a lot of places. How would you implement that ? – Mike Loury May 18 '21 at 05:38
  • @MikeLoury Check this https://onlinegdb.com/iz0dtRp5n – chandola May 18 '21 at 07:10

1 Answers1

0

You want to implement a mapping between ExceptionType1 to ExceptionType2. Your current implementation doesn't work because as per the signature of convertToType1Exception, it will always return ExceptionType1Base object. However note that type attribute of returned object will be 1 or 2 depending on whether it is ExceptionType1Derived1 or ExceptionType1Derived2.

One way to solve this problem is by catching Type1 exceptions individually and throwing corresponding Type2 exceptions. Below is a sample that does this. You can extend this for more exceptions by adding more catch cases.

#include <iostream>
#include <typeinfo>

class ExceptionType1Base
{
};
class ExceptionType1Derived1:public ExceptionType1Base
{
};
class ExceptionType1Derived2:public ExceptionType1Base
{
};

class ExceptionType2Base
{
public:
  ExceptionType2Base ()
  {
  }
  int type;
};

class ExceptionType2Derived1:public ExceptionType2Base
{
public:
  ExceptionType2Derived1 ()
  {
    type = 1;
  }
};
class ExceptionType2Derived2:public ExceptionType2Base
{
public:
  ExceptionType2Derived2 ()
  {
    type = 2;
  }
};

ExceptionType1Derived1
t1d1 ()
{
  throw ExceptionType1Derived1 ();
}

ExceptionType1Derived2
t1d2 ()
{
  throw ExceptionType1Derived2 ();
}

int
main ()
{
  try
  {
    t1d2 ();
    //t1d1();
  } catch (const ExceptionType1Derived1 & ex)
  {
    throw ExceptionType2Derived1 ();
  } catch (const ExceptionType1Derived2 & ex)
  {
    throw ExceptionType2Derived2 ();
  }
  return 0;
}

Here main will throw ExceptionType2Derived2. If you call t1d1 then ExceptionType1Derived1.

chandola
  • 126
  • 1
  • 10
  • 1
    That would work, but my only issue with that is if you have to do this across 20 methods and 10 exceptions, it would be too much. I ended up not using convert and just defining a new method: throwMappedException() and have this method throw instead of returning an object. doesn't look like there is a perfect solution here. – Mike Loury May 20 '21 at 19:19