Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the C++ standard library not use virtual inheritance for exceptions?

The C++ standard library defines std::runtime_error and similar to inherit from std::exception, but the inheritance is not virtual. This complicates the extension of the exception hierarchy. For example the following code has problems.

class sql_exception : public virtual std::exception {...};
class sql_disconnected : public virtual std::runtime_error, public virtual sql_exception {...};
void do_something() {
  throw sql_disconnected();
}
void call_something() {
  try {
     do_something();
  } catch (const std::exception& e) {
  }
}

std::exception is being not caught, as IMHO it should be. This can be worked around in various (needlessly complicated [IMHO]) ways.

I believe the standard should permit this behavior, and since it doesn't I have to assume there is a good reason, other than "this is the standard because it is the standard".

I am aware that there is some cost associated with virtual inheritance, but AFAIK it's negligible compared to the cost of stack unwinding and the rest of the exception handling.

Q1: For what technical reason did the standard library implement this behavior?

Q2: Was the problem of extending the hierarchy considered, and if so what does the standard say about the topic? Does the standard discourage it or have a recommendation to follow?

like image 603
Martin Avatar asked Oct 29 '22 16:10

Martin


1 Answers

It does not make sense to me to derive sql_disconnected from std::runtime_error but not also derive sql_exception from the same. IMHO any SQL error should be treated as a runtime error. std::runtime_error derives from std::exception, so you don't need to create a diamond hierarchy in the first place, and thus you don't need to use virtual inheritance to solve that problem. None of the standard STL exceptions use virtual inheritance, neither should your custom exceptions.

class sql_exception : public std::runtime_error {...};
class sql_disconnected : public sql_exception {...};

void do_something() {
  throw sql_disconnected();
}

void call_something() {
  try {
     do_something();
  }
  catch (const std::exception& e) {
  }
}
like image 81
Remy Lebeau Avatar answered Nov 15 '22 06:11

Remy Lebeau