Coding的痕迹

一位互联网奔跑者的网上日记

0%

C++中的用户定义字面量

   晚上在写一段多线程程序时,在C++标准库中发现了这样的写法,让我很惊讶:

1
this_thread::sleep_for(2s);

Ctrl + Click 点进去看,函数的声明是这样的:

1
2
3
_NODISCARD constexpr chrono::seconds operator"" s(unsigned long long _Val) noexcept /* strengthened */ {
return chrono::seconds(_Val);
}

  像是重载了双引号的写法,翻了翻 cppreference ,原来叫用户定义字面量(字面值)。

  用户定义字面量的后缀可以跟在十进制、八进制、十六进制、二进制、分数常量、数字序列、字符和字符串字面量后,其实就是不同内置字面量的类型加上自定义后缀,可以经过自定义方法将字面值转换成自定义的值的表示。用户字面量不能与内嵌的一些字面量冲突(如不能重载 LL,C++标准中表示 long long)。

  以整数举个例子吧,写一个函数把分钟字面值转换成秒(程序内部的单位):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using minute = unsigned long long;
using second = unsigned long long;

// 此处编译器警告, 应该加个下划线以便与保留的字面量区分
// warning C4455: 'operator ""min':
// literal suffix identifiers that do not start with an underscore are reserved
second constexpr operator"" min(minute val)
{
return val * 60;
}

int main()
{
std::cout << 10min << std::endl;
return 0;
}

  对于需要转换的类型,标准中也做了规定。如整数必须是 unsigned long long,小数必须是 long double,字符串必须是 const char *。同时,对字符串字面量的字面量运算符还要求需要为下列形式:

1
operator"" T(str, len) 

即,有一个表示字符串字面量长度(不含 '\0' )的参数 len

Cppreference 中还提到了最大吞噬原则(maximal munch rule),引用文中的例子:

1
2
3
4
5
int foo = 1;
int bar = 0xE+foo; // 错误:非法的预处理数字 0xE+foo
int baz = 0xE + foo; // OK

int quux = bar+++++baz; // 错误:bar++ ++ +baz,而非 bar++ + ++baz。

  因此,在对用户定义字面量进行运算时,应注意添加括号或空格以防出错。

  标准库中对复数和时间单位提供了字面量运算符,详见用户定义字面量

希望收获一份惊喜