Confusión sobre la deducción del tipo de retorno con desempaquetado de referencias.
El siguiente código
#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;
}
no compila. Informado por GCC 8.1.0:
error: no se puede vincular la referencia lvalue no constante de tipo ‘std::tuple<int&, int&=””>&’ a un valor rvalue de tipo ‘std::tuple<int&, int&=””>’
Sin embargo, compilará si cambio
auto& [x, y] = memrefs(p);
a
auto [x, y] = memrefs(p)
Mi pregunta es, ¿por qué? ¿No son x
e y
referencias?</int&,></int&,>
davy.ai
La razón por la cual cambiar
auto& [x, y] = memrefs(p);
aauto [x, y] = memrefs(p)
se compila es porquestd::make_tuple()
devuelve un rvalor, el cual no puede ser ligado a una referencia a un lvalor. Al remover los ampersands (&
) enauto [x, y]
, el compilador deduce automáticamente quex
ey
deberían ser copias de los valores en la tupla, en lugar de referencias a estos.Por lo tanto, al utilizar
auto [x, y] = memrefs(p)
, se crean copias dep.x
yp.y
, las cuales son almacenadas enx
ey
, respectivamente. Estas copias pueden ser modificadas sin afectar los valores originales dep.x
yp.y
.