Reputation: 6846
While answering this question I came across an interesting difference in the overload resolution of rvalue to reference between member and non-member operators.
Given two non-member operators, one passing the left parameter as const and one as non-const, both GCC 4.4.3 and MSVC2010 choose the const version when called with an rvalue.
However, given two member operators, one const and one non-const, both compilers choose the non-const version.
I assume that both compilers are complying with the standard on this, so I am curious as to why there is this discrepancy between const overload resolution between members and non-members. Please enlighten me :)
Here's some code to illustrate the difference:
#include <iostream>
class C {
public:
C(int i) { }
/*
C operator<<(C const &rhs) {
std::cout << "member non-const" << std::endl;
return *this;
}
C operator<<(C const &rhs) const {
std::cout << "member const" << std::endl;
return *this;
}
//*/
};
C operator<<(C &lhs, C const &rhs) {
std::cout << "non-member non-const" << std::endl;
return lhs;
}
C operator<<(C const &lhs, C const &rhs) {
std::cout << "non-member const" << std::endl;
return lhs;
}
int main() {
// Will print:
// "non-member const" when member operators are commented out
// "member non-const" when members are uncommented
C(5) << 6;
}
Upvotes: 3
Views: 152
Reputation: 477110
Rvalues cannot bind to references-to-nonconst, so only the reference-to-const overload of the free function is viable: operator<<(C(5), 6);
.
This does not apply to the member-operator, which is simply C(5).operator<<(6)
, and the C
-object isn't a function argument. You would have to say static_cast<const C &>(C(5)) << 6
to get the const version there, since it is the constness of this
that distinguishes the two member operator overloads.
In the presence of both member and free-function operators, the member function is preferred, so putting all this together explains the observed behaviour.
Upvotes: 2