私は最近、C++で転送参照を調べていますが、私は現在の概念の理解を簡単にまとめています。転送参照とテンプレートコードのconst左辺参照
テンプレート関数foo
が、T
という1つの引数に転送参照を渡しているとします。
template<typename T>
void foo(T&& arg);
私は左辺値でこの関数を呼び出した場合、T
がT&
がarg
パラメータが原因ルールT& && -> T&
を崩壊参照するタイプT&
でも作るよう推測されます。
この関数は、このような関数呼び出しの結果として、無名の一時的で呼び出された場合は、T
はarg
パラメータの型T&&
でも作るT
と推測されます。
foo
の中にありますが、arg
は名前付きパラメータなので、パラメータを他の関数に渡して値のカテゴリを維持したい場合はstd::forward
を使用する必要があります。
template<typename T>
void foo(T&& arg)
{
bar(std::forward<T>(arg));
}
私が理解する限り、cv修飾子はこの転送の影響を受けません。つまり、fooを名前付きconst変数で呼び出すと、T
はconst T&
と推定され、arg
の型は参照の折りたたみ規則のためにconst T&
になります。 const値については、T
はconst T
と推定され、arg
はconst T&&
となります。
これはまた、arg
の値をfoo
に変更すると、その変数にin変数を渡した場合にコンパイル時エラーが発生することを意味します。
今質問します。 コンテナクラスを作成していて、コンテナにオブジェクトを挿入するメソッドを提供したいとします。 insert
メンバ関数がobj
に転送基準を取ることにより
template<typename T>
class Container
{
public:
void insert(T&& obj) { storage[size++] = std::forward<T>(obj); }
private:
T *storage;
std::size_t size;
/* ... */
};
insert
場合、私は、記憶されたタイプT
の移動代入演算子を活用するstd::forward
を使用することができInfactは、一時的なオブジェクトを通過させました。
以前は、参照を転送することについて何も知らなかった場合、const値参照を使用してこのメンバ関数を記述していました。 void insert(const T& obj)
insert
に一時オブジェクトが渡された場合、このコードは(おそらくより効率的な)移動代入演算子を利用しないことが欠点です。
私は何かを見逃していないと仮定します。
挿入機能に2つの過負荷を与える理由はありますか? 1つは左辺値参照を取り、もう一方は転送参照を取る。
void insert(const T& obj);
void insert(T&& obj);
私が求めている理由は、the reference documentation for std::vector
がpush_back
方法は2つのオーバーロードで来ることを述べていることです。
void push_back (const value_type& val);
void push_back (value_type&& val);
なぜ最初のバージョン(const value_type&
を取って)必要がありますか?
あなたの 'insert(T && obj)'はフォワーディングリファレンスではありません。それはクラスによって固定されています。 – Jarod42