User-defined literals
自C++11%29以来用户定义的文字数%28
允许整数、浮点、字符和字符串文本通过定义用户定义的后缀来生成用户定义类型的对象.
句法
用户定义的文字是下列任何形式之一的表达式.
decimal-literal ud-suffix | (1) | |
---|---|---|
octal-literal ud-suffix | (2) | |
hex-literal ud-suffix | (3) | |
binary-literal ud-suffix | (4) | |
fractional-constant exponent-part(optional) ud-suffix | (5) | |
digit-sequence exponent-part ud-suffix | (6) | |
character-literal ud-suffix | (7) | |
string-literal ud-suffix | (8) | |
1-4%29个用户定义的整数字面值,如12_km
5-6%29个用户定义的浮点文字,如0.5_Pa
7%29个用户定义字符文字,如'c'_X
8%29用户定义的字符串文本,如"abd"_L
或u16"xyz"_M
decimal-literal | - | same as in integer literal, a non-zero decimal digit followed by zero or more decimal digits |
---|---|---|
octal-literal | - | same as in integer literal, a zero followed by zero or more octal digits |
hex-literal | - | same as in integer literal, 0x or 0X followed by one or more hexadecimal digits |
binary-literal | - | same as in integer literal, 0b or 0B followed by one or more binary digits |
digit-sequence | - | same as in floating literal, a sequence of decimal digits |
fractional-constant | - | same as in floating literal, either a digit-sequence followed by a dot (123.) or an optional digit-sequence followed by a dot and another digit-sequence (1.0 or .12) |
exponent-part | - | same as in floating literal, the letter e or the letter E followed by optional sign, followed by digit-sequence |
character-literal | - | same as in character literal |
string-literal | - | same as in string literal, including raw string literals |
ud-suffix | - | an identifier, introduced by a literal operator or a literal operator template declaration (see below). All ud-suffixes introduced by a program must begin with the underscore character _. The standard library ud-suffixes do not begin with underscores. |
In the integer and floating-point digit sequences, optional separators ' are allowed between any two digits and are ignored | (since C++14) |
---|
如果令牌与用户定义的文字语法和常规文字语法相匹配,则假定它是常规文字%28,也就是说,它不可能过载。LL
在123LL
29%。
当编译器遇到用户定义的带有ud-后缀的文字时X
,它执行非限定名查找,查找具有名称的函数。operator "" X
如果查找找不到声明,程序就不正确。否则,
1%29用于用户定义的整数字面值
如果重载集包含具有参数类型的文字运算符,则为%29unsigned long long
,则将用户定义的文字表达式视为函数调用。operator "" X(nULL)
,其中n是没有ud-后缀的文字。
B%29否则,重载集必须包含原始文字运算符或原始文字运算符模板,但不能同时包含这两个运算符。如果重载集包含原始文字运算符,则用户定义的文字表达式将被视为函数调用。operator "" X("n")
否则,如果重载集包含原始文字运算符模板,则用户定义的文字表达式将被视为函数调用。operator "" X<'c1', 'c2', 'c3'..., 'ck'>(),其中C1.……ck是n...
2%29用于用户定义的浮点文字,
如果重载集包含具有参数类型的文字运算符,则为%29long double
,则将用户定义的文字表达式视为函数调用。operator "" X(fL)
,在哪里f
是没有ud-后缀的文字。
B%29否则,重载集必须包含原始文字运算符或原始文字运算符模板,但不能同时包含这两个运算符。如果重载集包含原始文字运算符,则用户定义的文字表达式将被视为函数调用。operator "" X("f")
否则,如果重载集包含原始文字运算符模板,则用户定义的文字表达式将被视为函数调用。operator "" X<'c1', 'c2', 'c3'..., 'ck'>(),其中C1.……ck是f...
3%29对于用户定义的字符串文本,用户定义的文字表达式被视为函数调用。operator "" X (str, len)
,在哪里str
是没有ud-后缀的文字,并且len
它的长度不包括终止空字符。
4%29对于用户定义的字符文本,用户定义的文字表达式被视为函数调用。operator "" X (ch)
,在哪里ch
是没有ud-后缀的文字。
二次
long double operator "" _w(long double
std::string operator "" _w(const char16_t*, size_t
unsigned operator "" _w(const char*
int main() {
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
}
二次
当字符串文本连接发生在翻译阶段6,用户定义的字符串文本也被连接起来,它们的ud-后缀为连接目的而被忽略,但在所有级联字面值上只能出现一个后缀:
二次
int main() {
L"A" "B" "C"_x; // OK: same as L"ABC"_x
"P"_x "Q" "R"_y;// error: two different ud-suffixes (_x and _y)
}
二次
文字运算符
由用户定义的文字调用的函数称为文字运算符
%28或,如果它是一个模板,文字运算符模板
29%。它和任何其他的声明一样功能或功能模板在命名空间范围%28中,它也可能是一个朋友函数、函数模板的显式实例化或专门化,或者是由使用声明%29引入的,但以下限制除外:
此函数的名称可以有以下两种形式之一:
operator "" identifier | | |
---|---|---|
operator user-defined-string-literal (since C++14) | | |
identifier | - | the identifier to use as the ud-suffix for the user-defined literals that will call this function. Must begin with the underscore _: the suffixes that do not begin with the underscore are reserved for the literal operators provided by the standard library. |
---|---|---|
user-defined-string-literal | - | the character sequence "" followed, without a space, by the character sequence that becomes the ud-suffix. This special syntax makes it possible to use language keywords and reserved identifiers as ud-suffixes, and is used by the declaration of operator ""if from the header <complex>. Note that using this form does not change the rules that user-defined literal operators must begin with an underscore: declarations such as operator ""if may only appear as part of a standard library header. However, it allows the use of an underscore followed by a capital letter (which is otherwise a reserved identifier) |
如果文字运算符是模板,它必须有一个空参数列表,并且只能有一个模板参数,这必须是一个非类型模板参数包,并带有元素类型char。
二次
template <char...> double operator "" _x(
二次
在文字运算符上只允许下列参数列表:
( const char * ) | (1) | |
---|---|---|
( unsigned long long int ) | (2) | |
( long double ) | (3) | |
( char ) | (4) | |
( wchar_t ) | (5) | |
( char16_t ) | (6) | |
( char32_t ) | (7) | |
( const char * , std::size_t ) | (8) | |
( const wchar_t * , std::size_t ) | (9) | |
( const char16_t * , std::size_t ) | (10) | |
( const char32_t * , std::size_t ) | (11) | |
具有此参数列表的1%29个文字运算符是原始文字运算符
,用作整数和浮点用户定义的文本%28的回退(见%29以上)。
2%29个包含这些参数列表的文字运算符是用户定义的整数字面值的首选文字运算符。
3%29个包含这些参数列表的文字运算符是用户定义的浮点文字的首选文字运算符。
具有这些参数列表的4-7%29个文字运算符由用户定义的字符文本调用。
具有这些参数列表的8-11%29个文字运算符由用户定义的字符串文本调用。
默认参数是不允许的。
丙语言链接是不允许的。
除上述限制外,文字运算符和文字运算符模板是正常函数%28和函数模板%29,它们可以被内联或转换,它们可以有内部或外部链接,可以显式调用,它们的地址可以取下来等等。
二次
void operator "" _km(long double // OK, will be called for 1.0_km
std::string operator "" _i18n(const char*, std::size_t // OK
template <char...> double operator "" _π( // OK
float operator ""_e(const char* // OK
float operator ""Z(const char* // error: suffix must begin with underscore
double operator"" _Z(long double // error: all names that begin with underscore
// followed by uppercase letter are reserved
double operator""_Z(long double // OK: even though _Z is reserved ""_Z is allowed
二次
注记
自从引入用户定义的文字之后,使用格式化固定宽度整数类型的宏常量在前面的字符串文字无效后没有空格:std::printf
("%"
PRId64
"\n",
INT64_MIN
必须
由std::printf
("%"
PRId64
"\n",
INT64_MIN
由于最大munch,用户定义的整数和浮点文字以p
,,,P
,%28自C+
+
17%29e
和E
,当接线员跟在后面的时候+
或-
,必须与源中空白的操作符分隔:
二次
long double operator""_E(long double
long double operator""_a(long double
int operator""_p(unsigned long long
auto x = 1.0_E+2.0; // error
auto y = 1.0_a+2.0; // OK
auto z = 1.0_E +2.0; // OK
auto w = 1_p+2; // error
auto u = 1_p +2; // OK
二次
否则,单个无效的预处理数字令牌%28e。g.1.0_E+2.0
%29已形成,这将导致编译失败。
实例
二次
#include <iostream>
// used as conversion
constexpr long double operator"" _deg ( long double deg )
{
return deg*3.141592/180;
}
// used with custom type
struct mytype
{
mytype ( unsigned long long m):m(m){}
unsigned long long m;
};
mytype operator"" _mytype ( unsigned long long n )
{
return mytype(n
}
// used for side-effects
void operator"" _print ( const char* str )
{
std::cout << str;
}
int main(){
double x = 90.0_deg;
std::cout << std::fixed << x << '\n';
mytype y = 123_mytype;
std::cout << y.m << '\n';
0x123ABC_print;
}
二次
产出:
二次
1.570796
123
0x123ABC
二次
标准库
在标准库中定义了下列文字运算符。
定义在内联命名空间std::文本::Complex中[医]文字
*。
运算符“ifOperator”“iOperator”“il%28C++14%29A std:复数”表示纯虚数%28函数%29
定义在内联命名空间std::文本::chrono中[医]文字
操作符“h%28C++14%29
操作符“min”%28C++14%29
运算符“s%28C++14%29
操作符ms%28C++14%29
操作符“”US%28C++14%29
运算符ns%28C++14%29
定义在内联命名空间std::alals::string中[医]文字
运算符“s%28C++14%29将字符数组文字转换为Basic[医]字符串%28功能%29
定义在内联命名空间std::alals::string中[医]视点[医]文字
运算符“SV%28C++17%29”创建字符数组文字%28函数%29的字符串视图。
© cppreference.com
在CreativeCommonsAttribution下授权-ShareAlike未移植许可v3.0。