Requisitos denominados de C++: LiteralType (desde C++11)
Especifica que un tipo es un tipo literal. Los tipos literales son los tipos de las variables constexpr y pueden construirse, manipularse y devolverse desde funciones constexpr.
Nota: el estándar no define un requisito denominado con este nombre. Esta es una categoría de tipo definida por el lenguaje central. Se incluye aquí como un requisito con nombre solamente por consistencia.
Requisitos
Un tipo literal es cualquiera de los siguientes:
|
(desde C++14) |
- tipo escalar;
- tipo referencia;
- un array de tipos literal;
- un tipo clase, que puede estar calificado-cv, que tiene todas las propiedades siguientes:
- tiene un destructor trivial (hasta C++20)constexpr (desde C++20),
- todos sus miembros de datos no estáticos y no variantes, así como sus clases base, son tipos literales no volátiles, y
- es ya sea
|
(desde C++17) |
- un tipo de unión agregada que
- no tiene miembros variantes, o
- tiene al menos un miembro variante de tipo literal no volátil,
- un tipo agregado no unión, y cada uno de sus miembros unión anónima
- no tiene miembros variantes, o
- tiene al menos un miembro variante de tipo literal no volátil,
- un tipo con al menos un constructor
constexpr(que puede ser una plantilla) que no es un constructor de copia o movimiento.
Notas
Un tipo puede ser literal incluso si todos sus constructores constexpr están eliminados, inaccesibles o no pueden participar en la resolución de sobrecarga.
struct A { constexpr A(int) = delete; char c; }; // A es un tipo literal
constexpr A v = std::bit_cast<A>('0'); // Correcto es C++20
// v tiene tipo literal, con lo que puede ser constexpr
Ejemplo
Tipo literal que extiende los literales de cadena:
#include <cstddef>
#include <iostream>
#include <stdexcept>
class conststr // conststr es un tipo literal
{
const char* p;
std::size_t sz;
public:
template<std::size_t N>
constexpr conststr(const char(&a)[N]) : p(a), sz(N - 1) {}
constexpr char operator[](std::size_t n) const
{
return n < sz ? p[n] : throw std::out_of_range("");
}
constexpr std::size_t size() const { return sz; }
};
constexpr std::size_t count_lower(conststr s)
{
std::size_t c{};
for (std::size_t n{}; n != s.size(); ++n)
if ('a' <= s[n] && s[n] <= 'z')
++c;
return c;
}
// función de salida que requiere una constante
// en tiempo de compilación N, para prueba
template<int N>
struct constN
{
constN() { std::cout << N << '\n'; }
};
int main()
{
std::cout << "el numero de letras minúsculas en \"Hola, mundo!\" es ";
constN<count_lower("Hola, mundo!")>(); // el literal cadena es implícitamente
// convertido a conststr
}
Salida:
el numero de letras minúsculas en "Hola, mundo!" es 8
Informes de defectos
Los siguientes informes de defectos de cambio de comportamiento se aplicaron de manera retroactiva a los estándares de C++ publicados anteriormente.
| ID | Aplicado a | Comportamiento según lo publicado | Comportamiento correcto |
|---|---|---|---|
| CWG 1453 | C++11 | una clase literal podía tener miembros de datos volátiles | no permitido |
| CWG 1951 | C++11 C++14 |
No estaba claro si los tipos void calificado-cv (C++14)y los tipos de clase (C++11) son tipos literales. |
Lo son. |
| CWG 2096 | C++11 | para que un tipo unión sea literal, todos sus miembros no estáticos deben ser literales |
solo se necesita un miembro de datos no estático |
| CWG 2598 | C++11 | para que un tipo unión sea literal, debe tener al menos un miembro de datos no estático |
no puede tener ningún miembro de datos no estático |
Véase también
(C++11)(en desuso en C++17)(eliminado en C++20) |
Comprueba si un tipo es un tipo literal. (plantilla de clase) |