'enum/integral casting from throw/catch?

As I understand it, the exception system in C++ doesn't implicitly cast to/from types that can be cast without issue, and I'd assume this is for more strict debugging; if you're throwing a bool, you may not want it to be caught in a statement where int is the exception type. This makes it particularly tricky for me to do the following:

enum Exception {
  Flag1 = 1,  //  0b00000001
  Flag2 = 2,  //  0b00000010
  Flag3 = 4,  //  0b00000100
  Flag4 = 8   //  0b00001000
  // And so on...
};

void doSomeStuff() {
  // Theoretical code happens here
  throw Flag1;
}

int main() {
  try {
    doSomeStuff();
  } catch (Exception exception) {
    if (exception & Flag1) {
      std::cout << "Flag 1 is fatal" << std::endl;
      return exception;
    }
    if (exception & Flag2) std::cout << "Flag 2 is non-fatal" << std::endl;
    if (exception & Flag3) std::cout << "Flag 3 is non-fatal" << std::endl;
    if (exception & Flag4) {
      std::cout << "Flag 4 is fatal" << std::endl;
      return exception;
    }
  }
  return 0;
}

It all works just fine when I'm only using 1 flag at a time, but once I throw anything that's been OR'd (e.g. throw Flag1 | Flag2;), it no longer "fits inside" the enum and terminates.

terminate called after throwing an instance of 'int'

The fix for this is seemingly simple -- change catch (Exception exception) to catch (int exception), because enum values are always convertible to integrals, but not the other way around. However, when I throw an enum value on its own, I now get the same error but in reverse.

terminate called after throwing an instance of 'Exception'

I can think of 3 possible fixes:

  • Explicitly cast to int every time I throw (the code that I'm actually trying to do this with is a very generic callback; could be run for dozens of different functions. Gross!)
  • Have duplicate catch(){} statements (because I am only sometimes returning from main() depending on the flags of the value thrown, I can't put this into its own function; even more gross)
  • Instead of an enum, use constants; probably just as fast (they both compile to literals), but less organized and should be completely unnecessary.

Are these my only options, or am I missing something?



Solution 1:[1]

Not tested but I think that Flag1 | Flag2 is considered by compiler as an int and not as a Exception

try casting the ored values before throwing

throw (int)(Flag1 | Flag2);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Gian Paolo