Should we provide a destructor with no-throw specifier?

3.4k views Asked by At
namespace QuantLib {

    //! Base error class
    class Error : public std::exception {
      public:
        /*! The explicit use of this constructor is not advised.
            Use the QL_FAIL macro instead.
        */
        Error(const std::string& file,
              long line,
              const std::string& functionName,
              const std::string& message = "");
        /*! the automatically generated destructor would
            not have the throw specifier.
        */
        ~Error() throw() {}
        //! returns the error message.
        const char* what() const throw ();
      private:
        boost::shared_ptr<std::string> message_;
    };

}

As you see through the comment, the destructor of class Error explicitly provides an empty implementation with no-throw specifier.

Question: Is this necessary? Or is this a good practice comparing to let the compiler generate a implicit destructor?

4

There are 4 answers

5
David Rodríguez - dribeas On BEST ANSWER

In C++11, destructors are implicitly throw() (unless any member or base of the type has a destructor with a different exception specification) so if you are compiling in C++11 mode there is no need.

If you are in C++03, you might want to add it, but whether it will have an effect or not is very implementation defined... Now, for documentation purposes you might want to add it, but again, it is commonly assumed that destructors don't throw.

0
Oliver Charlesworth On

Destructors should always be designed to never throw exceptions. So in that sense, there's little point in declaring an empty destructor merely in order to mark it as no-throw.

0
Steve Jessop On

Depends what you think throw() means.

What it actually means according to the standard is, "put extra code around every call to this function if necessary, or in the function itself, to ensure that if this function throws then the exception is caught and std::unexpected is called".

Certain compilers implemented it to mean "optimize calls to this function on the assumption that they will not throw", but (in violation of the standard) didn't implement the runtime check.

So, adding it to a destructor (which certainly shouldn't throw) out to (but in practice might not) add a runtime check that should never be triggered and therefore might help debug your code. It may or may not enable an optimization.

1
bames53 On

Destructors always implicitly have exception specifications:

[class.dtor] 12.4 p3

A declaration of a destructor that does not have an exception-specification is implicitly considered to have the same exception-specification as an implicit declaration (15.4).

[except.spec] 15.4 p14

An implicitly declared special member function (Clause 12) shall have an exception-specification. If f is an implicitly declared default constructor, copy constructor, move constructor, destructor, copy assignment operator, or move assignment operator, its implicit exception-specification specifies the type-id T if and only if T is allowed by the exception-specification of a function directly invoked by f’s implicit definition; f shall allow all exceptions if any function it directly invokes allows all exceptions, and f shall allow no exceptions if every function it directly invokes allows no exceptions.

So, no, it's not necessary for you to use an exception specification.


In C++03 user defined destructors did not have an implicit exception specification, so if you do define your own destructor you can't rely on the compiler to automatically add the appropriate exception specification. But implicitly declared destructors have the same implicit exception specification as in C++11.