std :: tie завершается неудачно с «невозможно связать неконстантную ссылку на lvalue» при передаче значения из вызова функции - PullRequest
3 голосов
/ 04 июля 2019

Я ожидал, что этот код будет работать, но он не компилируется:

#include <tuple>

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

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

GCC 9 говорит:

ошибка: невозможно связать неконстантную ссылку lvalue типа 'int & 'to rvalue типа' int '

return std::tie(a.x, a.y()) < std::tie(b.x, b.y());
                     ~~~^~

Что не так с кодом, как его можно исправить и почему?Я пытаюсь написать краткую функцию сравнения, и обычно std::tie поддерживает это (действительно, это пример использования учебника для std::tie).

Демонстрация: https://godbolt.org/z/cWbQC0

Ответы [ 2 ]

6 голосов
/ 04 июля 2019

std::tie всегда ожидает lvalue для аргументов, поскольку его назначение должно использоваться в присваивании. Для обработки других категорий значений можно использовать 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());
}

Два кортежа теперь содержат ссылки на rvalue, которые привязаны к результатам вызовов S::y. Само собой разумеется, что лучше всего быть осторожным с продолжительностью жизни объекта при его использовании.

3 голосов
/ 04 июля 2019

std::tie принимает в качестве аргументов ссылки на lvalue, поэтому int, возвращаемый S::y, не может быть привязан.Вы можете использовать идеальную версию переадресации, std::forward_as_tuple, вместо:

#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());
}

Демо.

...