2012-05-24 17 views
9

Supongamos que tengo:¿Cuál es la especificación de excepción para un destructor virtual predeterminado en C++ 11?

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

¿Cuál es la excepción de especificación en el destructor en default? Es el destructor en mora equivalente a:

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

Sección 15.4 del estándar de C++ 11 dice que depende de las especificaciones de excepción de las funciones directamente invocadas por definición implícita del destructor. En este caso, no hay miembros ni clases base, por lo que AFAIK no hay funciones invocadas directamente por el destructor implícito. ¿Es esto una ambigüedad (u omisión) en el estándar?

Importa, por supuesto, porque si implícitamente tiene throw(), entonces todas las subclases deben declarar sus destructores con throw(). No me digas que es una mala idea arrojar excepciones en los destructores, lo sé. Me ocupo de un montón de código heredado donde las especificaciones de excepción no se utilizaron en absoluto.

Como punto de información, cuando lo probé:

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

me dio un error (Ficha de excepción no coincidentes) en GCC 4.4 (aunque admito que puede que no haya tenido la línea de comando de la derecha cambia), pero no en XCode 4.3 utilizando los compiladores "11".

Respuesta

4

una copia de seguridad anteriormente en la misma frase (§15.4/14):

... su implícita excepción de especificación especifica el tipo T-id si y sólo si T está permitido por la excepción- especificación de una función directamente invocada por definición implícita de f; ..."

por lo tanto, si ~Foo no invoca ninguna función, tiene una declaración implícita de que no admite excepciones que se arrojen

acuerdo. a §15.4/3:

Dos excepción especificaciones son compatibles si:

  • ambos son no-lanzamiento (véase más adelante), independientemente de su forma,

Eso es El caso aquí, por lo que realmente no importa si la declaración es throw() o noexcept - los dos son compatibles en cualquier caso.

+0

Gracias por la respuesta. Para realizar un seguimiento un poco más, la especificación dice "Se considera implícitamente que una declaración de un destructor que no tiene una especificación de excepción tiene la misma especificación de excepción que una declaración implícita" Entonces, "virtual ~ SubFoo();" (sin una especificación de excepción) no está mal formado, a menos que invoca directamente funciones que implícita o explícitamente permiten lanzar? – user1414050

+0

@ user1414050: Creo que es correcto, sí, pero nosotros ' Estoy adentrándome en los rincones más oscuros del lenguaje, no apostaría mucho a que la mayoría de los compiladores lo entiendan todavía. En particular, sospecho que muchos compiladores (¿la mayoría?) tratan 'virtual ~ SubFoo();' con el significado "pueden arrojar cualquier cosa ", al igual que lo haría con una función normal. –

+0

Creo que esta conclusión puede no ser válida, ya que el" si y solo si "se contradice con la siguiente oración parcial sobre allowin g todas las excepciones (es decir, el estándar es autocontradictorio aquí). Y creo que es cuestionable si la intención es que los destructores no tengan tiro por defecto. Porque eso sería incompatible con C++ 03. –

2

El standardese agradable, comenzando en C++ 11 §8.4.2/2,

Si una función es por defecto de forma explícita en su primera declaración,
- se considera implícitamente que si constexpr la declaración implícita sería,
- se considera implícitamente que tiene la misma especificación de excepción que si se hubiera declarado implícitamente (15.4), & hellip;

Pero luego, en C++ 11 §15.4/14, la lógica recae rápidamente,

Una declarado implícitamente función miembro especial (Cláusula 12) tendrá un excepción de especificación. Si f es un constructor predeterminado declarado implícitamente, constructor de copia, mover constructor, destructor, operador de asignación de copia o operador de asignación de movimiento, su especificación de excepción implícita especifica el tipo-id T si y solo si T está permitido por la especificación de excepción de una función invocada directamente por la definición implícita f; f permitirá todas las excepciones si cualquier función que invoca directamente permite todas las excepciones, y f no permitirá excepciones si cada función que invoca directamente no permite excepciones.

En el significado del estándar de "permitir" se trata de permitir explícitamente, a través de una especificación de excepción.

Si f llama dos funciones, una de las cuales especifica y por lo tanto permite T, y uno de los cuales permite que todas las excepciones, a continuación, f deberán especificar T y permita que todas las excepciones, que ISN t ’ posible.

Esto definitivamente parece un defecto en el estándar.

Encontré un Informe de Defectos relacionado, http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1351.

Sin embargo, parece que esta área es solo un gran desastre. :-(

+0

@anonymous downvoter: por favor explique su voto a favor para que otros puedan aprender de su (s) visión (es). –

+0

No me parece un DR; simplemente significa que debe considerar 'la especificación de excepción especifica T' como un subconjunto de' permitir todas las excepciones'. – MSalters

+0

@MSalters: no hay sintaxis para eso? –

Cuestiones relacionadas