Idéalement Déclarer au Moment de la Compilation des Chaînes en C++

Être en mesure de créer et de manipuler des chaînes de caractères lors de la compilation en C++ dispose de plusieurs applications utiles. Bien qu'il est possible de créer au moment de la compilation des chaînes en C++, le processus est très lourd, que la chaîne de caractères doit être déclaré comme un variadic séquence de caractères, par exemple:

using str = sequence<'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!'>;

Des opérations telles que la concaténation de chaîne, sous-chaîne d'extraction, et beaucoup d'autres, peuvent être facilement mises en œuvre que les opérations sur les séquences de caractères. Est-il possible de déclarer au moment de la compilation des chaînes plus facilement? Si non, est-il une proposition dans les œuvres qui permettrait à la pratique de la déclaration de la compilation des chaînes?

Pourquoi Les Approches Existantes De L'Échec

Idéalement, nous aimerions être en mesure de déclarer au moment de la compilation des chaînes comme suit:

//Approach 1
using str1 = sequence<"Hello, world!">;

ou, à l'aide définis par l'utilisateur littéraux,

//Approach 2
constexpr auto str2 = "Hello, world!"_s;

decltype(str2) aurait un constexpr constructeur. Une messier version de la méthode 1 est possible de mettre en œuvre, en tirant parti du fait que vous pouvez effectuer les opérations suivantes:

template <unsigned Size, const char Array[Size]>
struct foo;

Toutefois, le tableau aurait besoin d'avoir une liaison externe, afin d'obtenir de 1 à travailler, vous devez écrire quelque chose comme ceci:

/* Implementation of array to sequence goes here. */

constexpr const char str[] = "Hello, world!";

int main()
{
    using s = string<13, str>;
    return 0;
}

Inutile de dire que cela est très gênant. Approche 2 est en fait pas possible de mettre en œuvre. Si nous étions à déclarer (constexpr) littérale de l'opérateur, alors comment pourrions-nous préciser le type de retour? Depuis que nous avons besoin l'opérateur pour retourner un variadic séquence de caractères, de sorte que nous aurions besoin d'utiliser le const char* paramètre pour spécifier le type de retour:

constexpr auto
operator"" _s(const char* s, size_t n) -> /* Some metafunction using `s` */

Il en résulte une erreur de compilation, car s n'est pas un constexpr. En essayant de contourner ce problème en procédant de la manière suivante n'aide pas beaucoup.

template <char... Ts>
constexpr sequence<Ts...> operator"" _s() { return {}; }

La norme veut que ce spécifique littérale de l'opérateur formulaire est réservé pour l'entier et les types à virgule flottante. Alors que 123_s, la abc_s ne le serait pas. Si nous fossé définis par l'utilisateur littéraux tout à fait, et juste utiliser un constexpr fonction?

template <unsigned Size>
constexpr auto
string(const char (&array)[Size]) -> /* Some metafunction using `array` */

Comme avant, nous rencontrons le problème est que le tableau, maintenant un paramètre à la constexpr fonction, est en lui-même n'est plus un constexpr type.

Je crois qu'il devrait être possible de définir un préprocesseur C macro qui prend une chaîne de caractères et la taille de la chaîne en argument, et renvoie une séquence comprenant les caractères dans la chaîne (à l'aide de BOOST_PP_FOR, stringification, tableau des indices, etc). Cependant, je n'ai pas le temps (ou suffisamment d'intérêt) pour mettre en œuvre une telle macro =)

  • Boost est une macro qui définit une chaîne de caractères qui peut être utilisé comme une expression constante. Eh bien, il définit une classe qui a un membre de type string. Avez-vous vérifier cela?
  • Liaison externe n'est pas une exigence de plus pour les non-gabarit de type d'arguments. En fait, str a une liaison interne dans votre exemple. (Point mineur, vous ne pouvez toujours pas utiliser les littéraux de chaîne.)
  • Avez-vous vérifié cpp-next.com/archive/2012/10/... ?
  • Un Débordement de pile n'est pas l'endroit approprié pour poser de savoir si une proposition pour quelque chose existe. Le meilleur endroit pour ce faire pourrait être la le C++ du site.
  • Ah, donc la mise en œuvre de cette aide du préprocesseur est plus facile que je ne le pensais. Voulez-vous post que comme la réponse? Abrahams solution semble élégante pour moi.
  • Ce que je voulais dire est un peu différente de ce que le titre implicite. Maintenant j'ai édité le titre et le corps afin de réfléchir à ma question avec plus de précision. Si aucune méthode n'existe en C++11 pratique pour initialiser au moment de la compilation des chaînes, alors oui, je me demandais si il y a une proposition dans les œuvres. Cependant, Evgeny Panasyuk a souligné un article de David Abrahams qui donne une solution élégante. Donc, je pense que cette question peut toujours être utile à d'autres personnes qui sont à la recherche pour plus d'informations sur la compilation des chaînes de caractères.
  • Avez-vous vraiment besoin de simples caractères non-type de modèle arguments? Vous pouvez envisager d'utiliser constexpr tableaux, voir par exemple ce DONC, la question, Xeo (et ma) réponse
  • Je pense que j'ai besoin de l'caractères non-gabarit de type d'arguments. Corrigez-moi si je me trompe, mais une fois que les deux std::arrays ont été renvoyées de la constexpr fonction dans Xeo réponse, ils ne peuvent plus être concaténés au cours de la compilation. Je voudrais la capacité de manipuler des chaînes de caractères lors de la compilation (par exemple, la concaténation de chaîne d'extraction, etc.), après qu'ils ont été initialisés.
  • Qu'est ce que le DONC, la question que j'ai mentionné est tout au sujet de: la Concaténation de chaînes au moment de la compilation. Voir aussi cette bibliothèque pour le moment de la compilation de manipulation de chaîne; je pense que j'ai même vu une plus amélioré la bibliothèque (il ne peut pas trouver un guichet automatique).
  • Fondamentalement, vous développez les caractères stockés dans le tableau/pointeur en paramètre pack (comme Xeo n'). S'ils ne sont pas divisés en non-type de modèle arguments, vous pouvez les utiliser dans constexpr fonctions et d'initialiser les tableaux (donc, concat, substr, etc).
  • Intéressant, donc le membre de la pile dans le constexpr classe string peut être utilisé dans la suite constexpr consolidés. Je vais jouer avec cela, et de voir comment les deux implémentations de comparer. À l'aide de tableaux au lieu de variadic séquences de char peut rendre les choses plus faciles.
  • Où voulez-vous? Quelle est la différence entre celui-ci et const char* / string pour votre cas d'utilisation?
  • En bref, constexpr des chaînes peut être analysé au cours de la compilation, de sorte que vous pouvez prendre différents chemins de code en fonction des résultats. Essentiellement, vous pouvez créer des listes de montage en C++; les applications sont assez infinies.

InformationsquelleAutor void-pointer | 2013-04-07