web-dev-qa-db-fra.com

Est-ce que std :: string finira par être notre chaîne de compilation après tout?

De nombreux développeurs et auteurs de bibliothèques éprouvent des difficultés avec les chaînes de compilation depuis plusieurs années maintenant - comme chaîne standard (bibliothèque), std::string, nécessite une allocation de mémoire dynamique et n'est pas constexpr.

Nous avons donc un tas de questions et d'articles de blog sur la façon d'obtenir les bonnes chaînes de compilation:

Nous avons maintenant appris que non seulement new est disponible dans le code constexpr, ce qui permet une allocation dynamique au moment de la compilation, mais, en fait, std::string deviendra constexpr en C++ 2 (rapport de réunion du groupe de travail standard C++ par Herb Sutter).

Cela signifie-t-il que pour le code C++ 20 et plus, nous devrions supprimer toutes ces implémentations de chaînes astucieuses lors de la compilation et toujours simplement utiliser std::string?

Sinon - quand le ferions-nous et quand resterions-nous à ce qui est possible aujourd'hui (autre que le code rétrocompatible bien sûr)?


Remarque: je ne parle pas de chaînes dont le contenu fait partie de leur type, c'est-à-dire pas de parler de l'équivalent de std::integral_constant; ça ne va certainement pas être std::string.

18
einpoklum

Cela dépend de ce que vous entendez par "chaîne constexpr".

Ce que C++ 20 vous permet de faire, c'est d'utiliser std::string Dans une fonction marquée constexpr (ou consteval). Une telle fonction peut créer un string, le manipuler, etc., comme tout type littéral. Cependant, cette chaîne ne peut pas s'échapper dans un code non - constexpr; ce serait une allocation non transitoire et est interdite.

Le fait est que tous les exemples que vous donnez sont des tentatives d'utiliser des chaînes comme paramètres de modèle . C'est une chose similaire mais différente. Vous ne parlez pas seulement de construire une chaîne au moment de la compilation; vous voulez maintenant l'utiliser pour instancier un modèle.

C++ 20 résout ce problème en permettant aux types définis par l'utilisateur d'être des paramètres de modèle. Mais les exigences sur ces types sont beaucoup plus strictes que d'être simplement des types littéraux. Le type doit avoir aucun membre non public et les seuls membres sont de types qui respectent ces restrictions . Fondamentalement, le compilateur doit savoir qu'une comparaison octet-sage de ses membres de données représente une valeur équivalente. Et même un constexpr - compatible std::string Ne fonctionne pas de cette façon.

Mais std::array<char, N> peut faire cela. Et si vous êtes dans le code constexpr, appelez une fonction constexpr qui renvoie un std::string, Et stockez cette chaîne dans une valeur constexpr, puis string::size() est une fonction constexpr. Vous pouvez donc l'utiliser pour remplir le N de votre tableau.

Copier les caractères dans un constexpr array (Puisque c'est une valeur constexpr, c'est immuable) est un peu plus compliqué, mais c'est faisable.

C++ 20 résout donc ces problèmes, mais pas (directement) avec std::string.

12
Nicol Bolas