Mike Vine
Mike Vine

Reputation: 9852

Why are you not allowed to bind a rvalue reference to a non const reference but you are allowed to call non const member functions on one

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

Answers (1)

Mike Seymour
Mike Seymour

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

Related Questions