C++11:std的微妙之处::转发:身份真的有必要吗?
c++11: subtlety of std::forward: Is identity really necessary?
我设置了一个测试用例来学习完美转发。
std::string inner(const std::string& str ) {
return "const std::string&";
}
std::string inner(std::string& str ) {
return "std::string&";
}
std::string inner(const std::string&& str ) {
return "const std::string&&";
}
std::string inner(std::string&& str ) {
return "std::string&&";
}
template <typename T> void outer(T&& t) {
std::cout << "t: " << t << std::endl;
std::cout << "perfect forward: " << inner(std::forward<T>(t)) << std::endl;
std::cout << std::endl;
}
void PerfectForwarding()
{
outer("literal");
outer(lvalue);
outer(constlvalue);
outer(rvalue());
outer(constrvalue());
}
std::forward
按预期工作。 当我在没有标识的情况下实现自己的转发函数时,会出现有趣的行为:
template <typename T> T&& MyForward(T& t)
{
return ((T&&)t);
}
用外部的MyForward
替换std::forward
会得到完全相同的结果! 这种行为引出了一个问题,为什么使用身份?
编译器 VS2010
更新1:关于防止类型扣除
AFAIK,特殊类型扣除规则仅在T&&上激活。 请注意 forward、forward(typename identity<T>::type& t)
的定义。 参数类型只有一个 &. 事实上,在我更改 MyForward 以使用标识并省略 (T&&) 强制转换后,该示例无法编译。 从表面上看,从左值到右值的铸造似乎使前向工作。
更新 2:在 GCC 4.5 的 ideone.com 上测试,行为相同。
remove_reference<T>
(identity
在旧版本的草稿中,但已更改为remove_reference
)用于防止类型推断:std::forward
仅适用于显式类型参数。否则,将编译以下内容:
std::forward(t)
。但它不会做正确的事情。
关于左值/右值的问题,请注意std::forward
有两个重载:一个用于右值,另一个用于右值。
事实上,给出的MyForward
实现更像是std::move
:它将左值转换为右值(不同之处在于 move 也接受右值)。
我在VS 2010中检查了forward
和identity
的定义。您的MyForward
和他们的forward
之间的唯一区别是您使用 T&
参数,而他们使用 typename identity<T>::type&
参数。而identity<T>::type
只是T
.
这种差异最重要的(也可能是唯一)影响是,要使用它们的forward
必须显式指定模板参数,而MyForward
的模板参数可以从调用中推导出来。
- 在决定是通过参考还是通过价值时,尺寸真的是一个问题吗
- LibGit2 SSH身份验证失败
- 字节真的是最小可寻址单元吗
- 以非特权用户身份查询 NTFS 特殊文件的元数据?
- 如果我真的真的想从 STL 容器继承,并且我继承构造函数并删除新运算符,会发生什么?
- 如何在 std::vector 中找到<bool>哪些索引是真的?
- std::string 的对象真的可以移动吗?
- 在这种情况下,我真的复制了字节还是复制了字符?
- int8_t和uint8_t真的是整数吗?它们有什么用?
- 真的没有来自 std::string_view 的 std::string 的显式构造函数吗?
- 为什么 WinInet 在通过 FQDN 连接时无法通过协商自动进行身份验证,但如果通过 IP 连接则成功?
- 查找不等式为真的次数时出现问题
- 考虑到其他好处,关键字'auto'真的有助于简化调试C++吗?
- 有没有更好的方法来处理异常? try-catch块真的很丑
- 在为嵌套类定义行外友元时,我真的必须打破封装吗?
- 你如何理解"std: :forward is just syntactic sugar"?这是真的吗?
- "std::forward"和"std::move"真的不生成代码吗?
- VS 2017 和 2019 运行 c++ 真的很慢
- 结构和类在C++中真的等价吗?
- C++11:std的微妙之处::转发:身份真的有必要吗?