std::tie fails with "cannot bind non-const lvalue reference" when passed value from a function call

std::tie always expects lvalues for arguments, since its intended purpose is to be used in assignment. To handle other value categories, one may use std::forward_as_tuple:

bool f(const S& a, const S& b)
{
    return std::forward_as_tuple(a.x, a.y()) < std::forward_as_tuple(b.x, b.y());
}

The two tuples now contain rvalue references that are bound to the results of the calls to S::y. Goes without saying that one best be careful with object lifetimes when using it.


std::tie takes lvalue references as arguments, so int returned by S::y can't bind. You could use the perfect forwarding version, std::forward_as_tuple, instead:

#include <tuple>

struct S
{
    int x = 0;
    int y() const { return 1; }
};

bool f(const S& a, const S& b)
{
    return std::forward_as_tuple(a.x, a.y()) < std::forward_as_tuple(b.x, b.y());
}

Demo.