Nuestro team de redactores ha estado horas buscando la respuesta a tu duda, te regalamos la respuestas por esto esperamos que te resulte de mucha apoyo.
Permite que los literales enteros, de coma flotante, de caracteres y de cadena produzcan objetos de tipo definido por el usuario mediante la definición de un sufijo definido por el usuario.
Sintaxis
Un literal definido por el usuario es una expresión de cualquiera de las siguientes formas.
literal-decimalsufijo ud | (1) | |
literal-octalsufijo ud | (2) | |
literal hexadecimalsufijo ud | (3) | |
literal-binariosufijo ud | (4) | |
constante fraccionalexponente-parte(Opcional)sufijo ud | (5) | |
secuencia de dígitosexponente-partesufijo ud | (6) | |
carácter-literalsufijo ud | (7) | |
literal de cadenasufijo ud | (8) |
1-4) literales enteros definidos por el usuario, como 12_km
5-6) literales de punto flotante definidos por el usuario, como 0.5_Pa
7) literal de carácter definido por el usuario, como 'c'_X
8) literal de cadena definida por el usuario, como "abd"_L
o u"xyz"_M
literal-decimal | – | igual que en el literal entero, un dígito decimal distinto de cero seguido de cero o más dígitos decimales |
literal-octal | – | igual que en el literal entero, un cero seguido de cero o más dígitos octales |
literal hexadecimal | – | igual que en el literal entero, 0x o 0X seguido de uno o más dígitos hexadecimales |
literal-binario | – | igual que en el literal entero, 0b o 0B seguido de uno o más dígitos binarios |
secuencia de dígitos | – | igual que en literal flotante, una secuencia de dígitos decimales |
constante fraccional | – | igual que en literal flotante, ya sea un secuencia de dígitos seguido de un punto (123. ) o un opcional secuencia de dígitos seguido de un punto y otro secuencia de dígitos (1.0 o .12 ) |
exponente-parte | – | igual que en literal flotante, la letra e o la carta E seguido de un signo opcional, seguido de secuencia de dígitos |
carácter-literal | – | igual que en el carácter literal |
literal de cadena | – | igual que en el literal de cadena, incluidos los literales de cadena sin formato |
sufijo ud | – | un identificador, introducido por un operador literal o un plantilla de operador literal declaración (ver más abajo). Todos sufijo udLos introducidos por un programa deben comenzar con el carácter de subrayado. _ . La biblioteca estándar sufijo udno comienzan con guiones bajos. |
En las secuencias de dígitos enteros y de coma flotante, separadores opcionales ' se permiten entre dos dígitos y se ignoran |
(desde C ++ 14) |
Si un token coincide con una sintaxis literal definida por el usuario y una sintaxis literal regular, se supone que es un literal regular (es decir, es imposible sobrecargar LL
en 123LL
).
Cuando el compilador encuentra un literal definido por el usuario con sufijo udX
, realiza una búsqueda de nombre no calificado, buscando una función con el nombre operator "" X
. Si la búsqueda no encuentra una declaración, el programa está mal formado. De lo contrario,
1) Para literales enteros definidos por el usuarioa) si el conjunto de sobrecarga incluye un operador literal con el tipo de parámetro unsigned long long
, la expresión literal definida por el usuario se trata como una llamada de función operator "" X(nULL)
, donde n es el literal sin sufijo udB) de lo contrario, el conjunto de sobrecarga debe incluir, pero no ambos, un operador literal sin formato o una plantilla de operador literal numérico. Si el conjunto de sobrecarga incluye un operador literal sin formato, la expresión literal definida por el usuario se trata como una llamada de función. operator "" X("n")
C) de lo contrario, si el conjunto de sobrecarga incluye una plantilla de operador literal numérico, la expresión literal definida por el usuario se trata como una llamada de función operator "" X<'c1', 'c2', 'c3'..., 'ck'>()
, donde c1..ck son los caracteres individuales de n
.2) Para literales de punto flotante definidos por el usuario,a) Si el conjunto de sobrecarga incluye un operador literal con el tipo de parámetro long double
, la expresión literal definida por el usuario se trata como una llamada a función operator "" X(fL)
, dónde f
es el literal sin sufijo udB) de lo contrario, el conjunto de sobrecarga debe incluir, pero no ambos, un operador literal sin formato o una plantilla de operador literal numérico. Si el conjunto de sobrecarga incluye un operador literal sin formato, la expresión literal definida por el usuario se trata como una llamada de función. operator "" X("f")
C) de lo contrario, si el conjunto de sobrecarga incluye una plantilla de operador literal numérico, la expresión literal definida por el usuario se trata como una llamada de función operator "" X<'c1', 'c2', 'c3'..., 'ck'>()
, donde c1..ck son los caracteres individuales de f
.3) Para literales de cadena definidos por el usuario, deje str
ser el literal sin sufijo ud:
a) Si el conjunto de sobrecarga incluye una plantilla de operador literal de cadena con un parámetro de plantilla que no es de tipo para el que str es un argumento de plantilla bien formado, entonces la expresión literal definida por el usuario se trata como una llamada de función operator "" X , |
(desde C ++ 20) |
B) de lo contrario, la expresión literal definida por el usuario se trata como una llamada de función operator "" X (str, len)
, dónde len
es la longitud de la cadena literal, excluyendo el carácter nulo de terminación4) Para los literales de caracteres definidos por el usuario, la expresión literal definida por el usuario se trata como una llamada de función. operator "" X(ch)
, dónde ch
es el literal sin sufijo ud
longdoubleoperator""_w(longdouble); std::string operator""_w(constchar16_t*, size_t);unsignedoperator""_w(constchar*);intmain()1.2_w;// calls operator "" _w(1.2L) u"one"_w;// calls operator "" _w(u"one", 3)12_w;// calls operator "" _w("12")"two"_w;// error: no applicable literal operator
Cuando la concatenación literal de cadena tiene lugar en la fase de traducción 6, las cadenas literales definidas por el usuario también se concatenan, y su sufijo udes se ignoran con el propósito de la concatenación, excepto que solo puede aparecer un sufijo en todos los literales concatenados:
intmain() L"A""B""C"_x;// OK: same as L"ABC"_x"P"_x "Q""R"_y;// error: two different ud-suffixes (_x and _y)
Operadores literales
La función llamada por un literal definido por el usuario se conoce como operador literal (o, si es una plantilla, plantilla de operador literal). Se declara como cualquier otra función o plantilla de función en el ámbito del espacio de nombres (también puede ser una función amiga, una instanciación explícita o especialización de una plantilla de función, o introducida por una declaración de uso), excepto por las siguientes restricciones:
El nombre de esta función puede tener una de estas dos formas:
operator "" identificador |
||
operator literal-cadena-definida-por-usuario(desde C ++ 14) |
identificador | – | el identificador que se utilizará como sufijo ud para los literales definidos por el usuario que llamarán a esta función. Debe comenzar con el guion bajo _ : los sufijos que no comienzan con el subrayado están reservados para los operadores literales proporcionados por la biblioteca estándar. |
literal-cadena-definida-por-usuario | – | la secuencia de caracteres "" seguido, sin espacio, por la secuencia de caracteres que se convierte en el sufijo ud. Esta sintaxis especial hace posible el uso de palabras clave de idioma e identificadores reservados como sufijos ud, y se usa para la declaración de operator ""if desde el encabezado . Tenga en cuenta que el uso de este formulario no cambia las reglas de que los operadores literales definidos por el usuario deben comenzar con un guión bajo: declaraciones como operator ""if solo puede aparecer como parte de un encabezado de biblioteca estándar. Sin embargo, permite el uso de un guión bajo seguido de una letra mayúscula (que de lo contrario es un identificador reservado) |
Si el operador literal es una plantilla, debe tener una lista de parámetros vacía y solo puede tener un parámetro de plantilla, que debe ser un paquete de parámetros de plantilla sin tipo con tipo de elemento char
(en cuyo caso se conoce como plantilla de operador literal numérico).
template<char...>doubleoperator""_x();
o un parámetro de plantilla que no es de tipo de tipo de clase (en cuyo caso se conoce como plantilla de operador literal de cadena). structAA(constchar*);autooperator<=>(const A&)const=default;;template<A a> A operator""_a(); |
(desde C ++ 20) |
Solo se permiten las siguientes listas de parámetros en operadores literales:
( const char * ) |
(1) | |
( unsigned long long int ) |
(2) | |
( long double ) |
(3) | |
( char ) |
(4) | |
( wchar_t ) |
(5) | |
( char8_t ) |
(6) | (desde C ++ 20) |
( char16_t ) |
(7) | |
( char32_t ) |
(8) | |
( const char * , std::size_t ) |
(9) | |
( const wchar_t * , std::size_t ) |
(10) | |
( const char8_t * , std::size_t ) |
(11) | (desde C ++ 20) |
( const char16_t * , std::size_t ) |
(12) | |
( const char32_t * , std::size_t ) |
(13) |
1) Los operadores literales con esta lista de parámetros son los operadores literales sin formato, utilizado como reserva para literales definidos por el usuario de punto flotante y entero (ver más arriba)2) Los operadores literales con estas listas de parámetros son el operador literal de primera elección para literales enteros definidos por el usuario3) Los operadores literales con estas listas de parámetros son el operador literal de primera elección para literales de punto flotante definidos por el usuario4-8) Los operadores literales con estas listas de parámetros son llamados por literales de caracteres definidos por el usuario9-13) Los operadores literales con estas listas de parámetros son llamados por literales de cadena definidos por el usuario
No se permiten argumentos predeterminados.
No se permite la vinculación del lenguaje C.
Aparte de las restricciones anteriores, los operadores literales y las plantillas de operadores literales son funciones normales (y plantillas de funciones), se pueden declarar en línea o constexpr, pueden tener enlaces internos o externos, se pueden llamar explícitamente, se pueden tomar sus direcciones, etc. .
voidoperator""_km(longdouble);// OK, will be called for 1.0_km std::string operator""_i18n(constchar*, std::size_t);// OKtemplate<char...>doubleoperator"" _π();// OKfloatoperator""_e(constchar*);// OKfloatoperator""Z(constchar*);// error: suffix must begin with underscoredoubleoperator""_Z(longdouble);// error: all names that begin with underscore// followed by uppercase letter are reserveddoubleoperator""_Z(longdouble);// OK: even though _Z is reserved ""_Z is allowed
Notas
Desde la introducción de literales definidos por el usuario, el código que usa Formatear constantes de macro para tipos enteros de ancho fijo sin espacio después de que el literal de cadena anterior dejara de ser válido: std::printf("%"PRId64"n",INT64_MIN);
tiene que ser reemplazado por std::printf("%"PRId64"n",INT64_MIN);
Debido al munch máximo, enteros definidos por el usuario y literales de punto flotante que terminan en p
, P
,(desde C ++ 17)e
y E
, cuando es seguido por los operadores +
o -
, debe estar separado del operador con espacios en blanco o paréntesis en la fuente:
longdoubleoperator""_E(longdouble);longdoubleoperator""_a(longdouble);intoperator""_p(unsignedlonglong);auto x =1.0_E+2.0;// errorauto y =1.0_a+2.0;// OKauto z =1.0_E +2.0;// OKauto q =(1.0_E)+2.0;// OKauto w =1_p+2;// errorauto u =1_p +2;// OK
Lo mismo se aplica al operador de punto que sigue a un literal definido por el usuario entero o de punto flotante:
#includeusingnamespace std::literals;auto a =4s.count();// Errorauto b =4s .count();// OKauto c =(4s).count();// OK
De lo contrario, un solo token de número de preprocesamiento no válido (p. Ej., 1.0_E+2.0
o 4s.count
) se forma, lo que hace que falle la compilación.
Ejemplos de
#include// used as conversionconstexprlongdoubleoperator""_deg(longdouble deg )return deg *3.14159265358979323846264L/180;// used with custom typestructmytypeunsignedlonglong m;;constexpr mytype operator""_mytype(unsignedlonglong n )return mytypen;// used for side-effectsvoidoperator""_print(constchar* str ) std::cout << str;intmain()double x =90.0_deg; std::cout << std::fixed << x <<'n'; mytype y =123_mytype; std::cout << y.m <<'n';0x123ABC_print;
Producción:
1.5707961230x123ABC
Biblioteca estándar
Los siguientes operadores literales se definen en la biblioteca estándar.
Definido en el espacio de nombres en línea std::literals::complex_literals |
|
---|---|
operador “” sioperador “” ioperador “” il(C ++ 14) | A std::complex literal que representa un número imaginario puro (función) |
Definido en el espacio de nombres en línea std::literals::chrono_literals |
|
operador “” h(C ++ 14) | A std::chrono::duration literal que representa horas (función) |
operador “” min(C ++ 14) | A std::chrono::duration literal que representa minutos (función) |
operador “” s(C ++ 14) | A std::chrono::duration literal que representa segundos (función) |
operador “” ms(C ++ 14) | A std::chrono::duration literal que representa milisegundos (función) |
operador “” nosotros(C ++ 14) | A std::chrono::duration literal que representa microsegundos (función) |
operador “” ns(C ++ 14) | A std::chrono::duration literal que representa nanosegundos (función) |
operador “” y(C ++ 20) | A std::chrono::year literal que representa un año en particular (función) |
operador “” d(C ++ 20) | A std::chrono::day literal que representa un día de un mes (función) |
Definido en el espacio de nombres en línea std::literals::string_literals |
|
operador “” s(C ++ 14) | Convierte un literal de matriz de caracteres en basic_string (función) |
Definido en el espacio de nombres en línea std::literals::string_view_literals |
|
operador “” sv(C ++ 17) | Crea una vista de cadena de un literal de matriz de caracteres (función) |
Sección de Reseñas y Valoraciones
Si piensas que te ha resultado de utilidad nuestro post, sería de mucha ayuda si lo compartieras con el resto entusiastas de la programación y nos ayudes a dar difusión a este contenido.