2017-12-15 19 views
-1

を転送:のstd ::を使用して友人を尋ねる非転送、昔ながら参照して

次のコードでstd::forwardは右辺値にパラメータcをキャストしないのはなぜ?

template <typename T> 
void f (T& c) { 
    using value_type = typename std::remove_reference_t<T>; 
    std::vector<value_type> v; 
    // debugger reveals: push_back(T&& value) is called here 
    v.push_back(std::forward<T>(c)); 
} 

ここで、cは汎用/転送の参照ではありません。私は、実際にはこの機能が多分使用される可能性が高いという事実を認識していますが、それでも好奇心が強いのです。

+0

"* cは普遍的な/フォワーディングリファレンスではないことに注意してください*"なぜ*あなたは 'std :: forward'を使っていますか? –

+0

私は誤って1つのアンパサンドを省略し、std :: forwardがなぜここにあるように動作するのか不思議に思っていました。 –

+2

http://thbecker.net/articles/rvalue_references/section_08.html – hadriel

答えて

1

この状況を理解するには、転送参照が機能する理由を理解する必要があります。あなたがsome_type&する

some_type some_object; 
foo(some_object); 

テンプレート控除のようなもの推論Tを書くとき

template <typename T> 
void foo(T&& t) {} 

のような定義を考えます。パラメータtのタイプはsome_type& &&です。参照への参照はできないため、reference collapsingのルールが適用され、some_type& &&some_type&に折りたたまれています。 some_typeをする

があれば、代わりに、あなたは

some_type some_object; 
foo(std::move(some_object)); 

テンプレート控除のようなもの推論Tを書きます。パラメータtのタイプはsome_type&&です。これは完全に有効なタイプなので、参照の折りたたみは行われません。

今度はstd::forwardになります。 std::forward<U>はすべて、そのパラメータをU&&にキャストします。 Usome_typeの場合、上記の2番目の場合と同様に、パラメータはsome_type&&にキャストされます。それはrvalue-referenceのままです。 Usome_type&である場合、上記の最初の場合と同様に、再び参照縮退が実行され、some_type& &&some_type&になります。したがって、std::forwardは左辺値参照を返します。

元の質問に対する最終的な答えは、std::forwardの戻り値の型は、std::forwardのテンプレートパラメーターとして渡される型にのみ依存します。あなたのケースのTは常に非参照型として推論されるため、std::forwardは常にrvalue-referenceを返します。

+0

最も詳細な回答として受け入れられました。 –

1

まあ、std::forward<T>(x)の定義は、xをタイプT&&にキャストすることです。引数として非参照を渡すと、右値の参照T&&が返されます。 Tは参照型(参照への参照を持つことはできません)であることはできないため、参照型でない必要があります。

2

std::forward<T>(c)は、static_cast<T&&>(c)に相当します。

T&&が転送参照である場合、これはTは左辺値参照型として推定され、T&&を参照崩壊ルールによって同じ左辺参照型になるため、左辺値が左辺値として転送されることを可能にします。あなたの状況では、T&&は転送参照ではないので、これは動作しません。

関連する問題