2010-11-24 16 views
23
struct A 
{ 
    A(const A& src); 
    A(const char* src); 
}; 
struct B 
{ 
    operator A(); 
    operator char*(); 
}; 
void test() 
{ 
    B v; 
    A s(v); 
} 

EDG/ComeauとMSVCは、GCC 4.4.4、CLANGおよびBCC が曖昧である間にコードを許可します。これはあいまいかどうか? (暗黙のキャスト)

A C++委員は、(最初​​は)これと答え:

それがあいまいではありません。 A(const A &) コンストラクタはA(const char *)コンストラクタよりも優れています。 変換シーケンスは、ユーザ定義の変換である に考えられるよう& パラメータは、結果の変換関数の に直接結合CONSTは、恒等変換 (13.3.3.1.4p1)によって に従いました。 const char * パラメータは、ユーザー定義の変換 に続いて修飾 の変換であるため、悪化します。

その後、彼はこれをフォローアップしました。

実際、私は間違っていました。ユーザー定義の変換 にシーケンスは、13.3.3.2p3で密接 多くを見て、 最後から弾丸が、この タイブレークがいる場合にのみ適用されることを明らかにタイブレークされた第2の変換 シーケンスこと は事実ですが2つの シーケンスには、同じ ユーザー定義の変換シーケンスが含まれており、この例では該当しない が含まれています。 1つのコンストラクタの変換 配列がB ::オペレータA()と 他の用途のB ::演算子のchar *()を使用しているため は、 は、二つ ユーザ定義の変換シーケンスと それらが曖昧である間にタイブレークありません。

私の質問はこれです。

13.3.3.2 P3は 以下のルールのいずれかが適用されない限り 同じ形の

二つの暗黙的な変換配列は区別できない 変換配列である、と述べています。

私の理解から言えば、キーワードは「次のルールの1つ」です。 "同じ変換シーケンス"と書かれている箇条書き は上記のものすべてを上書きしているわけではありません。私は "S1のランクはS2のランクよりも良い "と考えていたでしょうか?

+12

C++はそれほど複雑ではないと確信しています... – Hexagon

+0

C++コミュニティメンバーの連絡先があるので、問題を提出するように頼んではいけませんか? (または、http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.htmlに提出されているかどうか確認してください) –

+0

問題があるとは言いませんでした。標準。 –

答えて

4

はい、期待される結果は、型「B」の節13.3.3.2

マッチング引数「V」の私の解釈の最高の「A」のオーバーロードされたコンストラクタのいずれかのパラメータにあいまいである必要がありユーザー定義の変換。両方のシーケンスは、CONVERSIONランクです。

私の解釈は[...]ユーザー定義の変換シーケンス$ 13.3.3.2から次の引用は

を適用することである U1は、別のユーザー定義変換 シーケンスU2よりも優れた変換シーケンス あるそれらが同じ ユーザ定義の変換関数または コンストラクタが含まれている場合、U1の第二標準 変換シーケンスは、第2の標準変換より 良好である場合に U2のシーケンス。

これらの両方は、クラス 'B'で異なる変換関数を呼び出します。したがって、最初の条件そのものは満たされていないと思います。したがって、変換シーケンスのどちらも他のものより優れていないため、予期しない結果があいまいです。

+0

はい、これは明らかに曖昧です。なぜこれが受け入れられないのかわからないswer。なぜそれが曖昧なのかを直接指摘しています。しかし、それは "変換"ランクを持っていることは間違っています。後で言いますが、ユーザー定義の変換シーケンスは2つあります。ランクは標準的な変換シーケンス(完全一致、プロモーション、変換)に与えられます。ユーザーが定義した変換順序のランクはありません。 –

1

免責事項:標準は実際にこれらの部分では複雑なので、私は私の理解に完全に間違っているかもしれません。

の標準の定義実行可能な機能(13.3。3):すべての引数のために、私は、ICSI(F1)が より悪い変換シーケンスでない場合、これらの定義は、実行可能な 関数F1が他の実行可能な機能 F2よりも良い 関数であると定義されているが与えられ

ICSI(F2)、次いで

[...]

  • コンテキストは、ユーザー定義変換(8.5を参照、によって初期化され13.3.1.5及び13.3.1.6)と宛先 タイプ(すなわち、 が初期化されているエンティティのタイプ)にF1 の 戻り型から標準変換シーケンスは、標準よりも良好 変換シーケンスであります F2のタイプから宛先タイプへの変換シーケンス 。

私が正しく理解していれば、構築されるオブジェクトの種類は、ここではその重要性を持っており、それは A::A(const A &)より良い候補となるだろう。


ヨハネスを参照してください、この答えが間違っている理由を確認するためにコメント:これはChubsdadによって指摘理由確かに曖昧です。

+0

明らかに関連していますが+1ですが、上記の2つのコンテキストのうち、13.3.1.5は非クラス型(intなど)の初期化のみに関係し、13.3.1.6は*参照の初期化のみに関係します。だから私はここでそれを適用するとは思わない。 –

+0

@j_random_hacker:はい、8.5は初期化やそれ以外のものをカバーします – icecrime

+0

@icecrime:あなたはそうですが、プロットは太くなります:8.5/12によると、 'A s(v);'は直接初期化* - 右? 8.5/14の第6弾が適用されます。ここで引用するには大きすぎますが、重要な点は、次の箇条書き(一部)のコピー初期化の場合とは異なり、「ユーザー定義の変換」という言葉は言及していないことです。だから私はあなたが引用したスニペットはここに当てはまるとは思わないし、 'A s(v);'はあいまいだが 'A s = v;'は 'A(const A&)' ctorを選択すべきだと結論する。 –

関連する問題