Pourquoi le C++11 constexpr de manière restrictive?
Comme vous le savez probablement, C++11 introduit le constexpr
mot-clé.
C++11 introduit le mot-clé constexpr, qui permet à l'utilisateur de
garantir qu'une fonction ou le constructeur de l'objet est au moment de la compilation
constante.
[...]
Cela permet au compilateur de comprendre et de vérifier que [nom de la fonction] est un
constante de compilation.
Ma question est pourquoi il y a des restrictions sur la forme des fonctions qui peuvent être déclarés. Je comprends le désir de garantir que la fonction est pure, mais considérez ceci:
L'utilisation de constexpr sur une fonction impose certaines restrictions sur ce que les
cette fonction peut faire. Tout d'abord, la fonction doit avoir un non-retour void
type. Deuxièmement, le corps de la fonction ne peut pas déclarer de variables ou de définir de nouvelles
les types. Troisièmement, le corps ne peut contenir que des déclarations, null états
et une seule instruction de retour. Il doit exister des valeurs d'argument tels
que, d'après l'argument de substitution, à l'expression dans la déclaration
produit une expression constante.
Qui signifie que cette fonction pure est illégal:
constexpr int maybeInCppC1Y(int a, int b)
{
if (a>0)
return a+b;
else
return a-b;
//can be written as return (a>0) ? (a+b):(a-b); but that isnt the point
}
Aussi, vous ne pouvez pas définir des variables locales... 🙁
Alors je me demandais est-ce une décision de conception, ou de faire des compilateurs de le sucer quand il s'agit de prouver l'existence de la fonction un est pur?
- De nombreuses années plus tard, en c++14, je pense qu'il est compilable maintenant. (coliru.stacked-crooked.com/a/e84489e166f931b7) ou bien j'ai mal compris quelque chose? C'est un comportement indéfini?
- c++14 assoupli les règles pour constexpr, mais cette question est à propos de C++11
Vous devez vous connecter pour publier un commentaire.
La raison pour laquelle vous pourriez avoir besoin d'écrire des déclarations à la place des expressions que vous voulez prendre avantage de les capacités supplémentaires d'états, en particulier la capacité de la boucle. Mais pour être utile, il faudrait que la possibilité de déclarer des variables (aussi interdits).
Si vous combinez une facilité pour la lecture en boucle, avec des variables mutables, avec logique de branchement (comme dans
if
consolidés) ensuite, vous avez la possibilité de créer des boucles infinies. Il n'est pas possible de déterminer si une telle boucle va jamais se terminer (le problème de l'arrêt). Ainsi, certaines sources serait la cause de la compilateur pour accrocher.Par récursive à l'aide de fonctions pures, il est possible de provoquer une récursion infinie, ce qui peut être démontré de manière équivalente puissant pour le bouclage les capacités décrites ci-dessus. Cependant, C++ dispose déjà de ce problème au moment de la compilation - il se produit avec le modèle d'extension et ainsi de compilateurs déjà avoir un interrupteur pour le "modèle de la pile de la profondeur" afin qu'ils sachent le moment d'abandonner.
Si les restrictions semblent conçues pour s'assurer que ce problème (qui est de déterminer si une compilation C++ ne sera jamais fini) ne peut pas faire plus épineux que c'est déjà fait.
The reason you'd need to write statements [is]... the ability to loop.
Je suis en désaccord, je veuxif
/else
et localesconst
objets pour la lisibilité du code, ni de qui (devrait) ajouter aucun questions pour les compilateurs.Les règles pour
constexpr
fonctions sont conçues de telle sorte qu'il est impossible à écrire unconstexpr
fonction qui a des effets secondaires.En exigeant
constexpr
ont pas d'effets secondaires, il devient impossible pour un utilisateur de déterminer le lieu et le moment où il a été réellement évaluée. Ceci est important carconstexpr
fonctions sont autorisés à se produire lors de la compilation et de l'exécution, à la discrétion du compilateur.Si des effets indésirables ont été autorisés alors, il faudrait que certaines règles concernant l'ordre dans lequel ils devraient être observées. Que serait incroyablement difficile à définir - même plus difficile que la
static
initialisation du problème de commande.Relativement simple ensemble de règles pour garantir que ces fonctions soient sans effets secondaires est d'exiger qu'ils soient une seule expression (avec quelques restrictions supplémentaires sur le dessus de cela). Cela semble limiter initialement et les règles de la déclaration if que vous avez noté. Alors que ce cas particulier pourrait avoir aucun effets secondaires, elle aurait introduit supplémentaire de complexité dans les règles, et étant donné que vous pouvez écrire les mêmes choses à l'aide de l'opérateur ternaire ou de manière récursive, c'est vraiment pas une affaire énorme.
n2235 est le papier qui a proposé l'
constexpr
plus en C++. Il traite de la raison d'être de la conception - la citation qui semble être celui-ci à partir d'une discussion sur les destructeurs, mais généralement:Il est intéressant de noter que le document mentionne également qu'une proposition précédente, il est suggéré de le le compilateur déduit automatiquement les fonctions qui ont été
constexpr
sans le mot clé new, mais cela s'est avéré être unworkably complexe, qui semble à l'appui de ma proposition, que les règles ont été conçues pour être simples.(Je pense qu'il y aura d'autres citations dans les références citées dans le document, mais qui couvre le point clé de mon argument sur les pas d'effets secondaires)
constexpr
fonctions, étant donné qu'ils doivent être définis dans le TU, avant de servir. Si toutes les variables référencées sontconst
, et toutes les fonctions appelées sont déjàconstexpr
, c'estconstexpr
. Sinon, c'est pasconstexpr
. Je pense que le problème de l'arrêt est le plus grand souci.En fait le C++ comité de normalisation est de penser à la suppression de plusieurs de ces contraintes pour le c++14. Voir ci-document de travail http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3597.html
Les restrictions pourraient certainement être levé un peu, sans activation de code qui ne peut pas être exécuté au cours de la compilation, ou qui ne peut pas être prouvée à toujours arrêter. Cependant, je suppose que ce n'était pas fait parce que
il ne ferait que compliquer le compilateur pour un gain minime. Compilateurs C++ sont très complexes car est
spécifier exactement comment beaucoup est autorisé sans violer les restrictions ci-dessus auraient été beaucoup de temps, et étant donné que les caractéristiques ont été reportées afin d'obtenir la norme de la porte, il y avait peu d'intérêt pour ajouter plus de travail (et de loin retard de la norme) pour peu de gain
certaines des restrictions aurait été plutôt arbitraire ou plutôt compliqué (surtout sur les boucles, étant donné que C++ n'est pas le concept d'un natif de l'incrémentation de la boucle for, mais à la fois la condition et l'incrément de code doivent être explicitement spécifiée dans l'instruction for, rendant ainsi possible l'utilisation arbitraire des expressions pour eux)
Bien sûr, seul un membre de la commission des normes pourrait donner une réponse faisant autorité si mes suppositions sont correctes.
constexpr
fonctions sont autorisés à être récursive, donc il n'y a aucune garantie qu'ils ont toujours arrêter. Les implémentations sont autorisés et destiné à donner jusqu'à leur évaluation après une certaine profondeur de récursion est atteint (la norme suggère un minimum de 512).Je pense que constexpr est juste pour les objets const. Je veux dire, vous pouvez maintenant avoir static const objets comme
String::empty_string
construit de manière statique(sans le piratage!). Cela peut réduire le temps avant que le "principal" appelé. Et static const objets peuvent avoir des fonctions comme.length(), operator==,...
c'est pourquoi 'expr' est nécessaire. En "C", vous pouvez créer constante statique des structures comme ci-dessous:Noyau Linux a des tonnes de ce type de classes. En c++, vous pouvez le faire maintenant avec constexpr.
remarque: je ne sais pas mais le code ci-dessous ne doivent pas être acceptées comme si version: