2016-04-15 3 views
1

私は現在、r値参照と移動セマンティクスを行っていますが、私自身のコーディング実験では奇妙な矛盾が見られます。std :: forwardを使用すると、なぜr値を渡している間にl値参照関数を呼び出せるのですか?

#include <iostream> 

using namespace std; 

class X{}; 

void g(X&& t) // A 
{ 
    cout << "Rref call" << endl; 
}  

void g(X& t) // B 
{ 
    cout << "Lref call" << endl; 
}  

template<typename T> 
void f(T&& t) 
{ 
    g(forward<T>(t)); 
} 

int main() 
{ 
    X x; 
    f(x); // 1 
    f(X()); // 2 

    return 0; 
} 

がここに予想される出力を生成します:

Lrefを呼び出し

Rrefのコール

をしかし、私は先に行くと場合は、以下のコードを考えると

r値参照を取るオーバーロードされた関数gを削除する(コメント行// A)に上記の表記、私は次のような出力が得られます。

Lrefを呼び出し

Lrefを呼び出し、この作品をどのよう

?なぜコンパイラはX&&を渡そうとしているときにg(X& t)への呼び出しに不平を言いませんか?

+3

Visual Studioを使用していますか?もしそうなら、それは[非標準的な拡張子](http://stackoverflow.com/questions/1565600/how-come-a-non-const-reference-cannot-bind-to-a-temporary-object)から一時変数を非const参照にバインドすることができます。この例では失敗します(http://ideone.com/TcJbJA)。 –

+0

James、それはまさにそれに見えます。論理が起こっているのを理解しようとしていた。とても感謝しております。 – Joefers

答えて

3

g(X&& t)のオーバーロードをコメントアウトするときは、MSVC extensionを使用しています。この場合、バインディングの値はconstの左辺値になります。警告レベルを/W4にすると、MSVCは非標準の内線が使用されていることを通知します。

gccとclangの両方fail to compileそのオーバーロードのコードはコメントアウトされています。

+0

Visual Studioを使用していて、これをうれしく受け入れていました。親切にありがとう。 – Joefers

+0

これはMSVCで最も恐ろしいバグの1つです。そして、それはrvalue参照がなかった時代に何らかの感覚を戻していたかもしれませんが、今は0の感覚を持っています。彼らはC++ 11コードのためにオフにしておくべきです。 – SergeyA

+0

@SergeyA '/ W4'と'/WX'でコンパイルすると、それは消えます:)しかし、私は彼らの言い訳をしたくない、これは恐ろしい拡張です。 – Praetorian

関連する問題