A resposta curta é que não só é static
útil, como sempre será desejável.
Primeiro, observe que static
e constexpr
são completamente independentes um do outro. static
define a vida útil do objeto durante a execução; constexpr
especifica que o objeto deve estar disponível durante a compilação. Compilação e execução são disjuntas e descontínuas, no tempo e no espaço. Assim, uma vez que o programa é compilado, constexpr
não é mais relevante.
Toda variável declarada constexpr
é implicitamente, const
mas const
e static
é quase ortogonal (exceto pela interação com static const
números inteiros).
O C++
modelo de objeto (§1.9) exige que todos os objetos que não sejam campos de bits ocupem pelo menos um byte de memória e tenham endereços; além disso, todos esses objetos observáveis em um programa em um determinado momento devem ter endereços distintos (parágrafo 6). Isso não exige muito que o compilador crie uma nova matriz na pilha para cada chamada de uma função com uma matriz const não estática local, porque o compilador pode se refugiar no as-if
princípio, desde que possa provar que nenhum outro objeto desse tipo pode ser observado.
Infelizmente, isso não será fácil de provar, a menos que a função seja trivial (por exemplo, não chame nenhuma outra função cujo corpo não seja visível na unidade de tradução) porque matrizes, mais ou menos por definição, são endereços. Portanto, na maioria dos casos, a const(expr)
matriz não estática precisará ser recriada na pilha a cada chamada, o que anula o ponto de poder computá-la em tempo de compilação.
Por outro lado, um static const
objeto local é compartilhado por todos os observadores e, além disso, pode ser inicializado mesmo que a função na qual ele é definido nunca seja chamada. Portanto, nenhuma das opções acima se aplica, e um compilador é livre não apenas para gerar apenas uma única instância dele; é gratuito gerar uma única instância dele no armazenamento somente leitura.
Então você definitivamente deve usar static constexpr
no seu exemplo.
No entanto, há um caso em que você não gostaria de usar static constexpr
. A menos que um constexpr
objeto declarado seja usado ou declarado por ODRstatic
, o compilador é livre para não incluí-lo. Isso é bastante útil, pois permite o uso de constexpr
matrizes temporárias em tempo de compilação sem poluir o programa compilado com bytes desnecessários. Nesse caso, você claramente não gostaria de usar static
, pois static
é provável que force o objeto a existir no tempo de execução.
const
de umconst
objeto, apenas de umconst X*
que aponte para umX
. Mas esse não é o ponto; o ponto é que objetos automáticos não podem ter endereços estáticos. Como eu disse,constexpr
deixa de ser significativo uma vez que a compilação estiver concluída, então não há nada de deitar fora (e muito possivelmente nada, porque o objeto não é ainda garantida a existir em tempo de execução.)