1

I have to deal with very old C++ code which is including a header file containing code snippets like this one,

  static inline unsigned int
  EventId(unsigned long Header) throw (std::string)
  {
    if (!isTDCHeader(Header)  && !isTDCTrailer(Header)) {
      throw std::string("CAENV1x90Data::EventId - not a tdc header");
    } 
    else {
      return ((Header & EVENTID_MASK) >> EVENTID_RSHIFT);
    }
  }

Snippets like this cause compiling errors like the following,

error: ISO C++1z does not allow dynamic exception specifications
   Lost(unsigned long datum) throw (std::string)

I understand why this is happening, but I have no idea how to port this code to compile under C++17 with a minimal amount of "headache".

I found questions such as

but I am not able to translate the solution to my case as I am absolutely not a C++ "aficionado" (even though I promised myself to start someday...).

273K
  • 29,503
  • 10
  • 41
  • 64
Michele Peresano
  • 154
  • 1
  • 11
  • 6
    `EventId(unsigned long Header) throw (std::string)` -> `EventId(unsigned long Header)` – NathanOliver Feb 28 '23 at 14:11
  • Thanks that worked! I have no idea why exactly, but it worked. I guess the `throw std::string("bla");` part is fine then... – Michele Peresano Feb 28 '23 at 14:17
  • 5
    Long story short, C++ found the specifications useless, so got rid of them. – Passer By Feb 28 '23 at 14:20
  • 1
    Yes, as the Q&A's you've linked to cover, its the exception specification (the `thow (some_type)` part after the function that was removed from C++. You can't still throw exceptions. – NathanOliver Feb 28 '23 at 14:20
  • 4
    What is more useful to know for an optimizer is if a function can't throw an exception, and that is why we got `noexcept` and the new way of doing exception specifications. – NathanOliver Feb 28 '23 at 14:21
  • 1
    _Unrelated (to go further):_ If you have to rework this code, it would be a better practice to throw an exception deriving from `std::exception` instead of a `std::string` directly. It makes possible to handle exceptions through polymorphism instead (without caring about the actual type, it allows to just catch `std::exception` by reference). – Fareanor Feb 28 '23 at 14:27
  • 2
    Just drop it. You relay do not need `dynamic exception specifications`. AFAIK it doesn't impacts name mangling so even in case of dynamic library this should not be a problem. Only if you have empty list you translate `throw()` into `noexcept`. – Marek R Feb 28 '23 at 14:29
  • You can use `noexcept(false)` if you want to *explicitly* highlight the fact that a function can potentially throw. – Adrian Mole Feb 28 '23 at 15:05
  • 1
    If you're ever given the chance to rework this code I'd suggest rewriting it so that it fails using a `std::optional` or a `std::variant` this code doesn't need to throw and exception since failure appears to be anticipated quite often. The current thought process is that exceptions really should be a non-recoverable error ideally. – Mgetz Feb 28 '23 at 15:18

1 Answers1

4

Dynamic exception specifications were dropped without any real replacement.

Simply remove all such specifiers, except if the argument list is empty (throw()), in which case it should be replaced by noexcept. Also, if a destructor or operator delete/operator delete[] should have anything but throw() as such a specifier, then replace it with noexcept(false).

And don't confuse the dynamic exception specification on a function declaration with a throw-expression. Both use the keyword throw, but of course you should only remove the former, not the latter.

The default in C++ is that all functions (with minor exceptions like destructors since C++11) can throw any type as an exception. noexcept (or equivalently noexcept(true)) and noexcept(false) can be used to change that default, but it isn't possible anymore to specify types of exceptions that can be thrown explicitly.

user17732522
  • 53,019
  • 2
  • 56
  • 105