Un littéral de chaîne peut-il être indexé dans une expression constante?

Ceci est valide car une expression constexpr est autorisée à prendre la valeur “une valeur glvalue de type littéral qui fait référence à un object non volatile défini avec constexpr ou à un sous-object d’un tel object” (§5.19 / 2):

 constexpr char str[] = "hello, world"; constexpr char e = str[1]; 

Cependant, il semblerait que les littéraux de chaîne ne correspondent pas à cette description:

 constexpr char e = "hello, world"[1]; // error: literal is not constexpr 

2.14.5 / 8 décrit le type de littéraux de chaîne:

Les littéraux de chaîne ordinaires et les littéraux de chaîne UTF-8 sont également appelés littéraux de chaîne étroite. Un littéral de chaîne étroite est de type «tableau de n const char», où n est la taille de la chaîne définie ci-dessous et a une durée de stockage statique.

Il semblerait qu’un object de ce type puisse être indexé s’il était seulement temporaire et non d’une durée de stockage statique (5.19 / 2, juste après l’extrait de code ci-dessus):

[ constexpr autorise la conversion de valeur en valeur de]…… une valeur glvalue de type littéral qui fait référence à un object temporaire non volatile dont la durée de vie n’est pas terminée, initialisé avec une expression constante

Cela est particulièrement étrange, car prendre la valeur d’un object temporaire est généralement une “sortingche”. Je suppose que cette règle s’applique aux arguments de fonction du type référence, comme dans

 constexpr char get_1( char const (&str)[ 6 ] ) { return str[ 1 ]; } constexpr char i = get_1( { 'y', 'i', 'k', 'e', 's', '\0' } ); // OK constexpr char e = get_1( "hello" ); // error: ssortingng literal not temporary 

Pour ce que cela vaut, GCC 4.7 accepte get_1( "hello" ) , mais rejette "hello"[1] car “la valeur de ‘._0’ n’est pas utilisable dans une expression constante” … mais "hello"[1] est acceptable. comme une étiquette de cas ou un tableau lié.

Je coupe quelques cheveux de Standardese ici… l’parsing est-elle correcte et y avait-il une intention de conception pour cette fonctionnalité?

EDIT: Oh… il y a une motivation pour cela. Il semble que ce type d’expression soit le seul moyen d’utiliser une table de recherche dans le pré-processeur. Par exemple, cela introduit un bloc de code qui est ignoré à moins que SOME_INTEGER_FLAG ne soit SOME_INTEGER_FLAG 1 ou 5 et provoque un diagnostic si supérieur à 6:

 #if "\0\1\0\0\0\1"[ SOME_INTEGER_FLAG ] 

Cette construction serait nouvelle pour C ++ 11.

    L’intention est que cela fonctionne et que les paragraphes qui indiquent quand une conversion de valeur à valeur est valide seront modifiés avec une note indiquant que la valeur qui fait référence à un sous-object d’un littéral de chaîne est un object entier constant initialisé avec une expression constante ( décrit comme l’un des cas autorisés) dans un brouillon post-C ++ 11.

    Votre commentaire sur l’utilisation dans le préprocesseur semble intéressant, mais je ne sais pas si cela est censé fonctionner. J’entends parler de cela la première fois du tout.

    En ce qui concerne votre question sur #if , le comité de normalisation n’a pas pour objective d’augmenter le nombre d’expressions pouvant être utilisées dans le pré-processeur, et le libellé actuel est considéré comme un défaut. Ceci sera répertorié comme numéro principal 1436 dans le mailing post-Kona WG21. Merci d’avoir porté cela à notre attention!