c++ - valores - ¿Puede una cadena literal ser subíncrita en una expresión constante?
valores literales (2)
Esto es válido, porque una expresión constexpr
puede tomar el valor de "un valor de tipo literal que se refiere a un objeto no volátil definido con constexpr, o que se refiere a un subobjeto de tal objeto" (§5.19 / 2):
constexpr char str[] = "hello, world";
constexpr char e = str[1];
Sin embargo, parece 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 literales de cadena:
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 "array of 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ático.
Parecería que un objeto de este tipo podría ser indexado, si solo fuera temporal y no de duración de almacenamiento estático (5.19 / 2, justo después del fragmento de código anterior):
[
constexpr
permite la conversión de lvalue a rvalue de] ... un valor de tipo literal que se refiere a un objeto temporal no volátil cuya vida útil no ha finalizado, inicializado con una expresión constante
Esto es particularmente extraño ya que tomar el lvalor de un objeto temporal generalmente es "hacer trampa". Supongo que esta regla se aplica a los argumentos de función del 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
Para lo que vale, GCC 4.7 acepta get_1( "hello" )
, pero rechaza "hello"[1]
porque "el valor de ''._0'' no se puede utilizar en una expresión constante" ... sin embargo, "hello"[1]
es aceptable como una etiqueta de caso o una matriz enlazada.
Estoy dividiendo algunos pelos de Standardese aquí ... ¿es correcto el análisis y hubo alguna intención de diseño para esta característica?
EDIT: Oh ... hay un poco 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 que SOME_INTEGER_FLAG
sea 1 o 5, y provoca un diagnóstico si es mayor que 6:
#if "/0/1/0/0/0/1"[ SOME_INTEGER_FLAG ]
Esta construcción sería nueva para C ++ 11.
Con respecto a su pregunta sobre #if
, no fue la intención del comité de estándares aumentar el conjunto de expresiones que se pueden usar en el preprocesador, y la redacción actual se considera un defecto. Esto aparecerá como el problema principal 1436 en el correo posterior a Kona WG21. Gracias por traer esto a nuestra atención!
La intención es que esto funcione, y los párrafos que establecen que cuando una conversión de valor a valor es válida se enmendarán con una nota que indica que un valor que se refiere a un subobjeto de un literal de cadena 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 en absoluto.