https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83445

--- Comment #4 from Alexander Karzhenkov <karzh at mail dot ru> ---
r269667 concerns initializing an object from prvalue.
Here we have `Target` being initialized from lvalue if type `Source`.

What we can consider as being initialized from prvalue is the argument of copy
constructor. It would get the result of `Source::operator Target()`, but this
can be optimized out here. Such optimization, however, is not a mandatory copy
elision (introduced by C++17). The latter is not applicable to reference
initialization.

The mandatory copy elision also is not applicable to initialization `Target`
from `Source` as they are different types (see [dcl.init], item 17.6.1).

In case of direct initialization the candidates are all constructors of
`Target`, but not the conversion operator of `Source` (see [over.match.ctor]).
One of constructors must be called (but this call can be optimized out). The
question here is about implicit conversion for argument of the constructor.

Overload resolution matches the argument of each constructor against the
initializer (which is lvalue of `Source`). The best match is for `Target(Source
const&)` as it doesn't require any user-defined conversion.

If compiler prefers `Target(Target const&)`, it has to perform copy
initialization of its argument from `Source`. Such copy initialization cannot
be performed without user-defined conversion, so it is worse.

Invoking the constructor `Target(Source const&)` is user-defined conversion
whereas binding `Source const&` to `source` is not. But the constructor is
invoked explicitly; overload resolution only takes into account
argument/parameter match.

Reply via email to