Условное выражение с операндами типа lvalue

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

Пример:

struct S {};
S x, y;
void foo(bool cond) {
  cond ? x : y;  // what is the value category of the result?
}

Я вижу, что два разных абзаца в [expr.cond] говорят разные вещи.

Согласно пункту 4:

Если второй и третий операнды являются значениями gl с одной и той же категорией значений и имеют один и тот же тип, результат относится к этому типу и категории значений

Этот абзац кажется применимым и говорит, что результатом является lvalue, потому что второй и третий операнды являются lvalue одного типа.

Однако согласно пункту 6:

Стандартные преобразования Lvalue-to-rvalue, массива в указатель и функции в указатель выполняются для второго и третьего операндов. После этих преобразований выполняется одно из следующих действий:

  • Второй и третий операнды имеют одинаковый тип; результат именно такого типа. Если операнды имеют тип класса, результатом является временное значение prvalue типа результата, которое инициализируется копией либо из второго операнда, либо из третьего операнда в зависимости от значения первого операнда.

Этот абзац также кажется применимым и говорит, что результатом выражения является rvalue.

Так что это - lvalue или rvalue? Действительно ли два абзаца противоречат друг другу, или я упускаю что-то тонкое?


person HighCommander4    schedule 26.08.2015    source источник


Ответы (1)


Вы должны прочитать абзацы по порядку и выбрать первый, который подходит. Акцент мой.

1

...

2

Если второй или третий операнд имеет тип void ...

3

В противном случае, если второй и третий операнды имеют разные типы и либо имеют (возможно, cv-квалификационный) тип класса, либо если оба являются glvalue одной и той же категории значений и одного и того же типа, за исключением cv-квалификации. ..

4

Если второй и третий операнды являются значениями glvalue одной категории значений и имеют один и тот же тип ...

5

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

6

Стандартные преобразования Lvalue-to-rvalue (4.1), массива в указатель (4.2) и функции в указатель (4.3) выполняются для второго и третьего операндов. ...

person Brian Bi    schedule 26.08.2015
comment
Ах! В этом есть смысл :) - person HighCommander4; 26.08.2015