https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90745

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Resolution|---                         |INVALID
             Status|NEW                         |RESOLVED

--- Comment #7 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Slightly reduced:

#include <tuple>

template <class Op, class P0, class P1>
struct Expr
{
    Op op;
    std::tuple<P0, P1> t;

    using R = decltype(op(*(std::get<0>(t).p), *(std::get<1>(t).p)));
    operator R() { return op(*(std::get<0>(t).p), *(std::get<1>(t).p)); }
};

template <class Op, class P0, class P1> inline auto
expr(Op && op, P0 && p0, P1 && p1)
{
    return Expr<Op, P0, P1> { op, { p0, p1 } };
}

template <class T>
struct cell
{
    T * p = nullptr;

    template <class X> decltype(auto) operator =(X && x)
    {
        expr([](auto && y, auto && x)
                 {
                     y = x;
                 },
            *this, x);
    }
};

int main()
{
  cell<int> n;
  cell<int const> c;
  n = c;
}


I think GCC is correct to reject this, other compilers agree.

Overload resolution for 'n = c' considers cell<int>::operator=(X&&) as well as
cell's implicit assignment ops, but it _also_ considers cell<int
const>::operator=(X&&) due to ADL.

Because that overload has a decltype(auto) return type it has to instantiate
the body, which instantiates Expr<lambda, cell<int const>, cell<int const>>
which triggers the error in the std::tuple::operator= outside the immediate
context.

Reply via email to