La risposta breve è che non solo è static
utile, ma è sempre abbastanza desiderabile.
Innanzitutto, nota che static
e constexpr
sono completamente indipendenti l'uno dall'altro. static
definisce la durata dell'oggetto durante l'esecuzione; constexpr
specifica che l'oggetto dovrebbe essere disponibile durante la compilazione. Compilazione ed esecuzione sono disgiunte e non contigue, sia nel tempo che nello spazio. Quindi, una volta compilato il programma, constexpr
non è più rilevante.
Ogni variabile dichiarata constexpr
è implicitamente const
ma const
e static
è quasi ortogonale (ad eccezione dell'interazione con static const
numeri interi).
Il C++
modello a oggetti (§1.9) richiede che tutti gli oggetti diversi dai bit-field occupino almeno un byte di memoria e abbiano indirizzi; inoltre tutti questi oggetti osservabili in un programma in un determinato momento devono avere indirizzi distinti (paragrafo 6). Ciò non richiede al compilatore di creare un nuovo array nello stack per ogni invocazione di una funzione con un array const non statico locale, poiché il compilatore potrebbe rifugiarsi nel as-if
principio a condizione che possa dimostrare che nessun altro oggetto del genere può essere osservato.
Questo non sarà facile da dimostrare, sfortunatamente, a meno che la funzione non sia banale (ad esempio, non chiama alcuna altra funzione il cui corpo non è visibile all'interno dell'unità di traduzione) perché gli array, più o meno per definizione, sono indirizzi. Quindi nella maggior parte dei casi, l' const(expr)
array non statico dovrà essere ricreato nello stack ad ogni invocazione, il che sconfigge il punto di poterlo calcolare al momento della compilazione.
D'altra parte, un static const
oggetto locale è condiviso da tutti gli osservatori e inoltre può essere inizializzato anche se la funzione in cui è definito non viene mai chiamata. Quindi nessuno dei precedenti si applica e un compilatore è libero non solo di generare una sola istanza di esso; è libero di generarne una singola istanza nella memoria di sola lettura.
Quindi dovresti assolutamente usare static constexpr
nel tuo esempio.
Tuttavia, c'è un caso in cui non vorresti usare static constexpr
. A meno che un constexpr
oggetto dichiarato non sia utilizzato o dichiarato ODRstatic
, il compilatore è libero di non includerlo affatto. È piuttosto utile, perché consente l'uso di constexpr
array temporanei in fase di compilazione senza inquinare il programma compilato con byte non necessari. In tal caso, non si vorrebbe chiaramente utilizzarlo static
, poiché static
è probabile che costringa l'oggetto a esistere in fase di esecuzione.
const
da unconst
oggetto, solo da un puntoconst X*
che indica unX
. Ma non è questo il punto; il punto è che gli oggetti automatici non possono avere indirizzi statici. Come ho detto,constexpr
cessa di essere significativo una volta terminata la compilazione, quindi non c'è nulla da buttare via (e molto probabilmente nulla, perché l'oggetto non è nemmeno garantito che esista in fase di esecuzione.)