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.