plus - c++ website
Miembros generados implícitamente y noexcept (1)
Error de biblioteca: muestra true, true, true, true, true
en gcc 4.7.
Y el error no es que los constructores de movimientos generados no sean noexcept, sino 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ía de las funciones de la biblioteca en gcc 4.6 no eran correctas, y esto se ha abordado en gcc 4.7 ,
En cuanto a cuándo las funciones miembro generadas implícitamente son noexcept, esto se documenta en §15.4 / 14. Básicamente, no se noexcept
si todas las funciones a las que deberá llamar son todas noexcept
.
Una función miembro especial declarada implícitamente (Cláusula 12) tendrá una especificación de excepción . Si
f
es un constructor predeterminado implícitamente declarado, constructor de copia, constructor de movimiento, destructor, operador de asignación de copia u operador de asignación de movimiento, su especificación de excepción implícita especifica la id de tipoT
si y solo siT
es permitida por la especificación de excepción de una función invocada directamente por la definición implícita def
;f
permitirá todas las excepciones si cualquier función que invoca directamente permite todas las excepciones, yf
no permitirá excepciones si todas las funciones que invoca directamente no permite excepciones.
Recientemente comencé a agregar la nueva especificación de 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 implícitas generadas. Dado que las funciones de noexcept
move permiten 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. Tuve problemas para entender lo que el estándar tiene que decir al respecto y, por lo tanto, probé el siguiente código en g ++ 4.6 (con -std=c++0x
) para controlarlo:
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 salida de True, True, True, False, False
, lo que significa que el constructor / asignación de copia por noexcept
, mientras que mover la operación donde no.
Ahora para mi pregunta:
¿En qué circunstancias se declaran implícitamente (o se omiten) las funciones miembro noexcept
como noexcept
? Además, ¿es correcto el comportamiento obseved para foobar
o simplemente un error de compilación en gcc4.6?