繁体   English   中英

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

[英]What are use cases for structured bindings?

C++17 标准引入了一个新的结构化绑定特性,该特性最初在 2015 年提出的,其语法外观后来被广泛讨论

当您查看文档时,就会想到它们的一些用途。

聚合分解

让我们声明一个元组:

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++ 代码的可读性甚至性能?

笔记

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

您能否为结构化绑定提供一些其他可能不太明显的用例? 它们还能如何提高 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;
    }
}

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

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

除非有相反的证据,我认为结构化绑定只是处理遗留 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;

等。

当然,有人会在某个时候找到一个巧妙的用途,但对我来说,在了解它们一年后,它们仍然是一个未解之谜。 特别是因为这篇论文是由 Bjarne 合着的,Bjarne 通常不以介绍具有如此狭窄适用性的特性而闻名。

在一个 if 语句中初始化多个不同类型的变量; 例如,

if (auto&& [a, b] = std::pair { std::string { "how" }, 4U }; a.length() < b)
   std::cout << (a += " convenient!") << '\n';

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM