概述
C++ 20中引入了一些简化编程工作的语法上的新特性,我们暂且美其名曰:“语法糖”。下面,我们将对这些“语法糖”一一进行介绍。
语法糖1:using enum
假如有一个颜色的枚举类型,其定义如下。
enum class Color
{
Red,
Green,
Blue,
Black,
Purple
};
在C++ 20之前,如果我们想要使用这个枚举类的某个成员,通常需要像下面这样写。
Color clr = Color::Green;
在C++ 20中,引入了using enum。它提供了一种更简洁的方式来在作用域中引入枚举类型的成员,使得在使用枚举成员时,不需要再添加前缀,从而简化了代码的编写。
// 引入Color枚举的所有成员到当前作用域
using enum Color;
// 不需要再写前缀Color::
Color favoriteColor = Green;
语法糖2:Lambda的默认捕获
在 C++ 20之前,Lambda表达式的捕获子句需要显式地列出要捕获的变量(通过 [&]、[=] 或通过逐个列出变量的方式来捕获)。在C++ 20中,允许我们使用默认捕获作为捕获子句的一部分,并在需要时显式地覆盖这些默认值。
在下面的示例代码中,我们定义了一个Lambda函数,并将其赋值给pFunc。[=, &nNumber2]捕获列表中,=表示除了明确指出的nNumber2之外,其他外部变量都按值被捕获,而&nNumber2表示nNumber2按引用被捕获。mutable关键字使得Lambda内的代码可以修改按值捕获的变量副本。在Lambda函数内部,nNumber1++尝试增加按值捕获的nNumber1的副本的值。由于Lambda被声明为mutable,这个操作是允许的,但仅修改了副本,不影响外部的nNumber1。nNumber2++直接增加了按引用捕获的nNumber2的值,这会影响到外部的nNumber2。最终,nNumber1的值为66,nNumber2的值为100。
#include <iostream>
using namespace std;
int main()
{
int nNumber1 = 66;
int nNumber2 = 99;
auto pFunc = [=, &nNumber2]() mutable {
nNumber1++;
nNumber2++;
};
pFunc();
// 输出:66
cout << nNumber1 << endl;
// 输出:100
cout << nNumber2 << endl;
return 0;
}
语法糖3:requires关键字
C++ 20中引入了requires关键字,它是约束和概念特性的核心组成部分。通过使用requires,我们可以定义一个条件。该条件必须为真,以便模板参数或函数参数满足特定的要求。这有助于在编译时捕获错误,提高代码的可读性和可维护性。
#include <iostream>
#include <concepts>
using namespace std;
// requires后面的大括号内声明了对类型T的要求,即类型T的两个实例必须能够相加
template <typename T>
concept Addable = requires(T a, T b)
{
a + b;
};
template <Addable T>
T Add(T x, T y)
{
return x + y;
}
int main()
{
// 由于整型支持加法,故下面的调用是合法的
cout << Add(66, 99) << endl;
// 如果尝试使用不支持加法操作的类型,则编译会报错
// cout << Add("Hello", "Hope") << endl;
return 0;
}
语法糖4:常用的数学常量
C++ 20通过<numbers>头文件引入了一系列的数学常量,这些常量提供了精确的浮点数表示,使得在需要高精度的场景下非常有用。
#include <iostream>
#include <numbers>
using namespace std;
int main()
{
// 圆周率
cout << numbers::pi_v<double> << endl;
// 自然对数的底
cout << numbers::e_v<double> << endl;
// 黄金比例
cout << numbers::phi_v<double> << endl;
// 2的对数的倒数
cout << numbers::log2e_v<double> << endl;
// 10的对数的倒数
cout << numbers::log10e_v<double> << endl;
return 0;
}