Какова категория значений операндов операторов C++, если они не указаны?
ПОМЕЩЕНИЕ:
Стандарт C++11 классифицирует выражения на три категории непересекающихся значений: lvalues, xvalues и prvalues (§ 3.10/1). Объяснение того, что категории значения доступны, например, здесь.
Я пытаюсь выяснить, каковы требования различных операторов к категории значений их операндов. Пункт 3.10/1 определяет:
[...] Каждое выражение принадлежит точно к одной из основных классификаций в этой таксономии: lvalue, xvalue или prvalue. Это свойство выражения называется его категорией значений. [Примечание: обсуждение каждого встроенного оператора в разделе 5 указывает категорию получаемого им значения и категории значений ожидаемых им операндов. Например, встроенные операторы присваивания ожидают, что левый операнд является lvalue, а правый операнд является prvalue, и в результате получается lvalue. Определяемые пользователем операторы являются функциями, а категории значений, которые они ожидают и получают, определяются их параметрами и типами возвращаемых данных. —Конечная записка]
Несмотря на то, что говорится в примечании выше, пункт 5 не всегда очень ясно описывает категорию значений операндов операторов. Это, например, все, что сказано о категории значений операндов оператора присваивания (пункт 5.17/1):
Оператор присваивания (=) и составные операторы присваивания все группы справа налево. Все они требуют изменяемого lvalue в качестве своего левого операнда и возвращают lvalue, ссылаясь на левый операнд. Результатом во всех случаях является битовое поле, если левый операнд является битовым полем. Во всех случаях присваивание выполняется после вычисления значения правого и левого операндов и перед вычислением значения выражения присваивания. Что касается вызова функции с неопределенной последовательностью, операция составного присваивания является единственной оценкой. [Примечание: Поэтому вызов функции не должен вмешиваться между преобразованием lvalue-to-rvalue и побочным эффектом, связанным с каким-либо одним составным оператором присваивания. —Конечная записка]
Как насчет правильных операндов?
Слова "rvalue" и "lvalue" больше не встречаются во всем разделе 5.17. Хотя примечание в п. 3.10/1 прямо указывает на то, что встроенные операторы присваивания ожидают значение prvalue в качестве правого операнда, это явно не упоминается в разделе 5.17. Даже последнее примечание 5.17/1, в котором упоминается преобразование lvalue-в-значение, кажется, подразумевает, что r-значения ожидаются каким-то образом (зачем нужно преобразование в противном случае?), Но примечания в конце концов ненормативны.
Разделы, касающиеся других операторов, включая мультипликативные и аддитивные операторы, как правило, ничего не говорят о категории значений своих операндов. Я не смог найти ни одного "оператора по умолчанию" в Стандарте, утверждающего, что, если не указано иное, операнды встроенных операторов являются значениями. Отсюда и вопрос.
ВОПРОС:
- Какова категория значений правого операнда оператора присваивания; и, в более общем плане
- Как выяснить категорию значения операнда оператора, если он не указан? Является ли оно неограниченным (имеется в виду, что любая ценностная категория принята)? Если так, почему преобразования lvalue-в-значение должны когда-либо применяться в выражении присваивания?
Ссылки на стандарт C++11 высоко ценятся.
1 ответ
Да, это плохо определено и было покрыто ранее. По сути, каждый раз, когда требуется выражение lvalue, перечисляется, поэтому мы предполагаем, что каждый другой операнд должен быть выражением prvalue.
Итак, чтобы ответить на ваши вопросы:
- Prvalue.
- Если это не указано, это prvalue.
Примечание, указанное в связанном ответе, похоже, несколько раз менялось. Цитата из §3.10 стандарта C++11 выглядит следующим образом (и в настоящее время идентична в последнем проекте):
[Примечание: обсуждение каждого встроенного оператора в разделе 5 указывает категорию получаемого им значения и категории значений ожидаемых им операндов. Например, встроенные операторы присваивания ожидают, что левый операнд является lvalue, а правый операнд является prvalue, и в результате получается lvalue. Определяемые пользователем операторы являются функциями, а категории значений, которые они ожидают и получают, определяются их параметрами и типами возвращаемых данных. - конец примечания]
Здесь даже явно сказано, что операторы присваивания ожидают, что правый операнд будет prvalue. Конечно, это примечание и, следовательно, ненормативное.