6

The code shows my problem, I can't use take(3) after istream_view.

The error message is:

/home/linuxbrew/.linuxbrew/Cellar/gcc/11.1.0_1/include/c++/11.1.0/ranges:1775:48: error: passing 'std::ranges::take_view<std::ranges::transform_view<std::ranges::basic_istream_view<int, char, std::char_traits >, int ()(int)> >::_CI' {aka 'const std::counted_iterator<std::ranges::transform_view<std::ranges::basic_istream_view<int, char, std::char_traits >, int ()(int)>::_Iterator >'} as 'this' argument discards qualifiers [-fpermissive] 1775 | { return __y.count() == 0 || __y.base() == __x._M_end; }

#include <ranges>

using namespace std::views;
using namespace std::ranges;
int to_sq(int a){return a*a;}
int main()
{

    auto m_range = istream_view<int>(std::cin);
    // error
    for (auto i : m_range | transform(to_sq)|take(3))
    {
        std::cout << i << std::endl;
    }
}
cpplearner
  • 13,776
  • 2
  • 47
  • 72
Jiangqiu Shen
  • 81
  • 1
  • 4
  • 2
    Looks like a gcc bug that has been [fixed in trunk](https://godbolt.org/z/6qx19fdvc). Also, as mentioned above, please include a definition of `to_sq`. – cigien Jul 07 '21 at 21:50

1 Answers1

8

This is LWG 3391.

The transform here is irrelevant, just trying to iterate over istream_view<int>(std::cin) | views::take(3) is already a problem. From the issue:

The code is invalid because ranges::take_view::sentinel::operator==() must call counted_iterator::base() to compare the underlying iterator against its sentinel, and therefore this operator==() requires that the underlying iterator is copy_constructible.

gcc 11.1 doesn't incorporate this fix yet (specifically this commit which came out just a few weeks after 11.1 was released), but gcc trunk now does.

Barry
  • 286,269
  • 29
  • 621
  • 977