结构化绑定
结构化绑定就是将指定的名称和初始化器的子对象或元素绑定。 与引用一样,结构化绑定是现有对象的别名。与引用不同的是,结构化绑定不必是引用类型。
下面展示一些 内联代码片 。
attr(optional) cv-auto ref-qualifier(optional) [ identifier-list ] = expression ; (1)
attr(optional) cv-auto ref-qualifier(optional) [ identifier-list ] { expression } ; (2)
attr(optional) cv-auto ref-qualifier(optional) [ identifier-list ] ( expression ) ; (3)
| |
---|
attr | 任意数量属性的序列 | cv-auto | 可能是 cv 限定的类型说明符是,auto,也可能包括存储类说明符,static 或 thread_local | ref-qualifier | & 或者 && | identifier-list | 此说明引入的,逗号分隔的标识符列表 | expression | 是一个表达式,该表达式在顶层,没有逗号运算符(语法上,是赋值表达式),并且具有数组或非联合类类型。如果表达式引用标识符列表中的任何名称,则说明格式是错误的。 |
绑定数组
标识符列表中的每个标识符都成为一个左值的名称,该左值引用数组的相应元素。标识符的数量必须等于数组元素的数量。 每个标识符的引用类型是数组元素类型。如果数组类型 E 是 cv 限定的,那么它的元素类型也是如此。
例子
int a[2] = {1,2};
auto [x,y] = a;
auto& [xr, yr] = a;
绑定一个tuple类型
表达式 std::tuple_size::value 必须是良定义的整数常量表达式,并且,标识符的数量必须等于 std::tuple_size::value。 对于每个标识符,引用一个变量,该变量的类型是,引入一个类型为,std::tuple_element<i, E>::type 的引用。如果其对应的初始值设定项是左值,则为左值引用,否则为右值引用。第 i 个变量的初始化器是
- e.get(),如果通过类成员访问查找在 E 范围内查找标识符,get 发现至少一个说明是函数模板,其第一个模板参数是非类型参数
- 否则,get(e),其中 get 仅通过依赖于参数的查找来查找,忽略非 ADL 查找。
在这些初始化器表达式中,如果实体 e 的类型是左值引用,则 e 是左值(仅当 ref 限定符是 & 或 &&, 并且初始化器表达式是左值时,才会发生这种情况),否则是 xvalue(这有效地执行一种完美转发),i 是 std::size_t prvalue,并且 <i> 总是被解释为模板参数列表。 该变量具有与 e 相同的存储持续时间。 该标识符然后成为一个左值的名称,该左值引用绑定到所述变量的对象。 第 i 个标识符的引用类型是 std::tuple_element<i, E>::type。
例子
float x{1.0};
char y{‘c'};
int z{5};
std::tuple<float&,char&&,int> tpl(x,std::move(y),z);
const auto& [a,b,c] = tpl;
绑定数据成员
- E 的每个非静态数据成员必须是 E 的直接成员或 E 的相同基类
- 并且在命名为 e.name 时,必须在结构化绑定的上下文中是良定义的。
- E不能有匿名union成员。
- 标识符的数量必须等于非静态数据成员的数量。
标识符列表中的每个标识符都成为一个左值的名称,按说明顺序,该左值引用 e 的下一个成员(支持位字段);左值的类型是 e.m_i 的类型,其中 m_i 指的是第 i 个成员。 第 i 个标识符的引用类型,如果不是引用类型,则为 e.m_i 的类型,否则为 m_i 的说明类型。
例子
#include <iostream>
struct S {
mutable int x1 : 2;
volatile double y1;
};
S f() { return S{1, 2.3}; }
int main() {
const auto [x, y] = f();
std::cout << x << ' ' << y << '\n';
x = -2;
std::cout << x << ' ' << y << '\n';
}
if/switch 的初始化语句
if语句初始化
C++17 扩展了现有 if 语句的语法。可以在 if 语句本身中提供初始条件。这种新语法称为“带有初始化程序的 if 语句”。此增强功能简化了常见的代码模式,并帮助用户保持范围紧凑。这避免了范围外的变量泄漏。
例子
#include <iostream>
#include <cstdlib>
using namespace std;
int main() {
srand(time(NULL));
if (int random_num = rand(); random_num % 2 == 0) {
cout << random_num << " is an even number\n";
} else {
cout << random_num << " is an odd number\n";
}
return 0;
}
if与结构化绑定结合
当与结构化绑定结合使用时,带有初始化器的 if 的用处变得更加明显。 使用结构化绑定将 std::map::insert 的 std::pair 返回值解包为两个单独的变量,it(迭代器)和 Inserted(指示插入是否成功的布尔值)。 然后我们可以通过检查insert,来检查if语句中的插入是否成功。
例子
int main()
{
std::map<std::string, int> map;
map["hello"] = 1;
map["world"] = 2;
if (auto [it, inserted] = map.insert({ "hello", 3 }); !inserted)
std::cout << "hello already exists with value " << it->second << "\n";
if (auto [it, inserted] = map.insert({ "foo", 4 }); !inserted)
std::cout << "foo already exists with value " << it->second << "\n";
return 0;
}
switch语句初始化
与 if 语句一样,我们现在可以在 switch 语句中创建变量。
例子
enum Result
{
SUCCESS,
ABORTED
};
std::pair<size_t , Result> read_message()
{
return { 100, SUCCESS };
}
int main()
{
switch (auto res = read_message(); res.second)
{
case SUCCESS:
std::cout << "successfully wrote " << res.first << " bytes\n";
break;
case ABORTED:
std::cout << "operation aborted before completion\n";
break;
}
return 0;
}
inline变量
constexpr if
例子
#include <iostream>
#include <string>
struct S
{
int n;
std::string s;
float d;
};
template <std::size_t I>
auto& get(S& s)
{
if constexpr (I == 0)
return s.n;
else if constexpr (I == 1)
return s.s;
else if constexpr (I == 2)
return s.d;
}
int main()
{
S obj { 0, "hello", 10.0f };
std::cout << get<0>(obj) << endl;
std::cout << get<1>(obj) << endl;
}
折叠表达式
左结合二元运算符
右结合二元运算符
类模板的模板参数推导
为了实例化一个类模板,必须知道每个模板参数,但这不是说,必须指定每个模板参数。根据上下文,编译器可以从初始器的类型,推导出模板参数。
任何指定变量初始化和变量模板的说明
下面展示一些 内联代码片 。
// A code block
var foo = 'bar';
std::pair p(2, 4.5);
std::tuple t(4, 3, 2.5);
new表达式
例子
template<class T> struct A
{
A(T, T);
};
auto y = new A{1, 2};
auto z = new A{1.5};
函数式式的cast表达式
内联代码片
auto lck = std::lock_guard(mtx);
std::copy_n(vi1, 3,
std::back_insert_iterator(vi2));
std::for_each(vi.begin(), vi.end(),
Foo([&](int i) {...}));
auto 说明非类型模板参数
|