2012-02-07 8 views
18

Recientemente comencé a agregar la nueva especificación noexcept para mover constructores/asignaciones siempre que sea posible. Ahora comencé a preguntarme cómo es la especificación de excepción de las funciones miembro generadas implícitamente. Dado que tener noexcept mover funciones permite el uso de rutas de código más eficientes (por ejemplo, al cambiar el tamaño de un vector), espero que se declaren como noexcept siempre que sea posible. Tenía problemas para entender lo que el estándar tiene que decir al respecto y por lo tanto probado el siguiente código en g ++ 4.6 (con -std=c++0x) para conseguir un poco de control sobre ella:miembros generados implícitos y noexcept

struct foobar{}; 
int main() 
{ 
    foobar a, b; 
    std::cout<<std::boolalpha 
      <<noexcept(foobar())<<", "<<noexcept(foobar(a))<<", " 
      <<noexcept(a = b) <<", "<<noexcept(a = std::move(b))<<", " 
      <<noexcept(foobar(std::move(a)))<<std::endl; 
} 

Esto me dio una potencia de True, True, True, False, False, lo que significa ese valor predeterminado y copiar el constructor/asignación donde noexcept, mientras que la operación de mover donde no.

Ahora mi pregunta: ¿

¿En qué circunstancias se generan implícita (o default) funciones miembro declarados como noexcept? Además, ¿es correcto el comportamiento observado para foobar o simplemente un error del compilador en gcc4.6?

Respuesta

18

Error de biblioteca: muestra true, true, true, true, true en gcc 4.7.

Y el error es no que los constructores de movimiento generados no son noexcept, pero que std::move no está marcado como noexcept, como podemos ver con las pruebas adicionales:

std::cout << noexcept(a = static_cast<foobar&&>(b)) << ", " // true 
      << noexcept(foobar(static_cast<foobar&&>(b))) << ", " // true 
      << noexcept(std::move(b)) << std::endl; // false 

La mayor parte de la biblioteca funciones en gcc 4,6 no fue noexcept-correcta, y esto ha sido abordado en gcc 4.7,


cuanto a cuando las funciones miembro generados implcitely son noexcept, TH está documentado en §15.4/14. Básicamente, es noexcept si todas las funciones que necesita llamar son todas noexcept.

Un declarada implícitamente función miembro especial (Cláusula 12) tendrá excepción de especificación. Si f es un constructor por defecto declarado implícitamente, constructor de copia, mover constructor, destructor, copia asignación operador o mover operador de asignación, su implícita excepción de especificación especifica el tipo-idT si y sólo si T es permitido por la especificación de excepción de una función invocada directamente por la definición implícita de f; f deberá permitir todas las excepciones si cualquier función que invoca directamente permite que todas las excepciones, y f no permitan excepciones si cada función que invoca permite ninguna excepción.

+0

¿Significa eso que esas funciones son 'noexcept' siempre que sea posible (es decir, que no llaman a ninguna función de lanzamiento)? – Grizzly

+0

@Grizzly: Sí. – kennytm

+6

@Grizzly: Creo que significa que serán 'noexcept' si solo llaman a las funciones' noexcept' (es decir, si las funciones reales llamadas throw o not son irrelevantes, la especificación de excepción es lo que importa) –

Cuestiones relacionadas