Wednesday, January 26, 2022

Digest for comp.lang.c++@googlegroups.com - 6 updates in 1 topic

Paavo Helde <eesnimi@osa.pri.ee>: Jan 26 03:55PM +0200

Today I was surprised by an unexpected conversion from NSVC++ 2019. The
code example is here:
 
#include <iostream>
 
class A {
public:
A(size_t) {}
};
 
enum e { e1, e2, e3 };
 
class B {
public:
B(e) {}
};
 
void foo(A&&) {
std::cout << "Overload A\n";
}
 
void foo(const B&) {
std::cout << "Overload B\n";
}
 
int main() {
foo(e1);
}
 
MSVC++ 2019 compiles this fine and chooses overload A. g++ refuses to
compile it and reports an ambiguity. Who is right?
 
PS. If one replaces foo(A&&) with foo(const A&), then also MSVC reports
an ambiguity.
"Öö Tiib" <ootiib@hot.ee>: Jan 26 06:43AM -0800

On Wednesday, 26 January 2022 at 15:55:46 UTC+2, Paavo Helde wrote:
> compile it and reports an ambiguity. Who is right?
 
> PS. If one replaces foo(A&&) with foo(const A&), then also MSVC reports
> an ambiguity.
 
I suspect gcc is correct but cant bring normative proofs. The MSVC has its
legacy of being overly permissive there. I'm not even sure if it has stopped
accepting rvalues to initialise non-const lvalue references yet. Anyway I
like whatever diagnostics of doubt about whatever implicit conversions
as these keep causing major illusions and confusions.
Bonita Montero <Bonita.Montero@gmail.com>: Jan 26 03:50PM +0100

Am 26.01.2022 um 15:43 schrieb Öö Tiib:
> accepting rvalues to initialise non-const lvalue references yet. Anyway I
> like whatever diagnostics of doubt about whatever implicit conversions
> as these keep causing major illusions and confusions.
 
Maybe it would help to use a scoped enum which hasn't an implicit
conversion to int.
Paavo Helde <eesnimi@osa.pri.ee>: Jan 26 06:26PM +0200

26.01.2022 16:50 Bonita Montero kirjutas:
>>> Today I was surprised by an unexpected conversion
 
> Maybe it would help to use a scoped enum which hasn't an implicit
> conversion to int.
 
Yes, in new code scoped enums should be certainly preferred. Changing
them the scoped enums in old codebases is harder.
Bonita Montero <Bonita.Montero@gmail.com>: Jan 26 05:32PM +0100

Am 26.01.2022 um 17:26 schrieb Paavo Helde:
>> conversion to int.
 
> Yes, in new code scoped enums should be certainly preferred. Changing
> them the scoped enums in old codebases is harder.
 
When I have enums which are part of a namespace I mostly don't use
them, when I have enums which are part of a class I never use them.
Andrey Tarasevich <andreytarasevich@hotmail.com>: Jan 26 08:46AM -0800

On 1/26/2022 5:55 AM, Paavo Helde wrote:
> compile it and reports an ambiguity. Who is right?
 
> PS. If one replaces foo(A&&) with foo(const A&), then also MSVC reports
> an ambiguity.
 
The example can be simplified by taking `enum` out of the picture
 
#include <iostream>
 
class A {
public:
A(int) {}
};
 
class B {
public:
B(int) {}
};
 
void foo(A&&) {
std::cout << "Overload A\n";
}
 
void foo(const B&) {
std::cout << "Overload B\n";
}
 
int main() {
foo(0);
}
 
it will still exhibit the same behavior, but now it is fully
"symmetrical" with regard to `A` and `B`.
 
Experimenting with the example shows that MSVC seems to over-prioritize
the existing rule that binding rvalue reference to an rvalue is better
than binding an lvalue reference
http://eel.is/c++draft/over.ics.rank#3.2.3
 
However, in this case the two conversion sequences are incomparable
because they involve _different_ user-defined conversions. (In order to
be comparable they should use the same user-defined conversion.) This is
what is supposed to be recognized as an ambiguity by the compiler
http://eel.is/c++draft/over.ics.rank#3.3
 
If we simplify the example to a mere
 
#include <iostream>
 
class A {
public:
A(int) {}
};
 
void foo(A&&) {
std::cout << "Overload rvalue\n";
}
 
void foo(const A&) {
std::cout << "Overload lvalue\n";
}
 
int main() {
foo(0);
}
 
both candidate paths will use the the same user-defined conversion. The
call is no longer ambiguous, since the above
"rvalue-is-better-than-lvalue" logic kicks in.
 
--
Best regards,
Andrey Tarasevich
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: