结构化绑定的用例是什么?

时间:2017-08-03 09:56:16

标签: c++ c++17 structured-bindings

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可以找到关于可变量的讨论。

4 个答案:

答案 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';