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;
     ^~~~

Reply via email to