La respuesta corta es que no solo es static
útil, sino que siempre va a ser deseable.
Primero, tenga en cuenta que static
y constexpr
son completamente independientes entre sí. static
define la vida útil del objeto durante la ejecución; constexpr
especifica que el objeto debe estar disponible durante la compilación. La compilación y la ejecución son disjuntas y no contiguas, tanto en el tiempo como en el espacio. Entonces, una vez que se compila el programa, constexpr
ya no es relevante.
Cada variable declarada constexpr
es implícita const
, pero const
y static
son casi ortogonal (a excepción de la interacción con static const
números enteros).
El C++
modelo de objetos (§1.9) requiere que todos los objetos que no sean campos de bits ocupen al menos un byte de memoria y tengan direcciones; además, todos esos objetos observables en un programa en un momento dado deben tener direcciones distintas (párrafo 6). Esto no requiere que el compilador cree una nueva matriz en la pila para cada invocación de una función con una matriz const local no estática, porque el compilador podría refugiarse en el as-if
principio siempre que pueda probar que ningún otro objeto puede ser observado.
Desafortunadamente, eso no será fácil de probar, a menos que la función sea trivial (por ejemplo, no llama a ninguna otra función cuyo cuerpo no sea visible dentro de la unidad de traducción) porque las matrices, más o menos por definición, son direcciones. Por lo tanto, en la mayoría de los casos, la const(expr)
matriz no estática tendrá que recrearse en la pila en cada invocación, lo que frustra el punto de poder calcularla en el momento de la compilación.
Por otro lado, un static const
objeto local es compartido por todos los observadores, y además puede inicializarse incluso si la función en la que se define nunca se llama. Por lo tanto, nada de lo anterior se aplica, y un compilador es libre no solo para generar solo una sola instancia; es libre de generar una sola instancia en el almacenamiento de solo lectura.
Así que definitivamente deberías usarlo static constexpr
en tu ejemplo.
Sin embargo, hay un caso en el que no querrás usar static constexpr
. A menos que un constexpr
objeto declarado sea utilizado o declarado por ODRstatic
, el compilador es libre de no incluirlo en absoluto. Eso es bastante útil, porque permite el uso de constexpr
matrices temporales en tiempo de compilación sin contaminar el programa compilado con bytes innecesarios. En ese caso, claramente no querrá usar static
, ya que static
es probable que obligue al objeto a existir en tiempo de ejecución.
const
de unconst
objeto, solo desde un puntoconst X*
que apunta a unX
. Pero ese no es el punto; El punto es que los objetos automáticos no pueden tener direcciones estáticas. Como ya he dicho,constexpr
deja de ser significativa una vez finalizada la compilación, por lo que no hay nada de esparcir (y, posiblemente, nada en absoluto, porque el objeto no está garantizada incluso de existir en tiempo de ejecución.)