todas - static function c++
Modificar una variable global en una funciĆ³n constexpr en C++ 17 (2)
¿Qué compilador es correcto?
Clang tiene razón.
La definición de una función constexpr
según dcl.constexpr/3
La definición de una función
constexpr
cumplirá los siguientes requisitos:
(3.1) su tipo de devolución será un tipo literal;
(3.2) cada uno de sus tipos de parámetros debe ser de tipo literal;
(3.3) su cuerpo-función será= delete
,= default
, o una declaración compuesta que no contenga:
(3.3.1) una definición de asm,
(3.3.2) una declaración goto,
(3.3.3) una etiqueta identificadora,
(3.3.4) un try-block o
(3.3.5) una definición de una variable de tipo no literal o de duración de almacenamiento estático o de subprocesos o para la que no se realiza ninguna inicialización.
También según dcl.constexpr/5 :
Para una función
constexpr
o constructor constexpr que no está ni en default ni en una plantilla, si no existen valores de argumento tales que una invocación de la función o constructor podría ser una subexpresión evaluada de una expresión constante central,
Foo(true)
podría evaluarse a una expresión constante central (es decir, 1
).
Además, Foo(false)
podría ser pero no se requiere que sea evaluado constantemente.
CONCLUSIÓN
Por lo tanto, un 86327 en GCC.
Muchas gracias a @Barry, @aschepler y @BenVoigt por ayudarme con esta respuesta. En C ++ 17, ¿se le permite modificar variables globales en una función constexpr
?
#include <iostream>
int global = 0;
constexpr int Foo(bool arg) {
if (arg) {
return 1;
}
return global++;
}
int main() {
std::cout << global;
Foo(true);
std::cout << global;
Foo(false);
std::cout << global;
}
No esperaría que pudieras, pero clang 6 lo permite: https://godbolt.org/g/UB8iK2
GCC, sin embargo, no: https://godbolt.org/g/ykAJMA
¿Qué compilador es correcto?
Añadiré que dcl.constexpr / 5 también requiere:
Para una función constexpr o constructor constexpr que no está ni predeterminado ni una plantilla, si no existen valores de argumento tales que una invocación de la función o el constructor podría ser una subexpresión evaluada de una expresión constante central o, para un constructor, un inicializador constante para algún objeto ([basic.start.static]), el programa está mal formado, no se requiere diagnóstico.
Como deiberadamente escribió la función para que Foo(true)
evalúe una expresión constante central, Foo(false)
no es necesario para.