0

私が正しく理解していれば、完全転送はユニバーサル参照を使用して、渡された引数が左辺値または右辺値であると推測します。それはいいです。

つまり、この機能を実現するには、テンプレート機能を作成する必要があります。考えられる例の1つは次のとおりです。

template <class T>
void func(T&& str){
    auto s = std::forward<T>(str);
    cout << s << endl;
}

ただし、それが唯一Tであるfuncべきだとわかっている場合はどうなりstd::stringますか? 考えられるオプションの 1 つは、 type を制限するためにstd::enable_ifandを使用することだと思います。しかし、それはより冗長になっています。std::is_sameT

この種の状況のベストプラクティスは何ですか?

編集:

Kerrek SB が提案したように、可能なシナリオを作成しようとしています。

私はstd::vector<double>メンバーとして持っているクラスを作っています。そして、 も取るコンストラクタを作りたいと思いますstd::vector<double>。引数が左辺値ならメンバーにコピーしたいが、そうでなければ移動したい。

それはある種の可能な例ですか?

4

2 に答える 2

3

値で渡します。

その場合、ユーザーは、ベクターの最後を破棄するかどうかを決定します。また、引数が明らかに右辺値である場合 (たとえば、関数呼び出し内で一時的なベクトルを構築する場合) にも期待どおりに機能します。ここでは、完全転送は不適切なツールです。

于 2013-06-20T09:24:15.053 に答える
3

テンプレートが必要ない場合は、次の 2 つのオプションがあります。

  1. 値渡しして移動します。
  2. コピー用に 1 つ、移動用に 1 つのオーバーロードがあります。

最初のオプションは、必要に応じて、引数に移動するかコピーするかをコンパイラに決定させます。次に、コードは、それが左辺値または右辺値から来たかどうかを気にせず (左辺値から来た場合、それは既にコピーです)、それをメンバーに移動します。最適化は別として、これには 1 回の移動のオーバーヘッドがある場合がありますが、移動が安価な場合 ( の場合のようにstd::vector) は無視できる場合があります。

foo(std::vector<double> v) : v(std::move(v)) {}

2 番目のオプションでは、コンパイラではなく、コードが決定を下します。これにより、前述の 1 回の移動で発生する可能性のあるオーバーヘッドを回避できますが、スケーラブルではないという問題があります。コピーまたは移動したいパラメータが 4 つある場合、16 の異なるオーバーロードが必要になります (この問題は、完全な転送が解決しようとするものです)。 )。

foo(std::vector<double> const& v) : v(v) {}
foo(std::vector<double>&& v) : v(std::move(v)) {}

テンプレート オプションは適切にスケーリングされますが、望ましくない状況での使用を防ぐために何らかの制約が必要になる場合があります (制約のないテンプレート コンストラクターの場合、誤ってコピーに使用される可能性があります)。

もちろん、移動がコピーに縮退するタイプ ( などstd::array) を使用している場合は、このセットの最初のオーバーロードを使用できます。

于 2013-06-20T09:28:29.743 に答える