65 votes

Pourquoi ** pas ** pour déclarer une fonction `constexpr`?

Toute fonction qui se compose d'une instruction de retour ne pourra être déclaré constexpr et donc va permettre d'être évalués au moment de la compilation si tous les les arguments sont constexpr et seulement constexpr fonctions sont appelées dans son corps. Est-il une raison de ne pas déclarer tout ce genre de fonction constexpr ?

Exemple:

  constexpr int sum(int x, int y) { return x + y; }
  constexpr i = 10;
  static_assert(sum(i, 13) == 23, "sum correct");

Quelqu'un pourrait-il donner un exemple où la déclaration d'une fonction constexpr peut faire du mal?


Quelques réflexions:

Même si il ne devrait y avoir aucune bonne raison pour jamais de la déclaration d'une fonction pas constexpr je ne pouvais imaginer que l' constexpr mot a un transition: son absence dans le code qui n'a pas besoin de compilation les évaluations permettrait compilateurs qui ne mettent pas en œuvre au moment de la compilation les évaluations encore pour compiler ce code (mais à l'échec de manière fiable sur le code qui a besoin d'eux comme fait explicit en utilisant constexpr).

Mais ce que je ne comprends pas: si il devrait y avoir aucune bonne raison pour jamais de la déclaration d'une fonction non constexpr, pourquoi pas chaquefonction dans la bibliothèque standard déclarée constexpr? (On ne peut pas discuter qu'il n'est pas encore fait parce que il n'y avait pas suffisamment de temps encore le faire, parce que le faire pour tous est une évidence, contrairement à la décision de la pour chaque fonction, si le faire constexpr ou pas.) --- Je suis conscient que N2976 délibérément nécessite pas cstrs pour de nombreux standard de la bibliothèque de types comme les conteneurs que ce serait trop réducteurs pour possible les implémentations. Permet de les exclure de l'argument et me demande: une fois un type dans la bibliothèque standard a fait un constexpr cstr, pourquoi pas toutes les fonctions d'exploitation sur ce qu'il a déclaré constexpr?

Dans la plupart des cas, vous ne pouvez pas prétendre que vous ne souhaitez pas déclarer une fonction constexpr tout simplement parce que vous n'avez pas envisager n'importe quel moment de la compilation d'utilisation: parce que si les autres evtl. permettra d'utiliser votre code, ils peuvent voir une telle utilisation que vous n'avez pas. (Mais pour le type de trait types et des choses semblables, bien sûr.)

Donc je suppose qu'il doit y avoir une bonne raison et un bon exemple pour délibérément de ne pas déclarer une fonction constexpr?

(avec "toutes les fonctions" j'ai toujours dire: chaque fonction qui répond aux conditions pour être constexpr, c'est à dire, est défini comme un instruction de retour, ne prend que des arguments de types avec constexpr cstrs et ne fait appel qu' constexpr fonctions.)

La question Pourquoi est - std::forward jetez - constexpr-ness? est un cas particulier de celui-ci.

38voto

Anthony Williams Points 28904

Les fonctions ne peuvent être déclarés constexpr si ils obéissent aux règles pour l' constexpr --- pas de dynamique jette, pas d'allocation de mémoire, pas d'appels à la non-constexpr des fonctions, etc.

La déclaration d'une fonction de la bibliothèque standard, comme constexpr exige que TOUTES les implémentations obéir à ces règles.

Tout d'abord, cette demande de vérifier, pour chaque fonction, qu'il peut être mis en œuvre en tant que constexpr, ce qui est un long travail.

Deuxièmement, c'est une grosse contrainte sur les implémentations, et interdire de nombreuses implémentations de débogage. Il est, par conséquent, ne vaut que si les avantages l'emportent sur les coûts, ou les exigences sont suffisamment serrés que la mise en œuvre à peu près à obéir à l' constexpr règles de toute façon. La prise de cette évaluation, pour chaque fonction, est de nouveau un long travail.

15voto

templatetypedef Points 129554

Je pense que vous faites allusion, est appelé d'évaluation partielle. Ce que vous touchez, c'est que certains de ces programmes peuvent être divisés en deux parties - une pièce qui nécessite des informations d'exécution, et une pièce qui peut être fait sans les informations d'exécution et que, en théorie, vous pouvez simplement évaluer entièrement la partie du programme qui n'a pas besoin de toutes les informations d'exécution avant même de commencer l'exécution du programme. Il y a quelques langages de programmation qui font cela. Par exemple, la D langage de programmation est un interprète intégrée dans le compilateur qui permet d'exécuter du code lors de la compilation, à condition qu'il réponde à certaines restrictions.

Il y a quelques difficultés dans l'obtention de l'évaluation partielle de travail. Tout d'abord, il complique énormément la logique du compilateur, car le compilateur aura besoin d'avoir la capacité de simuler toutes les opérations que vous pourriez mettre dans un programme exécutable au moment de la compilation. Ce, dans le pire des cas, nécessite de disposer d'un interprète à l'intérieur du compilateur, en faisant un problème difficile (l'écriture d'un bon compilateur C++) et en faire des ordres de grandeur plus difficile à faire.

Je crois que la raison de la spécification actuelle sur constexpr est tout simplement de limiter la complexité de compilateurs. Le cas, elle est limitée à sont assez simples à vérifier. Il n'y a pas besoin de mettre en œuvre des boucles dans le compilateur (ce qui pourrait causer tout un tas de problèmes, à l'instar de ce qui se passe si vous obtenez une boucle infinie à l'intérieur du compilateur). Il évite aussi le compilateur susceptibles d'avoir à évaluer les déclarations qui pourraient provoquer des erreurs de segmentation lors de l'exécution, comme à la suite d'un mauvais pointeur.

Une autre considération à garder à l'esprit que certaines fonctions ont des effets secondaires, tels que la lecture de cin ou de l'ouverture d'une connexion réseau. Ces fonctions fondamentalement ne peut pas être optimisé au moment de la compilation, car cela nécessiterait la connaissance disponible uniquement lors de l'exécution.

Pour résumer, il n'y a pas de raison théorique, vous ne pouviez pas partiellement évaluer les programmes C++ au moment de la compilation. En fait, les gens font cela tout le temps. L'optimisation des compilateurs, par exemple, sont essentiellement des programmes qui tentent de le faire autant que possible. Modèle de la métaprogrammation est une instance où les programmeurs en C++ essayez d'exécuter du code à l'intérieur du compilateur, et il est possible de faire des grandes choses avec des modèles en partie parce que les règles pour les modèles forment un langage fonctionnel, le compilateur a un temps plus facile la mise en œuvre. En outre, si vous pensez à la différence entre le compilateur auteur des heures et des heures de programmation, le modèle de la métaprogrammation montre que si vous êtes d'accord rendant les programmeurs se plier en quatre pour obtenir ce qu'ils veulent, vous pouvez construire une assez faible de la langue (le système de template) et de garder la complexité du langage simple. (Je dis "faibles", comme dans "pas particulièrement expressif", pas "faible" dans la compilation de la théorie sens).

Espérons que cette aide!

4voto

Ben Voigt Points 151460

Si la fonction a des effets secondaires, vous ne voudriez pas la marquer constexpr . Exemple

Je ne peux pas obtenir de résultats inattendus, en fait, il semble que gcc 4.5.1 ignore simplement constexpr

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X