2016-12-10 8 views
10

質問はthis answerの文脈で浮かび上がった。キャスト演算子が型への型と参照が宣言されている場合、ダイレクトリストの初期化によって型参照キャストがあいまいになるのはなぜですか?

は例を考えてみましょう:

struct foo { 
    int value; 
    operator int&(){ return value; } 
    operator int(){ return value; } 
}; 

int main() { 
    int &a(foo{}); // #1 
    //int &b{foo{}}; // #2 -- ambiguity 
    int &c = foo{}; // #3 
    //int &d = {foo{}}; // #4-- ambiguity 
    int &d { a }; // #5 
    int &e = { a }; // #6 
    (void)a; 
    (void)c; 
    (void)d; 
    (void)e; 
} 

#1と#3はそうではない私が何故#2、#4、原因の曖昧さを理解していません。そのため、型の型へのキャスト演算子と型への参照が宣言されていると、ダイレクトリストの初期化によって、暗黙のキャストの参照が曖昧になるのはなぜですか?

+2

'int&a(foo {})'は直接初期化です。 'int&b {foo {}}'は直接* list *の初期化です。彼らは同じことではありません。 –

答えて

7

リストの初期化は、参照を初期化するために使用されると、リストされた値を取り、参照を初期化するために使用されるprvalue(別名:一時的)に変換します。

したがってint &b{foo{}}int &b(int(foo{}))と機能的に同等です。どちらがあいまいですか。それはoperator intまたはoperator int&を介してintを生成する可能性があります。

しかし、あいまいではない場合でも、prvalueには非const左辺値の参照があります。どちらが違法です。したがって、このコードはで、決してになりました。

ブレース-のinit-リスト(中括弧)はオブジェクト、ない参照オブジェクトへを初期化します。すでにオブジェクトがあり、そのオブジェクトへの参照を取得したい場合は、braced-init-listを使用しないでください。


しかし、なぜコンパイラは#5を受け入れないこの場合は?

リストの初期化は優先度の高い一連のルールなので、上で指摘した優先順位よりも高い優先順位を持つルールは、型が初期化されているものの型と同じである単一の値を含むbraced-init-listの場合です。 #5と#6はちょうどその法案に適合するように起こります。d,eaはすべてint&です。

しかし、オブジェクトを作成しようとしていないときに私のアドバイスを受け取り、braced-init-listを使用しないと、そのようなコーナーケースについて心配する必要はありません。

+3

誰もが正価(たとえば、自分)について知っているわけではありません。ここにその説明へのリンクです:http://stackoverflow.com/a/3601661/783510 –

+0

しかし、この場合、なぜコンパイラは#5を受け入れますか?これは 'int&d(int(a));'と同様のものではありません。 –

+1

@ W.F .:あなたの答えは私の編集を参照してください。 –

関連する問題