L’arrivée de C++17 – if constexpr

Bonjour tout le monde et bienvenue dans ce nouvel article consacré au if constexpr, arrivé avec C++17.

Des débuts mouvementés

A l’origine, les conditions compile-time ont été proposées avec la n3322 avec static_if et static_else en 2011.

Renommées constexpr_if et constexpr_else en 2014, pour devenir constexpr if et else en mars 2018, cette fonctionnalité subit ses derniers changements avec la p0292R2 pour devenir le  if constexpr que nous connaissons avec C++17.

Cette fonctionnalité avait fait monter aux créneaux notre saint père Bjarne Stroustrup en 2014, qui avait un avis très péjoratif sur cette fonctionnalité, lui préférant les futurs concepts lite, qui devraient arriver avec C++20.

Dans la  n3613, appuyée par la dernière slide de cette présentation, Bjarne présentait ses inquiétudes concernant ce qu’on appelait encore à l’époque static_if :

The static if feature recently proposed for C++ [1, 2] is fundamentally flawed, and its adoption would be a disaster for the language

Il appuie notamment le fait qu’il est possible de faire à peu prêt n’importe quoi avec (ce sur quoi je reviendrais à la fin de l’article), le comparant à goto, tout en rendant possiblement le travail des analyseurs statiques bien plus ardu. Si le document présente des problématiques réelles concernant l’ancien static_if, beaucoup ont considéré que les arguments techniques étaient soient inexacts, soit exagérés. Andrei Alexandrescu tient d’ailleurs les propos suivants sur ce post Reddit (que je vous invite à lire si ça vous intéresse) :

As always (well, almost always…) I stand by everything I write publicly. N3613 is unusually subjective, factually incorrect, and tendentious. It’s fine as a newsgroup article, blog post, or op-ed/opinion paper but quite a bit out of character for ISO C++. Saddeningly, it’s completely out of line as far as academic debate goes.

Usage et règles

L’un des principaux avantages de if constexpr est la simplification du code générique. Les références en bas de l’article contiennent un bon nombre de liens proposant des exemples d’utilisation.

if constexpr, contrairement à son homologue classique, n’est évalué qu’une seule fois au moment de la compilation. Il va choisir quelle branche sera compilée en fonction de la condition (qui doit être une expression connue à la compilation).

Dans un template, il n’est pas nécessaire que la branche inutilisée compile :

Dans l’exemple ci-dessus, la fonction foo est spécialisée pour les types entiers, et utilise une fonction membre de T si   T n’est pas de type intégral. Dans le cas d’un entier, la branche else contient t.do_something qui n’est pas valide mais ne pose pas de problème puisque la branche n’est pas choisie.

Note: le fait que la branche ignorée n’a pas à être valide n’est valable que lorsque if constexpr est à l’intérieur d’un template. De plus, il n’est pas autorisé que la branche soit invalide peu importe T (tout simplement parce qu’il n’existe dans ce cas aucune instanciation valide).

Cette règle se rapproche fortement de SFINAE, et le code ci-dessus aurait pu être écrit pré-C++17 à l’aide d’un peu plus de lignes. Par exemple :

D’une manière générale, if constexpr permet de remplacer les codes génériques utilisant la SFINAE. Dans la page sur std::visit de cppreferences.com, on peut voir un exemple de code tirant partie de cette fonctionnalité :

Comme vous pouvez le constater, if constexpr est utilisable dans les lambdas. Figurez-vous qu’il est même possible de mixer les deux formes de if :

if constexpr est aussi compatible avec le init-statement de C++17 :

On pourrait imaginer remplacer la compilation conditionnelle basée sur les condition du préprocesseur par if constexpr, mais les deux ne sont pas équivalents.

Si la branche inutilisée de if constexpr n’a pas à être valide dans le cas d’un template, ce n’est pas le cas dans le cas général :

Enfin, il est possible d’émuler if constexpr si votre compilateur n’est pas à jour. Je vous laisse ce lien sur stackoverflow.com où plusieurs solutions sont proposées :).

 

Voilà, c’est déjà la fin. Merci de m’avoir lu et je vous dit à bientôt !

Références et ressources

 

 

%d bloggers like this: