2013-12-14 28 views
11

コンパイラは左辺値を右辺値参照にバインドしようとしていると不平を言っていますが、どのように見えません。私はC++ 11、移動セマンティクスなどが新しくなっていますので、私に同行してください。LvalueからRvalueへの参照バインディング

私はこの機能を持っている:私は、次のようなエラーを得続ける

template <typename Key, typename Value, typename HashFunction, typename Equals> 
void FastHash<Key, Value, HashFunction, Equals>::Insert(Key&& key, Value&& value) 
{ 
    // ... 
} 

cannot convert argument 1 from 'std::string' to 'std::string &&' 

挿入()の呼び出しに

template <typename Key, typename Value, typename HashFunction, typename Equals> 
Value& FastHash<Key, Value, HashFunction, Equals>::operator[](Key&& key) 
{ 
    // Some code here... 

    Insert(key, Value()); // Compiler error here 

    // More code here. 
} 

このメソッドを呼び出しています。演算子のオーバーロードで右辺値としてkeyが定義されていませんか?なぜそれが左辺値として再解釈されているのですか?

ありがとうございました。

答えて

18
Insert(key, Value()); // Compiler error here 

keyここはKey&& keyです - これは左端です!それは名前があり、あなたはその住所をとることができます。その左辺値の型は「右辺値Key」です。

あなたは右辺値に合格する必要があり、そのためにあなたがstd::moveを使用する必要があります。

Insert(std::move(key), Value()); // No compiler error any more 

これは直感に反している理由私は見ることができます!しかし、一旦、あなたとrvalueの参照(rvalueにバインドされた参照)と実際のrvalueとを区別すると、それはより明確になります。

編集:ここでの本当の問題は、値の参照を一切使用しないことです。引数の型が導出される関数テンプレートでそれらを使用することは理にかなっています。これは、参照の折りたたみ規則のために引数が左辺値参照または右辺値参照のいずれかにバインドできるようにするためです。 http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers

FastHash<std::string, ... >をインスタンス化したときにクラスによって既に決定されているため、このケースでは、関数の呼び出し時にキーの種類が推測されません。したがって、あなたは実際にrvalue参照の使用を処方しているので、std::moveを使用するとコードが修正されます。

私はパラメータが値によって取りされていることにあなたのコードを変更します

template <typename Key, typename Value, typename HashFunction, typename Equals> 
Value& FastHash<Key, Value, HashFunction, Equals>::operator[](Key key) 
{ 
    // Some code here... 

    Insert(std::move(key), Value()); 

    // More code here. 
} 

template <typename Key, typename Value, typename HashFunction, typename Equals> 
void FastHash<Key, Value, HashFunction, Equals>::Insert(Key key, Value value) 
{ 
    // ... 
} 

が値引数の使用に起因する余分なコピーについてはあまり心配しないでください - これらは、しばしば、コンパイラによって最適化されています。

+2

左辺値の型が「キー」ではありませんか? rvalue-reference-nessはどのように保存されていますか? – hvd

+0

これは動作しますが、私はhvdが引き起こした問題を理解しているかどうかはわかりません。あなたは説明できますか? –

+0

@hvd彼女に引き継がれる引数型の減算がないので、保存されます。私の編集を参照してください。 – polkadotcadaver