Re: Bad use of stringstream temporary?
On 27 Mrz., 01:06, K. Frank wrote:
Thanks again for your explanation.
I should probably mention that there is more to && than its ability to
bind to temporaries. Not knowing more about && might lead to bad
surprizes. So, here are some more things you ought to know about
rvalue references:
For some object type T the type T&& will be an rvalue reference. It's
like an lvalue reference with two differences: the rules on how such a
reference can be initialized are different (obviously) and a function
call with an rvalue reference return type is considered an rvalue
expression (unlike the name of an rvalue reference).
For some reference type T the type T&& is not necessarily an rvalue
reference anymore. If T is an lvalue reference, then so is T&&. This
is called "reference collapsing". Examples:
T T&& T&
------------------
int int&& int&
int&& int&& int&
int& int& int&
Finally, there is a funny deduction rule that only applies to the
pattern T&& where T is a template parameter like in case #2:
template<class T> void bar(T const&) {} // #1
template<class T> void bar(T && r) { // #2
r = 0; // modifying temporaries does not hurt nobody, right?
}
int main() {
int i = 1729;
bar(99); // #2 with T=int, T&&=int&&
bar(i); // #2 with T=int&, T&&=int&
assert(i==1729); // test will FAIL!
}
In both calls #2 is picked because it is a better match:
call #1 #2
-----------------------------------------------
bar(99) bar<int>(int const&) bar<int>(int&&)
bar(i) bar<int>(int const&) bar<int&>(int&)
This is what I meant by bad surprizes. The purpose of this deduction
rule is to retain the information about the function argument's value
category as part of the type parameter. The "perfect forwarding"
technique relies on this behaviour.
SG