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

Ser*_*gey 19 c++ c++17 structured-bindings

C++ 17标准引入了一种新的结构化绑定功能,该功能最初于2015年提出,其语法外观在后面被广泛讨论.

一看完文档就会想到它们的一些用途.

聚合分解

让我们宣布一个元组:

std::tuple<int, std::string> t(42, "foo");
Run Code Online (Sandbox Code Playgroud)

命名元素副本可以通过一行中的结构化绑定轻松获得:

auto [i, s] = t;
Run Code Online (Sandbox Code Playgroud)

这相当于:

auto i = std::get<0>(t);
auto s = std::get<1>(t);
Run Code Online (Sandbox Code Playgroud)

要么

int i;
std::string s;
std::tie(i, s) = t;
Run Code Online (Sandbox Code Playgroud)

也可以无痛地获得对元组元素的引用:

auto& [ir, sr] = t;
const auto& [icr, scr] = t;
Run Code Online (Sandbox Code Playgroud)

所以我们可以使用所有成员都是公共的数组或结构/类.

多个返回值

从上面可以直接获得从函数中获取多个返回值的便捷方法.

还有什么?

你能为结构化绑定提供一些其他的,可能不太明显的用例吗?他们还能如何提高C++代码的可读性甚至性能?

笔记

正如评论中提到的,结构化绑定的当前实现缺少一些功能.它们是非可变参数,并且它们的语法不允许显式跳过聚合成员.在这里可以找到关于可变性的讨论.

sky*_*ack 17

你能为结构化绑定提供一些其他的,可能不太明显的用例吗?他们还能如何提高C++代码的可读性甚至性能?

更一般地说,您可以使用它来(让我说)解压缩一个结构并从中填充一组变量:

struct S { int x = 0; int y = 1; };

int main() {
    S s{};
    auto [ x, y ] = s;
    (void)x, void(y);
}
Run Code Online (Sandbox Code Playgroud)

另一种方式是:

struct S { int x = 0; int y = 1; };

int main() {
    S s{};
    auto x = s.x;
    auto y = s.y;
    (void)x, void(y);
}
Run Code Online (Sandbox Code Playgroud)

数组也是如此:

int main() {
    const int a[2] = { 0, 1 };
    auto [ x, y ] = a;
    (void)x, void(y);
}
Run Code Online (Sandbox Code Playgroud)

无论如何,因为当你从一个函数返回结构或数组时也可以工作,可能你可以争辩说这些例子属于你已经提到过的同一组例子.


@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;
    }
}
Run Code Online (Sandbox Code Playgroud)


Vit*_*meo 9

你能为结构化绑定提供一些其他的,可能不太明显的用例吗?

它们可用于实现get<N>结构 - 请参见magic_get自动生成的结构core17_generated.hpp.这很有用,因为它提供了一种原始形式的静态反射(例如,迭代a的所有成员struct).