Может ли функция-член вернуть модифицируемую ссылку lvalue на объект rvalue? - PullRequest
4 голосов
/ 12 марта 2020

Я немного сбит с толку по поводу этого кода:

struct A
{
    A& bar()&&;
};

A& A::bar()&&
{
    std::cout << "A::bar()&&\n";
    return *this;
}

int main()
{
    A{}.bar();// called by an rvalue
}

Итак, я понимаю, что bar может вызываться только с помощью модифицируемого-значения. До этого все нормально. Но как bar может возвращать непостоянную ссылку lvalue на это значение?

  • Как bar() связывает и возвращает изменяемую ссылку lvalue на этот объект rvalue?

Ответы [ 2 ]

3 голосов
/ 12 марта 2020

Чтобы быть немного менее легкомысленным: причина в том, что указатель this для класса C может быть либо C*, либо const C*, но не C& * или C&& * (это не так типы; вы не можете объявить C& * ptr). Таким образом, даже когда ваш метод выполняется для экземпляра rvalue класса A, вы получаете один из этих двух (GodBolt). И когда вы применяете оператор *, вы получаете lvalue , а не rvalue.

2 голосов
/ 12 марта 2020

Это связано с [expr.unary.op] / 1

Унарный оператор * выполняет косвенное обращение: выражение, к которому он применяется, должно быть указатель на тип объекта или указатель на тип функции и результатом является lvalue , ссылающееся на объект или функцию, на которые указывает выражение. Если тип выражения «указатель на T», тип результата будет «T». [Примечание: допустимо перенаправление через указатель на неполный тип (кроме cv void). Полученное таким образом l-значение может использоваться ограниченным образом (например, для инициализации ссылки); это lvalue не должно быть преобразовано в prvalue, см. [conv.lval]. - Конечная нота]

выделенная мина

Поэтому при разыменовании this вы получите lvalue. Неважно, указывает ли это на временный объект или нет, вы всегда получите lvalue. Поскольку *this является lvalue, вам по закону разрешено возвращать ссылку lvalue, программа в синтаксически правильная. Семантически это не так, но это гораздо сложнее проверить, и часто это не то, что диагностируется, так как для этого требуется немало анализа c.


Было бы здорово, если бы язык мог быть обновлен, если * возвращает значение lvalue только при применении к this в функции, не соответствующей rvalue.

...