简体   繁体   中英

What is the exception specification for a defaulted virtual destructor in C++11?

Suppose I have:

class Foo
{
public:
   virtual ~Foo()=default;
};

What is the exception-specification on the defaulted destructor? Is the defaulted destructor equivalent to:

   virtual ~Foo() {};
or
   virtual ~Foo() throw() {};
or
   virtual ~Foo() noexcept {};

Section 15.4 of the C++11 standard says it depends on the exception specifications of the functions directly invoked by the destructor's implicit definition. In this case there are no members, and no base classes, so AFAIK there are no functions directly invoked by the implicit destructor. Is this an ambiguity (or omission) in the standard?

It matters, of course, because if it implicitly has throw(), then all subclasses must declare their destructors with throw(). Don't tell me it's a bad idea to throw exceptions in destructors, I know that. I deal with lots of legacy code where exception specs were not used at all.

As a point of information, when I tried:

class SubFoo : public Foo
{
public:
   virtual ~SubFoo();
};

I got an error (mismatched exception specs) in GCC 4.4 (although I admit I may not have had the right command line switches), but not in XCode 4.3 using the "11" compilers.

Back up to earlier in the same sentence (§15.4/14):

...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;..."

Therefore, if ~Foo doesn't invoke any functions, it has an implicit declaration that allows no exceptions to be thrown.

According to §15.4/3:

Two exception-specifications are compatible if:

  • both are non-throwing (see below), regardless of their form,

That's the case here, so it doesn't really matter whether the declaration is throw() or noexcept -- the two are compatible in any case.

The standardese starts nicely in C++11 §8.4.2/2 ,

If a function is explicitly defaulted on its first declaration,
— it is implicitly considered to be constexpr if the implicit declaration would be,
— it is implicitly considered to have the same exception-specification as if it had been implicitly declared (15.4), …

But then, over in C++11 §15.4/14 , the logic rapidly devolves,

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.

In the standard's meaning of "allow" it is about explicitly allowing, through an exception specification.

If f calls two functions, one of which specifies and therefore allows T , and one of which allows all exceptions, then f must both specify T and allow all exceptions, which isn't possible.

So this definitely looks like a defect in the standard.

I found a related Defect Report, http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1351 .

However, it looks like this area is just a Big Mess. :-(

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM