Тип возврата '?:' (Тернарный условный оператор)

Почему первая возвращает ссылку?

int x = 1;
int y = 2;
(x > y ? x : y) = 100;

Пока второй не работает?

int x = 1;
long y = 2;
(x > y ? x : y) = 100;

Собственно, второй вообще не компилировался - "не lvalue слева от назначения".

+203
16 дек. '11 в 13:57
источник поделиться
3 ответа

Выражения не имеют типов возврата, у них есть тип и - как известно в последнем стандарте С++ - категория значений.

Условное выражение может быть lvalue или rvalue. Это его категория значений. (Это несколько упрощает, в C++11 мы имеем lvalues, xvalues ​​и prvalues.)

В очень широких и простых выражениях lvalue ссылается на объект в памяти, а rvalue - это просто значение, которое необязательно может быть привязано к объекту в памяти.

Выражение присваивания присваивает значение объекту, поэтому присваиваемая вещь должна быть lvalue.

Для условного выражения (?:) должно быть lvalue (опять же, в широких и простых выражениях), второй и третий операнды должны быть lvalues ​​одного и того же типа. Это связано с тем, что тип и значение условного выражения определяется во время компиляции и должно быть соответствующим независимо от того, является ли условие истинным. Если один из операндов должен быть преобразован в другой тип, чтобы соответствовать другому, то условное выражение не может быть lvalue, поскольку результат этого преобразования не будет lvalue.

ИСО/МЭК 14882: 2011 ссылки:

3.10 [basic.lval] Lvalues ​​и rvalues ​​(о категориях значений)

5.15 [expr.cond] Условный оператор (правила для какого типа и категории значений есть условное выражение)

5.17 [expr.ass] Операторы присваивания и составного присваивания (требование о том, что l.h.s. присваивания должно быть изменяемым значением l),

+170
16 дек. '11 в 14:05
источник

Связанные вопросы


Похожие вопросы

Тип тернарного выражения ?: является общим типом его второго и третьего аргументов. Если оба типа одинаковы, вы получите обратную ссылку. Если они конвертируемы друг к другу, их выбирают, а другую конвертируют (продвигают в этом случае). Поскольку вы не можете вернуть ссылку lvalue во временную (преобразованную/продвинутую переменную), ее тип - тип значения.

+56
16 дек. '11 в 13:59
источник

Он не может вернуть значение lvalue, так как он должен будет неявно продвигать тип x, чтобы соответствовать типу y (так как обе стороны : не одного типа), и с этим он имеет для создания временного.


Что говорит стандарт? (n1905)

Выражения 5.17 Операторы присваивания и составного присваивания

5,17/3

Если второй и третий операнды имеют разные типы и имеют (возможно, cv-qualified) тип класса, делается попытка преобразовать каждый из этих операндов в тип другого. Процесс определения того, можно ли преобразовать выражение E1 операнда типа T1 в соответствие с выражением операнда E2 типа T2, определяется следующим образом:

- Если E2 является lvalue: E1 может быть преобразован в соответствие E2, если E1 может быть неявно преобразован (раздел 4) в тип "ссылка на T2", при условии ограничения, которое при преобразовании ссылка должна связываться напрямую ( 8.5.3) к E1.

- Если E2 является rvalue или если преобразование выше не может быть выполнено:

- если E1 и E2 имеют тип класса, а базовые типы классов одинаковы или один является базовым классом другого: E1 может быть преобразован в соответствие E2, если класс T2 является тем же типом, что или базовый класс, класс T1 и cv-квалификация T2 - это такая же cv-квалификация, как или более высокая cv-квалификация, чем cv-квалификация T1. Если применяется преобразование, E1 изменяется на rvalue типа T2, который все еще относится к исходному объекту исходного объекта (или к соответствующему подобъекту). [Примечание: нет копии. - end note] путем копирования-инициализации временного типа T2 из E1 и использования этого временного в качестве преобразованного операнда.

В противном случае (т.е. если E1 или E2 имеет тип неклассов, или если оба они имеют типы классов, но базовые классы не являются одинаковыми или один базовый класс другого): E1 может быть преобразован в сопоставьте E2, если E1 может быть неявно преобразован в тип, который будет иметь выражение E2, если E2 были преобразованы в rvalue (или тип, который он имеет, если E2 является rvalue).

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


5,17/4

Если второй и третий операнды являются lvalues ​​и имеют один и тот же тип, результат имеет этот тип и является lvalue, и это бит-поле, если второй или третий операнд является битовым полем, или если оба являются битовыми полями.


5,17/5

В противном случае результатом будет значение r. Если второй и третий операнды не имеют одного и того же типа и имеют (возможно, cv-qualit) тип класса, то для определения конверсий (если они есть) применяются к операндам (13.3.1.2, 13.6), Если разрешение перегрузки выходит из строя, программа плохо сформирована. В противном случае применяются указанные таким образом преобразования, а преобразованные операнды используются вместо исходных операндов для остальной части этого раздела.

+18
16 дек. '11 в 14:00
источник

Посмотрите другие вопросы по меткам или Задайте вопрос