Reputation: 14573
When writing conversion operators, if I provide both a conversion to const T&
and T&&
, will C++ always prefer the rvalue operator when possible? This seems to be true in this small test:
#include <algorithm>
#include <stdio.h>
struct holds {
operator int&&() { printf("moving!\n"); return std::move(i); }
operator const int&() const { printf("copying!\n"); return i; }
private:
int i = 0;
};
int main() {
holds h;
int val = h;
}
prints:
╰─▸ ./test
moving!
But perhaps someone that speaks spec-ese better than I can verify?
Upvotes: 7
Views: 680
Reputation: 75707
So I don't have the energy and time to bury myself in the standard for this one. I am sure someone will.
However I want to point out your assumption is wrong. And you are missing a crucial information: one operator is const
, one is not and it turns out this is the deciding factor in your case not &&
vs const &
. Let's see:
operator int&&();
operator const int&() ;
holds h;
int val = h; // compile error
Gives the error:
conversion from 'holds' to 'int' is ambiguous
So you see both conversion operators are equal and none is preferred so there is an ambiguity.
operator int&&();
operator const int&() ;
const holds h;
int val = h; // error no viable method
Well, this is an easy and non-interesting one: no mutable method can be called on a const object
&&
mutable, const&
const, object mutableoperator int&&();
operator const int&() const;
holds h;
int val = h; // calls holds::operator int&&()
Now the mutable method is preferred because the object is mutable
&&
mutable, const&
const, object constoperator int&&();
operator const int&() const;
const holds h;
int val = h; // calls holds::operator int const&() const
Now the const
method is the only choice as a mutable method cannot be called on a const object.
Upvotes: 2
Reputation: 137315
There's no such preference.
Your example is actually showing preference for a non-const member function over a const one when called on a non-const object.
Upvotes: 8