https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86521
Bug ID: 86521 Summary: GCC 8 selects incorrect overload of ref-qualified conversion operator template Product: gcc Version: 8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: yannick.lepennec+gcc at live dot fr Target Milestone: --- Please consider the following code, built with `g++ -std=c++17 -Wall -Wextra -pedantic`. It used to be accepted by GCC 7.3, but this is no longer the case since GCC 8. Godbolt for convenience: https://godbolt.org/g/oXFQex It was broken since r258755, which makes this code ICE instead. The ICE itself was fixed in r259123, but said fix now makes GCC reject it with the below error. This is still the case on today's r262658. As far as I can tell, GCC seems to be incorrectly selecting the `const&` overload instead of the `&&` one. #include <utility> template<typename T> struct require_cast { T val; template<typename U> explicit operator U () && { return std::move(val); } template<typename U> explicit operator U const& () const& { return val; } }; struct base { base() = default; base(base&&) = default; base& operator=(base&&) = default; base(base const&) = delete; base& operator=(base const&) = delete; }; struct derived : base {}; int main() { require_cast<derived> d; (void)static_cast<base>(std::move(d)); (void)static_cast<derived>(std::move(d)); } repro.c++: In function ‘int main()’: repro.c++:34:41: error: use of deleted function ‘base::base(const base&)’ (void)static_cast<base>(std::move(d)); ^ repro.c++:23:5: note: declared here base(base const&) = delete; ^~~~ repro.c++:35:44: error: use of deleted function ‘derived::derived(const derived&)’ (void)static_cast<derived>(std::move(d)); ^ repro.c++:27:8: note: ‘derived::derived(const derived&)’ is implicitly deleted because the default definition would be ill-formed: struct derived : base {}; ^~~~~~~ repro.c++:27:8: error: use of deleted function ‘base::base(const base&)’ repro.c++:23:5: note: declared here base(base const&) = delete; ^~~~