2017-02-01 13 views
2

私はいくつかのクラスへの左と右の両方の参照を受け入れ、それをオブジェクトとして移動するメンバ関数を持っていたいと思います。現在、私は2つの別々の機能を持っている:C++で左右参照の両方を受け入れる方法は?

void ThrSafeQueue::push(Obj&& x) { 
    lock_guard(mutex_); 
    queue_.push(x); 
} 
void ThrSafeQueue::push(Obj& x) { 
    lock_guard(mutex_); 
    queue_.push(std::move(x)); 
} 
+7

左辺値と右辺値参照と呼ばれます。 –

+1

第1のケースでは、 'std :: move'も呼び出すべきです。メモでは、' x'は名前付き変数、したがって左辺値です。 – songyuanyao

+1

@ user1810087ちょうどメモ、彼らは今標準の転送参照と呼ばれています。 – NathanOliver

答えて

1

最初のオプションは、テンプレートメンバ関数(forwarding references)を使用することですが、それは仮想することはできませんし、いくつかのケースでは代わりにOBJのいくつかの他のタイプを受け入れることがあります。

template <typename T> 
void ThrSafeQueue::push(T&& x) { 
    lock_guard(mutex_); 
    queue_.push(std::move(x)); 
} 

第2の選択肢は、右参照を受け入れる機能と左参照をstatic_cast<Obj&&>の両方に残すことです。代わりにstatic_castのおstd::moveを使用することがあります。構文は、誤解を招くようです

template<typename T> 
void ThrSafeQueue::push(T && x) { 
    lock_guard(mutex_); 
    queue_.push(std::forward<T>(x)); 
} 

ThrSafeQueue t; 
t.push(Obj{}); 
Obj o; 
t.push(std::move(o)); 
+0

SFINAEを使用してテンプレート関数を制約することができます。また、参照は左辺値と右辺値参照と呼ばれます。 – NathanOliver

4

これは普遍的な参照が何のためにあるのかです。ここで&&は、実際には値の参照を指定するのではなく、テンプレート呼び出しに応じて左辺値または右辺値にバインドするuniversal referenceを指定します。

std::forwardは、そのテンプレートが左辺値の右辺値であるかどうかによって、std::moveに縮退するか、左辺値の場合はノーオペレーションかのどちらかを行います。

この例では、実際にはObjだけでなく、push()に何かを転送しようとします。これはおそらく問題ありませんが、Objでのみ使用するテンプレートの呼び出しを制限したい場合は、必要に応じてstd::enable_ifstd::is_sameという通常の技を使用できます。

+5

「汎用参照」という用語は推奨されていません。代わりに「転送参照」を使用する –

関連する問題