return 类型推导与解包引用的混淆

Confusion on return type deduction with unpacking references

以下代码

#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 报告:

error: cannot bind non-const lvalue reference of type 'std::tuple<int&, int&>&' to an rvalue of type 'std::tuple<int&, int&>'

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

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

auto [x, y] = memrefs(p)

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

decltype(auto) memrefs(Point &p);

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

structured_binding中, auto& [x, y] 中的 auto& 适用于 “元组”,不适用于 xy.

你不能

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

但你可以

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

然后xy指的是元组的适当部分。

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

正在构造 std::tuple<int&, int&> 类型的临时局部变量,returns 将其作为右值。在这种情况下,作为临时变量,可以使用 const 引用 (const std::tuple<int&, int&>&) 获取它,也可以将其复制到新元组中 (std::tuple<int&, int&>) .在您的情况下,您正在尝试获取对临时对象的非 const 引用 (std::tuple <int&, int&>&),这是不允许的。

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