Domanda

Questo è valido, perché a constexpr L'espressione può prendere il valore di "un glvalue di tipo letterale che si riferisce a un oggetto non volatile definito con costexpr o che si riferisce a un sotto-oggetto di tale oggetto" (§5.19/2):

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

Tuttavia, sembrerebbe che i letterali a stringa non si adattino a questa descrizione:

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

2.14.5/8 descrive il tipo di lettera di stringa:

I letterali di stringa ordinari e i letterali di stringa UTF-8 sono anche definiti letterali a stringa stretta. Una stringa stretta letterale ha un tipo "array di n const char", in cui n è la dimensione della stringa come definita di seguito e ha una durata di archiviazione statica.

Sembrerebbe che un oggetto di questo tipo potesse essere indicizzato, se solo fosse temporaneo e non di durata di archiviazione statica (5.19/2, subito dopo lo snippet sopra):

[constexpr consente la conversione da lValue-ralue di] ... un glvalue di tipo letterale che si riferisce a un oggetto temporaneo non volatile la cui durata non è terminata, inizializzata con un'espressione costante

Ciò è particolarmente strano dal momento che assumere il valore di un oggetto temporaneo è di solito "imbrogli". Suppongo

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

Per quello che vale, GCC 4.7 accetta get_1( "hello" ), ma rifiuta "hello"[1] Perché "il valore di '._0' non è utilizzabile in un'espressione costante" ... ancora "hello"[1] è Accettabile come etichetta del caso o un matrice vincolata.

Sto dividendo alcuni peli di standardesi qui ... l'analisi è corretta e c'era un po 'di design per questa funzione?

MODIFICARE: Oh ... c'è qualche motivazione per questo. Sembra che questo tipo di espressione sia l'unico modo per utilizzare una tabella di ricerca nel preprocessore. Ad esempio, questo introduce un blocco di codice che viene ignorato a meno che SOME_INTEGER_FLAG è 1 o 5 e causa una diagnostica se maggiore di 6:

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

Questo costrutto sarebbe nuovo a C ++ 11.

Nessuna soluzione corretta

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top