c++ c++11 literals stdstring constexpr

c++ - ¿Por qué debe construirse una cadena en tiempo de ejecución?



c++11 literals (2)

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

El propósito de std::string_literal , como std::string , es proporcionar una utilidad práctica para trabajar con texto. A diferencia de std::string , una instanciación de std::string_literal es un tipo literal y, por lo tanto, puede usarse 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 de retorno o variable local de una función constexpr

lo que también confirma que de hecho std::string no es un tipo literal .

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

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

Esto requeriría un cambio masivo del lenguaje central para hacer que algo como la memoria dinámica esté disponible en tiempo de compilación , o hacer algo como VLA / ARB y permitirlos en tipos literales. Dada la reacción violentamente negativa de Rapperswil Evolution no solo a N4025 (Clases de tamaño de tiempo de ejecución), sino a cualquier cosa que se parezca vagamente a VLA / ARB, podemos esperar que esto no suceda pronto, por lo que esta idea no debe comenzar.

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 of 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 7.1.5 de la norma C ++ 11 [dcl.constexpr] (el énfasis es mío en adelante ):

Un especificador constexpr utilizado en una declaración de objeto declara que el objeto es const . Dicho objeto tendrá un tipo literal y se inicializará . Si se inicializa mediante una llamada de constructor, esa llamada será una expresión constante (5.19). […]

y de la sección 3.9 [tipos de base] :

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 siguientes propiedades:

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

std::string no cumple con esos criterios.

Esta pregunta ya tiene una respuesta aquí:

¿Se pueden crear C-Strings o std::string s como constexpr o se deben crear 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 para clientes de noviembre de 2013 no permite que Visual Studio admita esto: https://stackoverflow.com/a/29255013/2642059 )

Pero incluso con gcc 4.9.2 no puedo hacer esto:

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

Me sale 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 aclaraciones sobre por qué una std::string no es un literal. Es decir: ¿Por qué se debe construir una cadena en tiempo de ejecución?

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


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