我应该啥时候 std::forward 函数调用?
Posted
技术标签:
【中文标题】我应该啥时候 std::forward 函数调用?【英文标题】:When should I std::forward a function call?我应该什么时候 std::forward 函数调用? 【发布时间】:2015-09-24 01:00:11 【问题描述】:我在 Effective Modern C++ 中看到的代码 sn-p 巧妙地实现了 instrumentation rationale 以创建 函数计时器:
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)(...
这看起来像是 the use of familiar template syntax in lambda expressions 的一个很好的用例,以防我们想让计时器类型成为编译时间常数。
【问题讨论】:
我认为这可能是因为func
可以使用非常量运算符()来实现大函数对象。这样,您可以避免无意义的复制,并允许函数对象的突变
表达式的 type 不会随强制转换而改变,但它的 value category 会。这就是全部而且只有point of forward
。
目的是确保选择正确的ref-qualified 重载operator()
。
func 的类型,一旦在函数中,就不再是 r 值引用了(假设它是在传入时)。如果是这样,每次你将它传递给一个函数时,它都会尝试移动它!这就是需要std::forward
的原因。
@Cameron 这里没有任何东西被传递给另一个函数。我的问题是针对这种特定情况的。 Tavian Barnes 指出的原因(并由 Kerrek 暗示)似乎令人信服
【参考方案1】:
更好地描述 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
的主体内是一个左值 (because it has a name)。如果您没有forward
函数参数,则永远无法调用&&
限定的重载。此外,如果没有 &
限定的重载,那么即使调用者向您传递了一个右值 foo
实例,您的代码也将无法编译。
Live demo
【讨论】:
您同意decltype(func)
部分仅在没有为func
拼写类型信息的通用lambda 中需要吗?如果是这种情况,我可以为template <class F> void Foo(F&& func)
写std::forward<F>(func)(...)
并做同样的事情对吗?
@NikosAthanasiou 是的,那会做同样的事情
直到我意识到func
不仅可以是函数指针、lambda 或std::function
实例,它还可以是任何声明@ 的类的实例时,我才明白为什么这很重要987654337@。只有这样它才变得重要。以上是关于我应该啥时候 std::forward 函数调用?的主要内容,如果未能解决你的问题,请参考以下文章
普通的右值引用和 std::forward 返回的有啥区别?
在 c 语言中调用函数时,啥时候应该添加“&”,啥时候不应该添加?
SGI slist 和 C++11 forward_list 有啥区别?