8 Expressions [expr]

8.16 Conditional operator [expr.cond]

conditional-expression:
	logical-or-expression
	logical-or-expression ? expression : assignment-expression

Условные выражения группируются справа налево. Первое выражение contextually converted to bool. Он оценивается, и если это так true, результатом условного выражения является значение второго выражения, в противном случае - значение третьего выражения. Оценивается только одно из второго и третьего выражений. Каждое вычисление значения и побочный эффект, связанный с первым выражением, упорядочивается перед каждым вычислением значения и побочным эффектом, связанным со вторым или третьим выражением.

Если второй или третий операнд имеет тип void, должно выполняться одно из следующих значений:

  • Второй или третий операнд (но не оба) - это (возможно, в скобках) throw-expression; результат относится к типу и категории ценности другого. Это conditional-expression битовое поле, если этот операнд является битовым полем.

  • И второй, и третий операнды имеют тип void; результат имеет тип void и является значением prvalue. [ Note: Это включает случай, когда оба операнда throw-expressions. ] end note

В противном случае, если второй и третий операнды являются битовыми полями glvalue той же категории значений и типов cv1 T и cv2 T, соответственно, операнды считаются относящимися к типу cv T для оставшейся части этого раздела, где cv является объединением cv1 и cv2.

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

  • Если E2 - lvalue, то целевой тип - «lvalue ссылка на T2» с учетом ограничения, что при преобразовании ссылка должна bind directly быть на lvalue.

  • Если E2 - xvalue, целевой тип - «ссылка rvalue на T2» с учетом ограничения, которое ссылка должна связывать напрямую.

  • Если E2 это prvalue или если ни одна из приведенных выше последовательностей преобразования не может быть сформирована, и хотя бы один из операндов имеет (возможно, cv-квалифицируемый) тип класса:

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

    • в противном случае, целевой тип является типом , который E2 будет иметь после применения lvalue-to-rvalue, array-to-pointerи function-to-pointer стандартных преобразований.

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

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

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

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

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

  • Второй и третий операнды имеют арифметический или перечислительный тип; обычные арифметические преобразования выполняются, чтобы привести их к общему типу, и результат имеет этот тип.

  • Один или оба из второго и третьего операндов имеют тип указателя; pointer conversions, function pointer conversionsИ qualification conversions выполнены , чтобы привести их к композитному типу указателя (пункт [expr]). Результатом является тип составного указателя.

  • Один или оба из второго и третьего операндов имеют указатель на тип элемента; pointer to member conversions и qualification conversions выполняются, чтобы довести их до своего composite pointer type. Результатом является тип составного указателя.

  • И второй, и третий операнды имеют тип std​::​nullptr_­t или один имеет этот тип, а другой является константой нулевого указателя. Результат типа std​::​nullptr_­t.