Что касается преобразования lvalue-rvalue, когда это необходимо?

Я читал довольно много в Интернете, и, похоже, многие люди упомянули следующие правила (но я не мог найти его в стандарте),

Оператор сложения + (и все остальные двоичные операторы) требует, чтобы оба операнда были rvalue, а результат - rvalue. И так далее.

Я проверил стандарт С++, и он ясно заявляет, что (пункт 3.10/2),

Всякий раз, когда glvalue появляется в контекст, в котором ожидается prvalue, glvalue преобразуется в prvalue

(п. 5/9),

Всякий раз, когда появляется выражение glvalue как операнд оператора, который ожидает значение для этого операнда, lvalue-to-rvalue (4.1), array-to-pointer (4.2) или стандарт функции-to-pointer (4.3) конверсии применяются для преобразования выражение в prvalue.

Он использует термин, который операнд "ожидает" prvalue. Однако, когда я смотрю на оператор добавок, оператор умножения и т.д., Он только упоминает, что результат - это значение prvalue, но он ничего не говорит о том, что "ожидаемые" операнды будут.

Действительно ли бинарный оператор ожидает, что операнды будут prvalue, имеет значение в следующем случае,

int b = 2;
int a = b + 1;

Если ожидается, что b будет prvalue, здесь будет преобразование lvalue-rvalue, а затем оно выполнит prvalue + prvalue и вернет prvalue, а результат prvalue будет присвоен lvalue a.

Однако, если b не требуется быть prvalue, это будет lvalue + prvalue, а результат - prvalue.

Я действительно хочу знать, где стандарт явно или неявно упоминает, что правила для разных операторов? Я проверяю все разделы операторов и только несколько операторов, которые в стандартах явно упоминают, должны ли операнды и результаты быть lvalue или rvalue. Для большинства операторов стандарт ссылается только на результат, но не на требование операнда.

Спасибо.


Btw, я нашел в Стандарте 5.19 относительно постоянного выражения, может очень "неявно" подразумевать, что бинарный оператор требует преобразования lvalue-to-rval в операндах. Для получения более подробной информации, пожалуйста, обратитесь к моему предыдущему вопросу,

смешивание использования constexpr и const?

условное выражение является константой если оно не связано с одним из следующее как потенциально оценивается подвыражение (3.2).

...

- преобразование lvalue-to-rvalue (4.1) если оно не применяется к

---- значение gl интегральный или перечисляемый тип, который относится к энергонезависимому объекту const с предыдущей инициализацией, инициализируется постоянным выражением

Спасибо за чтение.

Ответ 1

Таким образом, это, как правило, одна из тех, которые были выведены и неправильно обозначены частями стандарта; Однако в 3.10

[Примечание: некоторые встроенные операторы ожидают lvalue операндов. [Пример: встроенные операторы присваивания ожидают, что их левые операнды будут lvalues. - end example] Другие встроенные операторы дают rvalues, а некоторые ожидают их. [Пример: унарные и двоичные + операторы ожидают аргументы rvalue и дают результаты rvalue. - конец примера] Обсуждение каждого встроенного оператора в разделе 5 указывает, ожидает ли он lvalue-операндов и дает ли оно значение l. - конечная нота]

Обратите внимание на плохо заданный язык "в разделе 5 указывает, ожидает ли он lvalue-операндов и дает ли значение lvalue".

Рассмотрение главы 5 показывает, что каждый случай, когда выражение нуждается или возвращает значение l, перечисляется, однако перечислены очень немногие случаи, относящиеся конкретно к rvalues, я полагаю, что тогда предполагается, что остальные считаются значениями r. >

Я также подозреваю, что это плохо указано, поскольку с точки зрения стандарта это не особенно важно, если преобразование выполняется неявным или явным образом оператором, независимо от того, поведение должно быть последовательным и хорошо себя вести.

Ответ 2

(Прежде всего, извините за мой английский. Исправления абсолютно приветливы)

В стандарте говорится:

§5.7-3 Результатом двоичного + оператора является сумма операндов. [...]

Предположим, что мы имеем выражение e1 + e2, а выбранный оператор + является встроенным, выражение хорошо сформировано, e1 и e2 являются арифметическими типами или литьем по арифметическому типу доступно, и все в порядке, прекрасно и идеально!

Таким образом, применяется правило §5.7-3. В другой руке каждый операнд является выражением:

§5-1 [Примечание: [...] Выражение представляет собой последовательность операторов и операндов, которые задают вычисление. Выражение может привести к значению и может вызвать побочные эффекты. - конечная нота]

Он говорит, что выражение может привести к значению из-за выражений void, таких как выражение delete или void, но поскольку мы сказали, что e1 + e2 отлично -defined expression!, мы можем опустить глагол "can", и поэтому мы можем утверждать, что: выражение приводит к значению.

Последняя точка: для арифметических и логических встроенных операторов, я понимаю, хотя она не указана стандартом, имеет значение только значение ее операндов, независимо от их категории значений.

Я думаю, что с выражением достаточно для реализации встроенного оператора + (и других арифметических операторов), поскольку имеет значение только значение, и значение может быть достигнуто посредством выражения. По этой причине Стандарт не определяет их четко.

Все равно, этот тип вещей очень плохо структурирован. Например, я не нашел места, указывающего, когда оператор получает объект как операнд, а не прямое значение (сомневаюсь, что я в настоящее время пытаюсь решить), если оператор должен непосредственно использовать его значение для вычисления оператора, если значение является результатом оценки объекта и т.д. Очевидно, что важны только ценности, но, что именно говорит, что Стандарт для этих вещей является своего рода загадкой.