Exception Handling in C++ Terminate called after throwing an instance of ‘char const*’

A string literal is not a std::string. You throw the former, but try to catch the latter. Despite the fact a std::string may be constructed from a string literal, it won’t happen in a catch clause. The conversions which are allowed in a catch clause are detailed in [except.handle]/3:

A handler is a match for an exception object of type E if:

  • The handler is of type cv T or cv T& and E and T are the same type (ignoring the top-level cv-qualifiers), or
  • the handler is of type cv T or cv T& and T is an unambiguous public base class of E, or
  • the handler is of type cv T or const T& where T is a pointer or pointer to member type and E is a pointer or pointer to member type that can be converted to T by one or more of
    • a standard pointer conversion not involving conversions to pointers to private or protected or ambiguous classes
    • a function pointer conversion
    • a qualification conversion, or
  • the handler is of type cv T or const T& where T is a pointer or pointer to member type and E is std​::​nullptr_­t.

And neither of which applied for the case of literal -> std::string conversion.

Which ultimately results in that exception being uncaught, and the run-time calling std::terminate as is supposed to happen with uncaught exceptions.

In general, it’s best to throw a dedicated exception type (which may be part of a hierarchy), such that the very type name communicates the error that occurred. This will allow handling the error in more robust ways, if a handler (or a set of handlers) need to be written.

If you don’t want to follow the standard practice for some reason, you must make the conversion be one of those mentioned in the above bullets. You can either:

  1. Throw a std::string literal, like "You cannot devide by zero!"s (note the s suffix).
  2. Catch a const char*.

Leave a Comment