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

Reply via email to