c++ gcc c++11 constexpr side-effects

c++ - ¿Por qué puedo llamar a una función no constexpr dentro de una función constexpr?



gcc c++11 (1)

Considere el siguiente código:

#include <stdio.h> constexpr int f() { return printf("a side effect!/n"); } int main() { char a[f()]; printf("%zd/n", sizeof a); }

Hubiera esperado que el compilador se quejara de la llamada a printf dentro de f , porque f se supone que es constexpr , pero printf no lo es. ¿Por qué el programa compila e imprime 15 ?


El programa está mal formado y no requiere diagnóstico de acuerdo con el borrador de la sección 7.1.5 del estándar C ++ 11 El especificador de constexpr párrafo 5 que dice:

Para una función constexpr, si no existen valores de argumento de función tales que la sustitución de invocación de la función produzca una expresión constante (5.19), el programa está mal formado; No se requiere diagnóstico.

y proporciona el siguiente ejemplo:

constexpr int f(bool b) { return b ? throw 0 : 0; } // OK constexpr int f() { return f(true); } // ill-formed, no diagnostic required

y la sección 5.19 párrafo 2 dice:

Una expresión condicional es una expresión constante central a menos que incluya uno de los siguientes como una subexpresión potencialmente evaluada [...]

e incluye:

- una invocación de una función que no sea un constructor constexpr para una clase literal o una función constexpr [Nota: la resolución de sobrecarga (13.3) se aplica como de costumbre — nota final];

Probablemente preferiríamos un diagnóstico en este caso, podría ser simplemente un descuido, tengo un informe de error para una situación similar donde gcc no produce un error, pero probablemente nos gustaría que: El compilador tenga margen de maniobra en lo que considera ¿Un comportamiento indefinido en una expresión constante? .

Actualizar

El uso del -fno-builtin hará que gcc genere el siguiente error:

error: call to non-constexpr function ''int printf(const char*, ...)'' return printf("a side effect!/n"); ^

Por lo tanto, gcc considera que está mal formado , simplemente lo ignora cuando usa la versión incorporada de printf .

Aunque usar un poco inconsistente el -pedantic produce la siguiente advertencia:

warning: ISO C++ forbids variable length array ''a'' [-Wvla] char a[f()]; ^

Tenga en cuenta que al usar f() para inicializar una variable constexpr :

constexpr int x = f() ;

genera un error:

error: ''printf(((const char*)"a side effect!/012"))'' is not a constant expression

Tenga en cuenta que, además, en un caso más general, no se permite que un compilador marque las funciones de la biblioteca estándar como constexpr a menos que el estándar lo permita explícitamente .