C++ Logo


Advanced search

Re: Not understanding rvalue reference matching rules in overloaded functions.

From: Edward Diener <eldlistmailingz_at_[hidden]>
Date: Tue, 1 Jun 2021 13:21:05 -0400
On 6/1/2021 12:31 PM, Andrew Schepler via Std-Discussion wrote:
> On Tue, Jun 1, 2021 at 9:55 AM Edward Diener via Std-Discussion
> <std-discussion_at_[hidden]
> <mailto:std-discussion_at_[hidden]>> wrote:
> The code:
> #include <iostream>
> #include <utility>
> void afunc(int)
> {
> std::cout << "\nafunc(int)\n";
> }
> void afunc(int &&)
> {
> std::cout << "\nafunc(int &&)\n";
> }
> int main()
> {
> int i = 0;
> afunc(std::move(i));
> }
> The result is an error saying that the call to 'afunc' is ambiguous.
> Since std::move creates an rvalue reference and one of the overloads to
> afunc takes an rvalue reference, for an exact match, I do not
> understand
> the error. Would someone please explain and cite the section of the
> C++11 standard which explains why the exact match is an equal match to
> the other overload, thereby causing ambiguity ?
> Summary: Both conversion sequences are the identity conversion, and none
> of the special cases where value category and reference parameters do
> rank overloads apply.
> First, note that an expression effectively never has a reference type
> per [expr]/5. std::move(i) is an xvalue which has type int.

I actually did not realize before that the result of an expression can
never be a reference type. I do not quite understand why this was
decided, but given that it was I know it now.

> If we call "void afunc(int)" = F1 and "void afunc(int&&)" = F2, then
> ICS1(F1) is the identity conversion since no other row in
> [over.ics.scs]/3's Table 12 applies. For F2, note [over.ics.ref]/1:
> "When a parameter of reference type binds directly (8.5.3) to an
> argument expression, the implicit conversion sequence is the identity
> conversion, unless the argument expression has a type that is a derived
> class of the parameter type, in which case...." Since initialization of
> the reference parameter does not require a temporary object, the
> parameter does "bind directly", and ICS1(F2) is also the identity
> conversion.

I am not sure what "the implicit conversion sequence" means but for the
sake of my example I understand that the type of 'int' for an xvalue
binds directly to a parameter which is an 'int &&' and is therefore
considered an identity conversion.

My basic misunderstanding was thinking that an expression could evaluate
to a reference type and therefore that matching to a parameter which
itself was the same reference type had to be a better match than
matching to a parameter which was not a reference type.

Thank you very much for your explanation !

> Additional rules for ranking implicit conversion sequences involving
> references are found in [over.ics.rank]. Paragraph 3 lists:
> > Two implicit conversion sequences of the same form are
> indistinguishable conversion sequences unless one of the following rules
> applies:
> > - Standard conversion sequence S1 is a better conversion sequence S2 if
> > - S1 is a proper subsequence of S2 (comparing the conversion
> sequences in the canonical form defined by, excluding any
> Lvalue Transformation; the identity conversion sequence is considered to
> be a subsequence of any non-identity conversion sequence) or, if not that,
> > - the rank of S1 is better than the rank of S2, or S1 and S2 have
> the same rank and are distinguishable by the rules in the paragraph
> below, or, if not that,
> > - S1 and S2 differ only in their qualification conversion and ...
> > - S1 and S2 are reference bindings (8.5.3) and ...
> > - S1 and S2 are reference bindings (8.5.3) and ...
> > - S1 and S2 are reference bindings (8.5.3), and ...
> > - User-defined conversion sequence U1 is a better conversion sequence
> than another user-defined conversion sequence U2 if ...
> > - List-initialization sequence L1 is a better conversion sequence
> than list-initialization sequence L2 if ...
> (Yes, the repeated "reference bindings" bullets are intentional; the
> parts after "and" are different.) In the context, "same form" only means
> that the implicit conversion sequences are both standard conversion
> sequences, or both user-defined conversion sequences, or both ellipsis
> conversion sequences. (Note every well-formed list-initialization
> sequence is also either a standard conversion sequence or user-defined
> conversion sequence, per [over.ics.list].)
> None of these points apply, so ICS1(F1) and ICS2(F2) are
> indistinguishable, and overload resolution for the functions is ambiguous.

Received on 2021-06-01 12:21:51