Question

C'est valable, car un constexpr L'expression est autorisée à prendre la valeur de "une glvalue de type littéral qui fait référence à un objet non volatile défini avec Consxpr, ou qui fait référence à un sous-objet d'un tel objet" (§5.19 / 2):

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

Cependant, il semblerait que les littéraux de cordes 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 cordes ordinaires et les littéraux de cordes UTF-8 sont également appelés littéraux de cordes étroites. Un littéral de chaîne étroit a un type «tableau de n const char», où n est la taille de la chaîne telle que définie ci-dessous, et a une durée de stockage statique.

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

[constexpr Permet une conversion lvalue-rvalue de]… une glvalue de type littéral qui fait référence à un objet temporaire non volatile dont la durée de vie n'a pas terminé, initialisé avec une expression constante

Ceci est particulièrement étrange car la prise de la valeur d'un objet temporaire est généralement une «tricherie». Je suppose que cette règle s'applique aux arguments de fonction du type de 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: string literal not temporary

Pour ce que ça vaut, GCC 4.7 accepte get_1( "hello" ), mais rejette "hello"[1] Parce que "la valeur de '._0' n'est pas utilisable dans une expression constante"… pourtant "hello"[1] est acceptable en tant qu'étiquette de cas ou lié à un tableau.

Je divise des poils standardais ici… L'analyse est-elle correcte, et y avait-il une intention de conception pour cette fonctionnalité?

ÉDITER: Oh… il y a une certaine 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 est 1 ou 5, et provoque un diagnostic s'il est supérieur à 6:

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

Cette construction serait nouvelle dans C ++ 11.

Pas de solution correcte

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top