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 .