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_km5-6) literales de punto flotante definidos por el usuario, como 0.5_Pa7) literal de carácter definido por el usuario, como 'c'_X8) 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
operatorliteral-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)