2011-09-15 8 views
17

Esto es válido, porque una expresión constexpr puede tomar el valor de "un glvalue de tipo literal que se refiere a un objeto no volátil definido con constexpr o que se refiere a un subobjeto de dicho objeto" (§ 5.19/2):¿Puede un literal de cadena ser subscrito en una expresión constante?

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

sin embargo, parecería que los literales de cadena no se ajustan a esta descripción:

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

2.14.5/8 describe el tipo de cadenas literales:

Los literales de cadena ordinarios y los literales de cadena UTF-8 también se conocen como literales de cadena estrecha. Un literal de cadena estrecha tiene el tipo "matriz de n const char", donde n es el tamaño de la cadena como se define a continuación, y tiene una duración de almacenamiento estática.

Parecería que un objeto de este tipo podría ser indexados, aunque sólo fuera temporal y no de la duración de almacenamiento estático (5.19/2, justo después de que el fragmento anterior):

[constexpr permite lvalue-a-rvalue conversión de] ... un glvalue de tipo literal que se refiere a un objeto temporal no volátil cuyo tiempo de vida no ha terminado, inicializado con una expresión constante

Esto es particularmente extraño, ya que teniendo el lvalue de un objeto temporal es usualmente "c calefacción." Supongo que esta regla se aplica a funcionar argumentos de tipo de referencia, como en

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 

Por lo que vale la pena, GCC 4.7 acepta get_1("hello") pero rechaza "hello"[1] porque "el valor de' ._0' no es utilizable en una constante expresión "... aún "hello"[1]es aceptable como una etiqueta de caso o una matriz encuadernada.

Estoy dividiendo algunos pelos Standardese aquí ... ¿el análisis es correcto, y hubo alguna intención de diseño para esta función?

EDITAR: Oh ... hay algo de motivación para esto. Parece que este tipo de expresión es la única forma de usar una tabla de búsqueda en el preprocesador. Por ejemplo, esto introduce un bloque de código que se ignora a menos SOME_INTEGER_FLAG es 1 o 5, y causa un diagnóstico si es mayor de 6:

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

Este constructo sería nuevo en C++ 11.

Respuesta

6

La intención es que esto funcione y los párrafos que establezcan cuándo es válida una conversión lvalue a rvalue be amended with a note que establece que un lvalue que se refiere a un subobjeto de una cadena literal es un objeto entero constante inicializado con una expresión constante (que se describe como uno de los casos permitidos) en un borrador posterior a C++ 11.

Su comentario sobre el uso dentro del preprocesador parece interesante, pero no estoy seguro de si está destinado a funcionar. Me enteré de esto la primera vez.

+0

Creo que las notas no son normativas, ¿por qué? –

+2

Creo que el punto es que la redacción ya admite esta interpretación, simplemente no es lo suficientemente obvio y había dudas; de ahí una nota para ayudar a interpretar este caso particular de la esquina. De todos modos, eso es una noticia increíble. –

+1

¡Interesante! Como el caso 2 en 5.19 lvalue-to-rvalue conversion se refiere a subobjects, no estaba seguro de si el caso 1 aplicado a los miembros de matrices. Entonces, hay mucha superposición entre esos casos. En cuanto al truco del preprocesador ... '# if' se basa en aplastar identificadores hasta' 0' para desinfectar expresiones constantes. Luego se aplica 16.1/4, "Los tokens resultantes comprenden la expresión constante de control que se evalúa de acuerdo con las reglas de 5.19 usando una aritmética que tiene al menos los rangos especificados en 18.3". Ahora que lo pienso, una cadena con sufijo UD es inmune a la conversión '0'. ¡UH oh! – Potatoswatter

1

En relación con su pregunta sobre #if, el comité de normas no tenía la intención de aumentar el conjunto de expresiones que se pueden usar en el preprocesador, y la redacción actual se considera un defecto. Esto se incluirá en la lista como la cuestión central 1436 en el envío de correos post Kona WG21. Gracias por traer esto a nuestra atención!

+0

[DR 366] (http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#366) cubre el problema de preprocesamiento condicional en términos de §5.19. Aparentemente, el borrador de trabajo del estándar fue parcheado, pero la corrección fue sobrescrita por un cambio posterior. Probablemente la nueva corrección pertenece al §16, ya que la intención actual es tener poderosas expresiones constantes. – Potatoswatter

Cuestiones relacionadas