Reputation: 757
Consider the following code (taken from https://en.cppreference.com/w/cpp/language/cast_operator)
struct To {
To() = default;
To(const struct From&) {} // converting constructor
};
struct From {
operator To() const {return To();} // conversion function
};
int main()
{
From f;
To t2 = f; // copy-initialization: ambiguous
// (note, if conversion function is from a non-const type, e.g.
// From::operator To();, it will be selected instead of the ctor in this case)
}
As the comments say, the following line is indeed ambiguous because there are two candidates (The conversion function and the converting constructor are equally applicable)
To t2 = f; //compile error
However, as the note says if I remove the const
from the conversion
function resulting in the following code:
struct From {
operator To() {return To();} // conversion function
};
The call compiles fine.
The const
qualifier should not affect the conversion
function return value, so why the call is no longer ambiguous?
Upvotes: 3
Views: 93
Reputation: 238311
The const qualifier should not affect the conversion function return value
It doesn't affect that indeed, but that's also not relevant.
What it does affect is the argument - which is the implicit reference to this
. The implicit argument is a const lvalue for const member functions and non-const for non-const member functions. The arguments are what affect the overload resolution.
In the original code, both the constructor and the conversion operator arguments are exactly the same, so a conversion sequence from any type to either argument is equally preferable, and therefore ambiguous.
Without the const, your non-const lvalue expression f
doesn't need any conversions, while the constructor does require a conversion into const lvalue. As such, the operator is preferred by the overload resolution. If you had written const From f;
, then the constructor whose argument is const would have been chosen instead as in that case, the non-const conversion operator wouldn't even be valid candidate.
Upvotes: 1
Reputation: 170055
The const qualifier should not affect the conversion function return value, so why the call is no longer ambiguous?
It does not affect the result, but it affects overload resolution for choosing the best viable method. It's similar to the case of these made up functions
To make(From const&);
To make(From&);
Which overload is the better match in make(f)
? It's the second one, because the parameter type, being non-const, better matches the argument (f
), which is non-const itself.
Upvotes: 3