c++ - 什么时候 forward<T> 等同于 forward<decltype(Targ)> ?

标签 c++ c++14 perfect-forwarding

假设我想要一个通用的高阶函数。最常见的方法是:

一个。通用 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 );

如果 TF&&,那么返回类型仍然是 T&& 因为 T&& && == T&&。如果 T 只是一个 F(值类型),则返回类型仍然相同(T && == T&&)。引用折叠规则可以在 this site 上找到.

TLDR:没有有效的区别,因为引用折叠产生相同的类型。

关于c++ - 什么时候 forward<T> 等同于 forward<decltype(Targ)> ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33193254/

相关文章:

c++ - 在异常处理中通过引用捕获未在 C++ 中给出预期的输出

C++ - 从 'void*' 到 'uint8_t**' 的无效转换

c++ - 折叠嵌套的 std::future

c++ - 完美转发和 std::tuple(或其他模板类)

c++ - 将非空终止 c 字符串转换为终止 c 字符串的最干净方法

c++ - c++ - 如何让客户端在将数据写入管道之前检查服务器是否完成了从管道的读取操作

c++ - 默认复制赋值运算符未通过 is_copy_assignable 测试

c++ - 模板类型定义的数组初始化

c++ - 转发到就地构造函数

c++ - 为什么 C++11 move 运算符 (=) 的行为不同