返回类型推论与解包引用的混淆

Posted

技术标签:

【中文标题】返回类型推论与解包引用的混淆【英文标题】:Confusion on return type deduction with unpacking references 【发布时间】:2022-01-21 23:50:50 【问题描述】:

以下代码

#include <functional>
#include <tuple>
#include <iostream>

struct Point

    int x;
    int y;
;

decltype(auto) memrefs(Point &p)

    return std::make_tuple(std::ref(p.x), std::ref(p.y));


int main()

    Point p;
    auto& [x, y] = memrefs(p);
    x = 1;
    y = 2;
    std::cout << p.x << " " << p.y << std::endl;
    return 0;


不编译。由 GCC 8.1.0 报告:

错误:无法将'std::tuple&'类型的非常量左值引用绑定到'std::tuple'类型的右值

但是,如果我改变它会编译

auto&amp; [x, y] = memrefs(p);

auto [x, y] = memrefs(p)

我的问题是为什么? xy 不是引用吗?

【问题讨论】:

decltype(auto) memrefs(Point &amp;p) 返回一个临时值,即右值。右值只能绑定const &amp;,或者在您的第二种情况下复制。 您在寻找std::tie吗? 感谢您的回复。现在对我来说有点道理。我无法理解当返回单个引用时必须使用 auto&amp; x = getref(); 而不是返回多个引用时这一事实。 【参考方案1】:
decltype(auto) memrefs(Point &p);

std::tuple<int&, int&> memrefs(Point &p);

在structured_binding, auto&amp; in auto&amp; [x, y] 适用于 "tuple",不适用于 xy

你不能拥有

std::tuple<int&, int&>& tup = memrefs(p);

但你可以拥有

std::tuple<int&, int&> tup = memrefs(p);

那么xy指的是元组的适当部分。

【讨论】:

【参考方案2】:

线

return std::make_tuple(std::ref(p.x), std::ref(p.y));

正在构造一个std::tuple&lt;int&amp;, int&amp;&gt; 类型的临时局部变量并将其作为右值返回。在这种情况下,作为一个临时变量,它可以通过 const 引用 (const std::tuple&lt;int&amp;, int&amp;&gt;&amp;) 获取,也可以复制到新的元组 (std::tuple&lt;int&amp;, int&amp;&gt;) 中。在您的情况下,您试图获取对临时对象的非 const 引用 (std::tuple &lt;int&amp;, int&amp;&gt;&amp;),这是不允许的。

您如何指出,解决方案是将memrefs 返回的值复制到一个新值中,或者使用 const 引用获取它。

【讨论】:

我同意你的观点,但是pastebin.com/8p6JY7fb 它打印出 std::tuple const& 在线编译器为coliru或godbolt比pastebin更合适 确实,std::make_tuple 处理 std::reference_wrapper 以使用参考。 @Jarod42 所以简而言之,我和int&amp; 是对的?

以上是关于返回类型推论与解包引用的混淆的主要内容,如果未能解决你的问题,请参考以下文章

可选类型“问题?”的值必须解包以引用已包装基本类型“问题”的成员“问题文本”

具有复杂值类型的迭代器:与value_type和引用混淆

python高级特性之封包与解包

《双星物语》游戏资源格式分析与解包

struct--二进制数据结构的打包与解包

Python序列封包与解包