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 13.3.3.1.1, 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.

> 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 13.3.3.1.1, 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