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
, comostd::string
, es proporcionar una utilidad práctica para trabajar con texto. A diferencia destd::string
, una instanciación destd::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 objetoconstexpr
, y puede ser el tipo de un parámetro, valor de retorno o variable local de una funciónconstexpr
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 esconst
. 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í:
- ¿Es posible usar std :: string en un constexpr? 3 respuestas
¿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.