Reputation: 9852
The following are roughly equivalent in terms of being dangerous but the second 2 are disallowed by the language yet the first one isn't.
#include <algorithm>
#include <vector>
int main()
{
std::vector<int> v;
// allowed
std::vector<int>().swap(v);
// not allowed
v.swap(std::vector<int>());
// not allowed
std::swap(std::vector<int>(), v);
}
I know Visual Studio lets all these through as a compiler extension and I'm ignoring that for this question.
I'm not actually arguing that the first one be disallowed - I'd actually prefer the second 2 be allowed (there are places where this makes code more elegant and normally when C++ lets you do some thing which may be dangerous but could be benefical it lets it through) but it seems weird that there is a difference here.
Upvotes: 4
Views: 163
Reputation: 254771
Function arguments are subject to type conversions, which create a temporary rvalue. This would give confusing results if the function were passed a non-const reference to that temporary, when you expect it modify the argument. This potential confusion is a justification for not allowing temporaries to bind to non-const lvalue references.
There is no corresponding confusion for other reference types; const
references leave the object unmodified as expected, and rvalue references are specifically intended to bind to rvalues. Neither does the issue arise for member functions, since type conversions aren't applied to the object being called on.
Upvotes: 2