web-dev-qa-db-ja.com

引数を転送するためにstd :: forwardを使用する場合

C++ 0xは、std::forwardの使用例を示しています。

template<class T>
void foo(T&& arg) 
{
  bar(std::forward<T>(arg));
}

常にstd::forwardを使用することが有利なのはいつですか?

また、パラメーター宣言で&&を使用する必要がありますが、すべての場合に有効ですか?関数が&&で宣言されている場合、関数に一時変数を渡す必要があると思ったので、fooを任意のパラメーターで呼び出すことができますか?

最後に、次のような関数呼び出しがある場合:

template<int val, typename... Params>
void doSomething(Params... args) {
  doSomethingElse<val, Params...>(args...);
}

代わりにこれを使用する必要があります:

template<int val, typename... Params>
void doSomething(Params&&... args) {
  doSomethingElse<val, Params...>(std::forward<Params>(args)...);
}

また、関数でパラメーターを2回使用する場合、つまり同時に2つの関数に転送する場合、std::forwardを使用するのが賢明ですか? std::forwardは、同じものを一時的なものに2回変換して、メモリを移動し、2回目の使用に対して無効にしませんか?次のコードは大丈夫でしょうか?

template<int val, typename... Params>
void doSomething(Params&&... args) {
  doSomethingElse<val, Params...>(std::forward<Params>(args)...);
  doSomethingWeird<val, Params...>(std::forward<Params>(args)...);
}

私はstd::forwardに少し混乱しているので、喜んで整理を使用します。

147
coyotte508

最初の例のように使用します。

template <typename T> void f(T && x)
{
  g(std::forward<T>(x));
}

template <typename ...Args> void f(Args && ...args)
{
  g(std::forward<Args>(args)...);
}

これは、 参照の折りたたみ規則T = U&の場合はT&& = U&ですが、T = U&&の場合はT&& = U&&であるため、常に関数本体内の正しい型。最後に、forwardが左辺値になったxを(現在は名前を持っているために)最初に右辺値参照に戻す必要があります。

ただし、通常は意味をなさないので、何かを複数回転送しないでください。転送とは、引数を最後の呼び出し元まで移動する可能性があることを意味します。移動したのでなくなったので、再び使用することはできません(おそらく意図した方法で)。

116
Kerrek SB