Search code examples
c++c++20rvaluelvaluestdtuple

Structured bindings mixing rvalues and lvalues in C++


The commented line in the following snippet does not work as expected:

double a, b;
auto [c, d] = std::make_tuple<double, double&>([&]() -> double { return a; }(),
                                               [&]() -> double& { return b; }());
static_assert(std::is_same_v<double, decltype(c)>);
// static_assert(std::is_same_v<double&, decltype(d)>);    // Compile error!

Specifically, I would like to return both an rvalue and an lvalue in a single structured binding declaration. I have tried to declare c and d both using auto& and auto&&, but none of the approaches worked. Is there a way to achieve the above desired behavior?


Solution

  • std::make_tuple<double, double&>(...) returns std::tuple<double, double>, since it applies std::decay to the template arguments. In any case, you're not supposed to specify the template arguments for it, it can deduce them automatically.

    To have a reference in the tuple, construct it using std::tuple<double, double &>(...). Then your code works as you expect it to.