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

Considere el siguiente código:

#include  constexpr int f() { return printf("a side effect!\n"); } int main() { char a[f()]; printf("%zd\n", sizeof a); } 

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

El progtwig 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 progtwig está mal formado; no 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 comstackdor 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 el caso más general, un comstackdor no tiene permitido marcar las funciones estándar de la biblioteca como constexpr a menos que el estándar lo permita explícitamente .