本讲我们继续易用性的话题,看看现代 C++ 带来的其他易用性改进。
自定义字面量
字面量(literal)是指在源代码中写出的固定常量,它们在 C++98 里只能是原生类型,如:
"hello",字符串字面量,类型是 const char[6]
1,整数字面量,类型是 int
0.0,浮点数字面量,类型是 double
3.14f,浮点数字面量,类型是 float
123456789ul,无符号长整数字面量,类型是 unsigned long
C++11 引入了自定义字面量,可以使用 operator"" 后缀 来将用户提供的字面量转换成实际的类型。C++14 则在标准库中加入了不少标准字面量。下面这个程序展示了它们的用法:
#include <chrono>
#include <complex>
#include <iostream>
#include <string>
#include <thread>
using namespace std;
int main()
{
cout << "i * i = " << 1i * 1i
<< endl;
cout << "Waiting for 500ms"
<< endl;
this_thread::sleep_for(500ms);
cout << "Hello world"s.substr(0, 5)
<< endl;
}
输出是:
i * i = (-1,0)
Waiting for 500ms
Hello
上面这个例子展示了 C++ 标准里提供的帮助生成虚数、时间和 basic_string 字面量的后缀。一个需要注意的地方是,我在上面使用了 using namespace std,这会同时引入 std 名空间和里面的内联名空间(inline namespace),包括了上面的字面量运算符所在的三个名空间:
std::literals::complex_literals
std::literals::chrono_literals
std::literals::string_literals
在产品项目中,一般不会(也不应该)全局使用 using namespace std(不过,为节约篇幅起见,专栏里的很多例子,特别是不完整的例子,还是默认使用了 using namespace std)。这种情况下,应当在使用到这些字面量的作用域里导入需要的名空间,以免发生冲突。在类似上面的例子里,就是在函数体的开头写:
using namespace std::literals::
chrono_literals;
等等。
要在自己的类里支持字面量也相当容易,唯一的限制是非标准的字面量后缀必须以下划线 _ 打头。比如,假如我们有下面的长度类:
struct length {
double value;
enum unit {
metre,
kilometre,
millimetre,
centimetre,
inch,
foot,
yard,
mile,
};
static constexpr double factors[] =
{1.0, 1000.0