c++ undefined-behavior c++11 language-lawyer

c++ - constexpr comportamiento indefinido



undefined-behavior c++11 (2)

He estado experimentando con constexpr . En mi compilador de prueba (g ++ 4.6), esto no se compila con un error sobre el acceso fuera de límites. ¿Se requiere un compilador para detectar esto en tiempo de compilación?

#include <iostream> constexpr const char *str = "hi"; constexpr int fail() { return str[1000]; // Way past the end! } template <int N> struct foo { static void print() { std::cout << N << std::endl; } }; int main() { foo<fail()>::print(); }


§5.19 / 2 (en la segunda página; realmente debería dividirse en muchos párrafos) prohíbe expresiones constantes que contengan

- una conversión de lvalue a rvalue (4.1) a menos que se aplique a

- un valor de tipo integral o de enumeración que hace referencia a un objeto const no volátil con una inicialización anterior, inicializado con una expresión constante, o

- un valor de tipo literal que se refiere a un objeto no volátil definido con constexpr, o que se refiere a un subobjeto de dicho objeto

str[1000] traduce a * ( str + 1000 ) , que no se refiere a un subobjeto de str , en contraste con un acceso de matriz dentro de los límites. Así que esta es una regla diagnosticable, y el compilador debe presentar una queja.

EDIT: Parece que hay cierta confusión acerca de cómo se produce este diagnóstico. El compilador verifica una expresión contra §5.19 cuando necesita ser constante. Si la expresión no cumple con los requisitos, el compilador debe presentar una queja. En efecto, se requiere validar expresiones constantes contra cualquier cosa que, de lo contrario, podría causar un comportamiento indefinido. * Esto puede implicar o no intentar evaluar la expresión.

* En C ++ 11, "un resultado que no está definido matemáticamente". En C ++ 14, "una operación que tendría un comportamiento indefinido", que por definición (§1.3.24) ignora el comportamiento que la implementación podría definir como una alternativa.


Sí, se supone que el compilador captura esto en el momento de la compilación, si nos fijamos en la sección 5.19 Expresiones constantes en el párrafo 2 del borrador del estándar de C ++ , enumera esto como una exclusión para las expresiones constantes:

- una operación que tendría un comportamiento indefinido [Nota: incluyendo, por ejemplo, desbordamiento de entero con signo (Cláusula 5), ​​cierta aritmética de punteros (5.7), división por cero (5.6), o ciertas operaciones de desplazamiento (5.8), nota final;

y el problema 695, por lo que puedo decir, dice que el comportamiento indefinido no es constante y debería emitir un diagnóstico:

El consenso del CWG fue que una expresión como 1/0 simplemente debería considerarse no constante; cualquier diagnóstico resultaría del uso de la expresión en un contexto que requiera una expresión constante.

Puede encontrar más detalles en mi pregunta de respuesta automática aquí, que también se relaciona con los usos de esta función.