为什么一个完美的转发功能必须模板化?
为什么以下代码有效:
template<typename T1>
void foo(T1 &&arg) { bar(std::forward<T1>(arg)); }
std::string str = "Hello World";
foo(str); // Valid even though str is an lvalue
foo(std::string("Hello World")); // Valid because literal is rvalue
但无效:
void foo(std::string &&arg) { bar(std::forward<std::string>(arg)); }
std::string str = "Hello World";
foo(str); // Invalid, str is not convertible to an rvalue
foo(std::string("Hello World")); // Valid
为什么示例 2 中的左值没有以与示例 1 中相同的方式解析?
另外,为什么标准认为需要在 std::forwardforward
即可显示意图。
如果这不是一个标准的东西而只是我的编译器,那么我使用的是 msvc10,这可以解释糟糕的 C++11 支持。
编辑 1:将文字 "Hello World"
更改为 std::string("Hello World")
以创建右值。
Why is the following code valid:
template<typename T1>
void foo(T1 &&arg) { bar(std::forward<T1>(arg)); }
std::string str = "Hello World";
foo(str); // Valid even though str is an lvalue
foo(std::string("Hello World")); // Valid because literal is rvalue
But not:
void foo(std::string &&arg) { bar(std::forward<std::string>(arg)); }
std::string str = "Hello World";
foo(str); // Invalid, str is not convertible to an rvalue
foo(std::string("Hello World")); // Valid
Why doesn't the lvalue in example 2 get resolved in the same manner that it does in example 1?
Also, why does the standard feel it important to need to provide the argument type in std::forward<T>
versus simple deducing it? Simply calling forward
is showing intention, regardless of the type.
If this isn't a standard thing and just my compiler, I am using msvc10, which would explain the crappy C++11 support.
Edit 1: Changed the literal "Hello World"
to be std::string("Hello World")
to make an rvalue.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
首先,阅读本文以全面了解转发。 (是的,我将大部分答案委托给其他地方。)
总而言之,转发意味着左值保持左值,右值保持右值。您无法使用单一类型来做到这一点,因此您需要两种。因此,对于每个转发的参数,您需要该参数的两个版本,这需要该函数总共 2N 个组合。您可以对函数的所有组合进行编码,但是如果您使用模板,那么系统会根据需要为您生成这些不同的组合。
如果您正在尝试优化副本和移动,例如:
那么您应该停止并这样做:
您只需要一个构造函数。 指南:如果您需要自己的数据副本,请在参数列表中制作该副本;这使得调用者和编译器能够决定复制或移动。
First of all, read this to get a full idea of forwarding. (Yes, I'm delegating most of this answer elsewhere.)
To summarize, forwarding means that lvalues stay lvalues and rvalues stay rvalues. You can't do that with a single type, so you need two. So for each forwarded argument, you need two versions for that argument, which requires 2N combinations total for the function. You could code all the combinations of the function, but if you use templates then those various combinations are generated for you as needed.
If you're trying to optimize copies and moves, such as in:
Then you should stop and do it this way:
You only need one constructor. Guideline: if you need your own copy of the data, make that copy in the parameter list; this enables the decision to copy or move up to the caller and compiler.