假设我想要一个通用的高阶函数。最常见的方法是:
一个。通用 lambda
auto F1 = [](auto f) { /*...*/ }
B.函数模板
template<class F> auto F2(F&& f) { /*...*/ }
我的问题是关于如何在高阶函数中使用 f
。虽然在情况 A 中只有一种方法可以做到这一点:
std::forward<decltype(f)>(f)(...);
情况B至少有两种方式:
std::forward<decltype(f)>(f)(...);
std::forward<F>(f)(...);
这些方式是否等效?如果不是,“打破平局”的一些例子是什么?
最佳答案
正如所写,案例 A 和案例 B 的声明是不同的。案例 B 可以推导出左值或右值引用,但案例 A 只能推导出值类型。 auto
的推导类似于模板参数,因此将 auto
更改为 auto&&
以匹配声明。
为了回答您的问题,它们 是等价的。唯一的区别是引用折叠发生在情况 B 中。decltype(f)
将始终是一个引用,而 F
将是一个值类型,当参数传递给 F2
是一个右值:
F2(<lvalue>); decltype(f) == T&, F == T&
F2(<rvalue>); decltype(f) == T&&, F == T
这对 std::forward
无关紧要,因为引用折叠总是会产生正确的类型。
template< class T >
constexpr T&& forward( typename std::remove_reference<T>::type& t );
如果 T
是 F&&
,那么返回类型仍然是 T&&
因为 T&& && == T&&
。如果 T
只是一个 F
(值类型),则返回类型仍然相同(T && == T&&
)。引用折叠规则可以在 this site 上找到.
TLDR:没有有效的区别,因为引用折叠产生相同的类型。
关于c++ - 什么时候 forward<T> 等同于 forward<decltype(Targ)> ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33193254/