Working from the Efficient Modern C++, Item 25. we have an example
class Widget {
public:
template<typename T>
void setName(T&& newName)
{ name = std::forward<T>(newName); }
...
};
class Widget {
public:
void setName(const std::string& newName)
{ name = newName; }
void setName(std::string&& newName)
{ name = std::move(newName); }
...
};
Widget w;
w.setName("Adela Novak");
Now assuming case 1, the book states that the literal is conveyed to the assignment operator for t std::string inside w's name data member.
Assuming case 2, the book states that -> first a temporary is created from the literal, calling the string constructor, so the setName parameter can bind to it, and than this temporary is moved into w's name data member.
Why does this difference in behavior come about and how am I to think about it?
Namely, why is there no need for a temporary in case 1? Why is there difference? Is T&& not deduced to be an rvalue reference to a string, thus arriving at the same behavior as case 2 (obviously not, as per the book, but why)?
In case 1, T
is deduced to be const char (&)[12]
, not std::string
. There is no reason for the compiler to promote the string literal to std::string
yet. In case 2, every overload requires takes a reference to an std::string
, which forces the creation of a temporary std::string
to which a reference can be bound using the implicit const char*
constructor.
Note that while an rvalue reference such as std::string &&
may only bind to an rvalue, the templated equivalent T &&
may bind to both rvalues and lvalues.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With