for my understanding constexpr tells the compiler to calculate functions during compile time instead of running time.
Pas exactement: avec constexpr
le compilateur peut (ne doit pas) la fonction de calcul le temps de compilation. Et le compilateur le fait quand c'est nécessaire et possible.
En cas de
std::array<int, foo(5)> arr; // OK
il est nécessaire (parce que le deuxième argument de modèle de std::array
doit être connu au moment de la compilation) et possible (parce que 5 est connu au moment de la compilation).
Mais avec
int i = 10;
std::array<int, foo(i)> arr1; // Error
il est nécessaire (std::array
), mais pas possible (parce i
est une variable et le compilateur ne peut pas utiliser la valeur i
pas constante compilation, mais seulement le temps d'exécution).
C'est nécessaire mais pas possible, donc l'erreur.
Mais vous pouvez écrire
int i { 10 };
int j { foo(i) };
car il est impossible appel foo(i)
temps de compilation, mais il ne faut pas (parce que j
peuvent être initialisés temps d'exécution). Donc foo(i)
est appelé (soi-disant) temps d'exécution.
Pour compilez le std::array
en utilisant foo(i)
, vous devez définir i
comme constexpr
(ou const
)
constexpr int i { 10 };
de sorte que le compilateur peut utiliser la valeur de i
temps de compilation.
Why? i is declared beforehand why does it have to be a const?
Réponse courte: parce que le standard C++ 11 le dit. Réponse longue: parce que, de cette façon, il est plus simple de construire un compilateur. Si vous voulez utiliser un temps de compilation, vous pouvez le déclarer comme constexpr
et le compilateur vérifier qu'il n'est jamais modifié. C'est (relativement) simple à faire.
Sinon, si vous pouviez utiliser la valeur d'une variable non constante lors de la compilation, le compilateur devrait suivre l'histoire d'une variable pour déterminer sa valeur lorsqu'elle est utilisée dans une fonction constexpr
. Dans votre exemple de jouet est simple, dans la vraie vie serait un cauchemar.