https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90745
Bug ID: 90745 Summary: [9/10 Regression] std::tuple::operator= parameter causes error outside immediate context Product: gcc Version: 10.0 Status: UNCONFIRMED Keywords: rejects-valid Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: redi at gcc dot gnu.org Target Milestone: --- This compiled with gcc 8, but fails with 9 and trunk: #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 Op, class P0, class P1> inline void for_each(Op && op, P0 && p0, P1 && p1) { expr(op, p0, p1); } template <class V> struct cell { typename V::value_type * p; cell(typename V::value_type * p_): p { p_ } {} template <class X> decltype(auto) operator =(X && x) { for_each([](auto && y, auto && x) { y = x; }, *this, x); } }; template <class T> struct view { T * p; using value_type = T; cell<view<T>> iter() { return p; } cell<view<T const>> iter() const { return p; } view(T * p_): p(p_) {} }; /* /opt/gcc-9.1/bin/g++ -o mem-fn.o -c -std=c++17 -Wall -Werror -ftemplate-backtrace-limit=0 mem-fn.C /opt/gcc-8.3/bin/g++ -o mem-fn.o -c -std=c++17 -Wall -Werror -ftemplate-backtrace-limit=0 mem-fn.C */ int main() { { int cdata[3] = {44, 44, 44}; int ndata[3] = {77, 77, 77}; view<int> const c {cdata}; // 8.3 - 9.1 case [const or not] view<int> n {ndata}; for_each([](auto && n, auto && c) { n = c; }, n.iter(), c.iter()); } } e.cc: In instantiation of 'cell<V>::operator=(X&&) [with X = cell<view<const int> >&; V = view<const int>]::<lambda(auto:1&&, auto:2&&)> [with auto:1 = const int&; auto:2 = const int&]': e.cc:10:11: required from 'struct Expr<cell<V>::operator=(X&&) [with X = cell<view<const int> >&; V = view<const int>]::<lambda(auto:1&&, auto:2&&)>&, cell<view<const int> >&, cell<view<const int> >&>' e.cc:17:46: required from 'auto expr(Op&&, P0&&, P1&&) [with Op = cell<V>::operator=(X&&) [with X = cell<view<const int> >&; V = view<const int>]::<lambda(auto:1&&, auto:2&&)>&; P0 = cell<view<const int> >&; P1 = cell<view<const int> >&]' e.cc:23:9: required from 'void for_each(Op&&, P0&&, P1&&) [with Op = cell<V>::operator=(X&&) [with X = cell<view<const int> >&; V = view<const int>]::<lambda(auto:1&&, auto:2&&)>; P0 = cell<view<const int> >&; P1 = cell<view<const int> >&]' e.cc:35:17: required from 'decltype(auto) cell<V>::operator=(X&&) [with X = cell<view<const int> >&; V = view<const int>]' /home/jwakely/gcc/9/include/c++/9.1.1/type_traits:1017:12: [ skipping 2 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ] /home/jwakely/gcc/9/include/c++/9.1.1/tuple:901:31: required from 'static constexpr bool std::tuple<_T1, _T2>::__assignable() [with _U1 = cell<view<int> >&; _U2 = cell<view<const int> >&; _T1 = cell<view<int> >&; _T2 = cell<view<const int> >&]' /home/jwakely/gcc/9/include/c++/9.1.1/tuple:1205:74: required from 'class std::tuple<cell<view<int> >&, cell<view<const int> >&>' e.cc:8:24: required from 'struct Expr<main()::<lambda(auto:3&&, auto:4&&)>&, cell<view<int> >&, cell<view<const int> >&>' e.cc:17:46: required from 'auto expr(Op&&, P0&&, P1&&) [with Op = main()::<lambda(auto:3&&, auto:4&&)>&; P0 = cell<view<int> >&; P1 = cell<view<const int> >&]' e.cc:23:9: required from 'void for_each(Op&&, P0&&, P1&&) [with Op = main()::<lambda(auto:3&&, auto:4&&)>; P0 = cell<view<int> >; P1 = cell<view<const int> >]' e.cc:65:73: required from here e.cc:37:24: error: assignment of read-only reference 'y' 37 | y = x; | ~~^~~ I think the problem is the assignment operator, which gets errors outside the immediate context. The problem almost certainly started with r263625