web-dev-qa-db-ja.com

'?:'の戻り型(三項条件演算子)

なぜ最初に参照が返されるのですか?

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

第二はそうではありませんか?

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

実際、2番目はまったくコンパイルされませんでした-「代入の左辺値ではありません」。

207
Yola

式には戻り値の型はなく、型と-最新のC++標準で知られているように-値のカテゴリがあります。

条件式は、lvalueまたはrvalueです。これはその値のカテゴリです。 (これはやや単純化したもので、C++11左辺値、x値、およびpr値があります。

非常に広範かつ簡単に言えば、lvalueはメモリ内のオブジェクトを指し、rvalueは単なる値であり、必ずしもメモリ内のオブジェクトに添付されるとは限りません。

割り当て式はオブジェクトに値を割り当てるため、割り当てられるものはlvalueでなければなりません。

条件式(?:lvalue(ここでも、広範で単純な用語で)、2番目と3番目のオペランドは同じ値の左辺値。これは、条件式の型と値のカテゴリがコンパイル時に決定され、条件が真であるかどうかに関係なく適切でなければならないためです。オペランドの1つを別のタイプに変換して他のオペランドと一致させる必要がある場合、条件式はlvalueにはできません。この変換の結果はlvalue.

ISO/IEC 14882:2011参照:

3.10 [basic.lval]左辺値と右辺値(値カテゴリについて)

5.15 [expr.cond]条件演算子(条件式に含まれる型と値のカテゴリの規則)

5.17 [expr.ass]代入演算子と複合代入演算子(代入のl.h.s.は変更可能な左辺値でなければならないという要件)

173
CB Bailey

三項のタイプ?: expressionは、2番目と3番目の引数の共通タイプです。両方のタイプが同じ場合、参照が返されます。それらが相互に変換可能な場合、一方が選択され、もう一方が変換されます(この場合は促進されます)。一時変数(変換された/昇格された変数)への左辺値参照を返すことはできないため、その型は値型です。

57
Xeo

lvalueを返すことはできません。これは、xの型に一致するようにyの型を暗黙的に昇格する必要があるためです(:_は同じタイプではありません)、それで一時的なものを作成する必要があります。


標準は何と言っていますか? ( n1905

式5.17代入演算子と複合代入演算子

5.17/3

2番目と3番目のオペランドの型が異なり、どちらかが(おそらくcv修飾された)クラス型の場合、これらの各オペランドを他方の型に変換しようとします。タイプT1のオペランド式E1を、タイプT2のオペランド式E2と一致するように変換できるかどうかを判別するプロセスは、次のように定義されます。

— E2が左辺値の場合:E1を暗黙的に変換して(参照4)、「T2への参照」型に変換できる場合、E1はE2に一致します。変換では参照を直接バインドする必要があります(8.5.3 )E1へ。

— E2が右辺値である場合、または上記の変換を実行できない場合:

— E1およびE2にクラスタイプがあり、基礎となるクラスタイプが同じであるか、一方が他方の基本クラスである場合:T2のクラスが同じタイプまたはE2の基本クラスである場合、E1はE2に一致するように変換できます、T1のクラス、およびT2のcv修飾は、T1のcv修飾と同じcv修飾、またはそれより大きいcv修飾です。変換が適用される場合、E1は、元のソースクラスオブジェクト(またはその適切なサブオブジェクト)を引き続き参照する、タイプT2の右辺値に変更されます。 [注:つまり、コピーは作成されません。 — end note] E1からタイプT2のテンポラリをコピー初期化し、そのテンポラリを変換されたオペランドとして使用します。

そうでない場合(つまり、_E1_またはE2が非クラス型である場合、または両方がクラス型であるが、基礎となるクラスが同じまたは一方が他方の基本クラスでない場合):E1は一致するように変換できますE2が右辺値に変換された場合にE1を式E2が持つ型に暗黙的に変換できる場合(またはE2が右辺値である場合はその型)、E2。

このプロセスを使用して、第2オペランドを第3オペランドに一致するように変換できるかどうか、および第3オペランドを第2オペランドに一致するように変換できるかどうかを判別します。両方を変換できる場合、または一方を変換できても変換があいまいな場合、プログラムの形式は正しくありません。どちらも変換できない場合、オペランドは変更されずに残り、以下で説明するようにさらにチェックが実行されます。変換が1つだけ可能である場合、その変換は選択したオペランドに適用され、変換されたオペランドは、このセクションの残りの元のオペランドの代わりに使用されます。


5.17/4

2番目と3番目のオペランドが左辺値で同じ型である場合、結果はその型で左辺値であり、2番目または3番目のオペランドがビットフィールドの場合、または両方がビット-フィールド。


5.17/5

それ以外の場合、結果は右辺値です。 2番目と3番目のオペランドが同じ型でなく、どちらかが(おそらくcvで修飾された)クラス型である場合、オーバーロード解決を使用して、オペランドに適用する変換(ある場合)を決定します(13.3.1.2、13.6) 。オーバーロードの解決に失敗した場合、プログラムの形式は正しくありません。そうでない場合、このように決定された変換が適用され、変換されたオペランドが、このセクションの残りの元のオペランドの代わりに使用されます。

19