【问题标题】:Why structured bindings only work with auto为什么结构化绑定仅适用于 auto
【发布时间】:2017-10-16 07:02:55
【问题描述】:

Structured bindings 已在 c++17 中引入。它们能够声明从元组或结构初始化的多个变量。

此代码使用c++17 编译器进行编译。

#include <iostream>
#include <tuple>

int main() {
    auto tuple = std::make_tuple(1.0, 1);

    auto [ d, i ] = tuple;

    std::cout << "d=" << d << " i=" << i <<  '\n';

    return 0;
}

如果我不使用auto 声明变量,我会收到错误消息

错误:预期的 lambda 表达式主体 [d2 , i2] = 元组;

#include <iostream>
#include <tuple>

int main() {
    auto tuple = std::make_tuple(1.0, 2);

    double d2;
    int i2;

    [d2 , i2] = tuple;

    return 0;
}

我使用了clang version 4.0.0 和编译选项-std=c++1z

我可以将现有变量分配给结构化绑定吗?我需要使用auto吗?

【问题讨论】:

  • 结构化绑定只有在定义和初始化变量时才有可能。这是不可能的一般任务(为此使用std::tie)。

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


【解决方案1】:

您收到的错误消息很好地说明了为什么它只允许使用 auto:缺乏歧义,这将使语法更加依赖于上下文。

表达式开头的一对方括号表示一个 lambda。您所要求的是标准指定 有时 [d2 , i2] 是一个 lambda 的开头,它按值捕获 d2i2,而在 其他时间 这是一个拆包任务。一切都基于它后面的内容。

将它添加到语言中是不值得的。尤其是,自从 as Some programmer dude noted 以来,您已经有了 std::tie 来对元组做您想做的事情。

不仅如此,std::tie 还允许您忽略一些未打包的值,这是结构化绑定尚不支持的。所以这一切都归结为拥有一种更有限形式的语法糖,来做一些标准库已经用元组做的事情。


哦,如果您对 std::tie 仅适用于元组感到不满,您可以自己将其扩展为适用于任何 POD。看看这个magic_get implementation。可以将相同的想法应用于constexpr 将 POD 转换为可以馈送到std::tie 的引用元组。像这样的:

std::tie(d2, i2) = magic_unpack(/*some POD that isn't a tuple*/);

【讨论】:

  • 我认为这根本不是真的。如果未使用 auto,您可以在结构化绑定之前添加一个关键字,如下所示:structured_binding [d2, i2] = tuple。其他人可以想出一个看起来不错的语法,但解析的努力与auto 相同。然后你可以这样做:strucutured_binding [ bool d2, int i2]。这就是我喜欢这个功能的主要原因,因为您可以使用具有显式类型的结构化绑定以及默认不可构造的东西。
  • @iPherian - 那么你错过了问题的重点。这不是为什么 auto 是关键字,而是为什么需要关键字。
【解决方案2】:

此外,您可以使用std::tie() 将元组解包到其各个组件中。比如

#include <iostream>
#include <tuple>

int main() {
    auto tuple = std::make_tuple(1.0, 1);
    double d2;
    int i2;
    std::tie(d2, i2) = tuple;

    std::cout << "d2=" << d2 << " i2=" << i2 <<  '\n';

    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-29
    • 2018-01-10
    • 2015-12-10
    • 2018-01-23
    • 2018-09-23
    • 1970-01-01
    相关资源
    最近更新 更多