13

私が『 Effective Modern C++』で見たコード スニペットには、関数 timerを作成するインストルメンテーションの理論的根拠の巧妙な実装があります。

auto timeFuncInvocation = 
    [](auto&& func, auto&&... params)
    {
        start timer; 
        std::forward<decltype(func)>(func)(
            std::forward<decltype(params)>(params)...); 
        stop timer and record elapsed time; 
    };

私の質問はstd::forward<decltype(func)>(func)(...

  • 私の理解では、実際には関数を元の型にキャストしていますが、なぜこれが必要なのですか? 簡単な呼び出しでうまくいくようです。
  • 関数呼び出しを行うために完全転送を使用する他のケースはありますか?

これは、タイマー型をコンパイル時の定数にしたい場合に備えて、ラムダ式で使い慣れたテンプレート構文を使用するための良い使用例のように見えます。

4

1 に答える 1

16

std::forward<decltype(func)>(func)(...)何をしているのかをよりよく説明すると、 lambda に渡された引数の値カテゴリが保持されます

ref 修飾されたoperator()オーバーロードを持つ次のファンクターを検討してください。

struct foo
{
    void operator()() const &&
    { std::cout << __PRETTY_FUNCTION__ << '\n'; }

    void operator()() const &
    { std::cout << __PRETTY_FUNCTION__ << '\n'; }
};

ラムダの本体内にfunc左辺値があることに注意してください (名前があるため)。forward関数の引数を指定しなかった場合、&&修飾されたオーバーロードを呼び出すことはできません。さらに、&修飾されたオーバーロードが存在しない場合、呼び出し元が右辺値fooインスタンスを渡したとしても、コードはコンパイルに失敗します。

ライブデモ

于 2015-07-06T19:06:59.093 に答える