C ++ 17标准引入了一个新的structured bindings功能,该功能在2015年最初为proposed,其句法外观后来广泛discussed。
一旦查看文档,就会想到它们的一些用途。
汇总分解
让我们宣布一个元组:
std::tuple<int, std::string> t(42, "foo");
使用结构化绑定可以很容易地获得命名的元素副本:
auto [i, s] = t;
相当于:
auto i = std::get<0>(t);
auto s = std::get<1>(t);
或
int i;
std::string s;
std::tie(i, s) = t;
也可以毫不费力地获得对元组元素的引用:
auto& [ir, sr] = t;
const auto& [icr, scr] = t;
所以我们可以使用所有成员都是公共的数组或结构/类。
多个返回值
从函数中获取多个返回值的便捷方法如下所示。
还有什么?
您能为结构化绑定提供一些其他可能不那么明显的用例吗?他们还能如何提高C ++代码的可读性甚至性能?
备注
正如评论中提到的,结构化绑定的当前实现缺少一些功能。它们是非可变参数,并且它们的语法不允许显式跳过聚合成员。 Here可以找到关于可变量的讨论。
答案 0 :(得分:13)
您能为结构化绑定提供一些其他可能不那么明显的用例吗?他们还能如何提高C ++代码的可读性甚至性能?
更一般地说,您可以使用它(让我说)解压缩一个结构并从中填充一组变量:
struct S { int x = 0; int y = 1; };
int main() {
S s{};
auto [ x, y ] = s;
(void)x, void(y);
}
另一种方式是:
struct S { int x = 0; int y = 1; };
int main() {
S s{};
auto x = s.x;
auto y = s.y;
(void)x, void(y);
}
数组也是如此:
int main() {
const int a[2] = { 0, 1 };
auto [ x, y ] = a;
(void)x, void(y);
}
无论如何,因为当你从一个函数返回结构或数组时它也起作用,可能你可以说这些例子属于你已经提到的同一组例子。
@TobiasRibizel在回答评论中提到的另一个好例子是可以迭代容器并轻松解开内容。
作为基于std::map
的示例:
#include <map>
#include <iostream>
int main() {
std::map<int, int> m = {{ 0, 1 }, { 2, 3 }};
for(auto &[key, value]: m) {
std::cout << key << ": " << value << std::endl;
}
}
答案 1 :(得分:9)
您能为结构化绑定提供一些其他可能不那么明显的用例吗?
它们可用于为结构体实施get<N>
- 请参阅magic_get
's automatically generated core17_generated.hpp
。这很有用,因为它提供了一种原始形式的静态反射(例如迭代struct
的所有成员。
答案 2 :(得分:1)
除非有相反的证据,我认为结构化绑定仅仅是处理遗留API的工具。恕我直言,需要修改需要SB的API。
所以,而不是
auto p = map.equal_range(k);
for (auto it = p.first; it != p.second; ++it)
doSomethingWith(it->first, it->second);
我们应该能够写
for (auto &e : map.equal_range(k))
doSomethingWith(e.key, e.value);
而不是
auto r = map.insert({k, v});
if (!r.second)
*r.first = v;
我们应该能够写
auto r = map.insert({k, v});
if (!r)
r = v;
等
当然,有人会在某些时候找到一个聪明的用途,但对我来说,经过一年的了解,他们仍然是一个未解之谜。 ESP。因为这篇论文是由Bjarne共同撰写的,Bjarne通常不会引入具有如此狭隘适用性的特征。
答案 3 :(得分:1)
在if语句中初始化不同类型的多个变量;例如,
if (auto&& [a, b] = std::pair { std::string { "how" }, 4U }; a.length() < b)
std::cout << (a += " convenient!") << '\n';