12

std::forwardへの引数として使用する場合、関数パラメーターを使用する必要がありますstd::forward_as_tupleか?

template<class ... List>
void fn(List&& ... list){
   // do I need this forward?
   call_fn( forward_as_tuple( forward<List>(list)... ) );  
}

それらが右辺値参照として格納されることはわかっていますが、他に考慮すべきことはありますか?

4

3 に答える 3

9

std::forwardへの引数の値カテゴリを保持するには、 を使用する必要がありますfn()。引数は 内fnで名前を持っているため、左辺値であり、そうでないstd::forward場合は常にそのまま に渡されstd::forward_as_tupleます。

違いは、次の例を使用して実証できます。

template<typename T>
void bar2(T&& t)
{
    std::cout << __PRETTY_FUNCTION__ << ' '
               << std::is_rvalue_reference<decltype(t)>::value << '\n';
}

template<typename T>
void bar1(T&& t)
{
    std::cout << __PRETTY_FUNCTION__ << ' '
              << std::is_rvalue_reference<decltype(t)>::value << '\n';
    bar2(std::forward<T>(t));
    bar2(t);
}

bar1は常に引数を に渡します。bar2一度はstd::forwardあり、一度はなしです。それでは、左辺値と右辺値の引数でそれらを呼び出しましょう。

foo f;
bar1(f);
std::cout << "--------\n";
bar1(foo{});

出力:

void bar1(T&&) [with T = foo&] 0
void bar2(T&&) [with T = foo&] 0
void bar2(T&&) [with T = foo&] 0
--------
void bar1(T&&) [with T = foo] 1
void bar2(T&&) [with T = foo] 1
void bar2(T&&) [with T = foo&] 0

出力からわかるように、どちらの場合も を使用せずにstd::forward、引数は左辺値として に渡されbar2ます。

于 2014-08-21T14:23:06.627 に答える
3

std::forwardはい、ほぼ確実にここで使用したいと思います。これは、 の引数listが to の呼び出し後に使用されないことを前提としていますcall_fnこれは、std::forward完全な転送のセマンティクスを実行したいという点で、の典型的な使用例です。

std::forward その引数の値カテゴリを保持します(つまり、左辺値は左辺値として、右辺値は右辺値として)。が呼び出さstd::forward_as_tupleれたかのように、今度は同じことを行いますstd::tuple<List&&...>(std::forward<List>(list)...)

「右辺値参照として保存」に関する注意。Listパラメーター パック内の引数がすべて右辺値参照であるというわけではありません(そうである可能性があります) がList、このコンテキストでは推定されているため、参照の折りたたみが適用され、推定された型は右辺値参照または左辺値参照である可能性があります。の作成中に、std::tuple維持/維持したいのはこの区別です。

于 2014-08-21T14:20:14.313 に答える
1

はい、完全な転送セマンティクスを維持したい場合。あなたの例では:

template<class ... List>
void fn(List&& ... list)

は実際にはテンプレート パラメーターでList&&あるtypeは、右辺値参照ではなくユニバーサル参照です。そうしないと、渡された右辺値参照内で、参照の崩壊により左辺値参照として表示されます。Liststd::forwardstd::forward_as_tuplestd::forward_as_tuplefn

于 2014-08-21T14:01:54.433 に答える