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)(...

  • 据我了解,我们实际上是将函数转换为其原始类型,但为什么需要这样做呢?看起来一个简单的调用就可以解决问题。
  • 还有其他情况我们使用完美转发来进行函数调用吗?

如果我们想让计时器类型成为编译时间常数,这看起来像是在 lambda 表达式中使用熟悉的模板语法的一个很好的用例。

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'; }
};

请记住,在 lambda 的主体内func是一个左值(因为它有一个名称)。如果您没有forward函数参数,&&则永远无法调用限定的重载。此外,如果&不存在限定的重载,那么即使调用者向您传递了一个右值foo实例,您的代码也将无法编译。

现场演示

于 2015-07-06T19:06:59.093 回答