¿Por qué debe construirse una cadena en tiempo de ejecución? [duplicar]


Esta pregunta ya tiene una respuesta aquí:

¿Se pueden crear cadenas C o std::string como constexpr o deben crearse en tiempo de ejecución?

Con gcc 4.9.2 puedo hacer esto:

constexpr const char foo[] = "blee";

(Lamentablemente, la Vista Previa de la tecnología del Cliente de noviembre de 2013 no permite que Visual Studio apoyo esto: https://stackoverflow.com/a/29255013/2642059)

Pero incluso con gcc 4.9.2 no puedo hacer esto:

constexpr const std::string foo = "blee";

Obtengo el error:

error: the type 'const string {aka const std::basic_string<char>}' of constexpr variable 'foo' 
       is not literal

 constexpr const std::string foo = "blee";
                                   ^
note: 'std::basic_string<char>' is not literal because:
     class basic_string
           ^
note:   'std::basic_string<char>' has a non-trivial destructor

Pero me gustaría más aclaración sobre por qué a std::string no es literal. Es decir: ¿Por qué debe construirse una cadena en tiempo de ejecución?

Como se ha señalado, esta pregunta puede responderse parcialmente con esto: ¿Es posible usar std::string en un constexpr? pero no toca la ¿por qué std::string no puede ser un literal que es el núcleo de la pregunta.

Author: Community, 2015-03-25

2 answers

Hay una propuesta para una cadena constexpr : Cadena en tiempo de compilación: std:: string_literal y dice:

El propósito de std::string_literal, al igual que std::string, es proporcione una utilidad conveniente para trabajar con texto. A diferencia de std::string, una instanciación de std::string_literal es un literal tipo y así se puede utilizar en tiempo de compilación. Es decir, puede ser el tipo de un objeto constexpr, y puede ser el tipo de un parámetro, valor devuelto o variable local de un constexpr function

Que también confirma que efectivamente std::string no es un tipo literal.

Entonces, ¿por qué no simplemente hacer std::string un tipo literal?

Obtenemos una pista de por qué de la propuesta anterior por qué esto no es posible:

Esto requeriría un cambio masivo del lenguaje central para hacer algo como la memoria dinámica disponible en tiempo de compilación, o para hacer algo como VLA / ARB y permitirlos en tipos literales. Dada la violencia reacción negativa de Rapperswil Evolución no solo a N4025 (Clases de tamaño de Tiempo de ejecución), pero cualquier cosa que se asemeje vagamente a VLA / ARBs, puede esperar que esto no suceda en el corto plazo, por lo que esta idea es un sin principio.

std::string requiere memoria dinámica que no está disponible en tiempo de compilación.

Por qué constexpr no se puede aplicar a std:: string sino a array de char

constexpr aplicado a un objeto se aplicará a un tipo literal que no se aplica a std::string, pero se aplica a una matriz de const char. Del borrador de la sección estándar de C++117.1.5 [dcl.constexpr] (énfasis mío en el futuro):

Un especificador constexpr utilizado en una declaración de objeto declara el objeto como const. Tal objeto tendrá el tipo literal y ser inicializado. Si es inicializado por una llamada de constructor, que call será una expresión constante (5.19). […]

Y de la sección 3.9 [básico.tipos]:

Un tipo es un tipo literal si es:

E incluye:

  • un tipo escalar; o
  • una matriz de tipo literal

Los tipos aritméticos son tipos escalares e incluyen char , que cubre la matriz de const char

Y para las clases:

Un tipo de clase (Cláusula 9) que tiene todas las propiedades siguientes:

  • tiene un destructor trivial,
  • cada llamada de constructor y expresión completa en los inicializadores brace-or-equal para miembros de datos no estáticos (si los hay) es una expresión constante (5.19),
  • es un tipo agregado (8.5.1) o tiene al menos un constructor o plantilla de constructor constexpr que no es una copia o movimiento constructor , y
  • todos sus miembros de datos y clases base no-static son de tipos literales.

std::string no cumple con ese criterio.

 27
Author: Shafik Yaghmour,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-30 20:49:12

No puedes usar constexpr, porque std::string no tiene un destructor trivial . Compruebe los requisitos en cppreference.

 5
Author: XapaJIaMnu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-25 12:19:12