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;
}
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 theC-object isn’t a function argument. You would have to saystatic_cast<const C &>(C(5)) << 6to get the const version there, since it is the constness ofthisthat 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.