Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

ranges views size does not compile

#include <iostream>
#include <cstdlib>
#include <vector>
#include <ranges>
#include <algorithm>
using namespace std;


int main()
{
    vector<int> ints = {1,2,3,4,5};
    auto v = ints | views::take_while([](int i){return i<3;}) ;
    for (int i : v) std::cout << i << ' ';
    std::cout << '\n';
    int size = v.size();
    std::cout << size << std::endl;
}

v.size() does not compile. How do you do this ?

prog.cc: In function 'int main()':
prog.cc:16:23: error: no matching function for call to 'std::ranges::take_while_view<std::ranges::ref_view<std::vector<int> >, main()::<lambda(int)> >::size()'
   16 |     int size = v.size();
      |                       ^
In file included from prog.cc:5:
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/ranges:144:7: note: candidate: 'constexpr auto std::ranges::view_interface<_Derived>::size() requires (forward_range<_Derived>) && (sized_sentinel_for<decltype(std::ranges::__cust::end((declval<_Tp&>)())), decltype(std::__detail::__ranges_begin((declval<_Container&>)()))>) [with _Derived = std::ranges::take_while_view<std::ranges::ref_view<std::vector<int> >, main()::<lambda(int)> >]'
  144 |       size()
      |       ^~~~
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/ranges:144:7: note: constraints not satisfied
In file included from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/stl_iterator_base_types.h:71,
                 from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/stl_algobase.h:65,
                 from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/char_traits.h:39,
                 from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/ios:40,
                 from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/ostream:38,
                 from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/iostream:39,
                 from prog.cc:2:
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h: In instantiation of 'constexpr auto std::ranges::view_interface<_Derived>::size() requires (forward_range<_Derived>) && (sized_sentinel_for<decltype(std::ranges::__cust::end((declval<_Tp&>)())), decltype(std::__detail::__ranges_begin((declval<_Container&>)()))>) [with _Derived = std::ranges::take_while_view<std::ranges::ref_view<std::vector<int> >, main()::<lambda(int)> >]':
prog.cc:16:23:   required from here
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h:555:13:   required for the satisfaction of 'sized_sentinel_for<std::ranges::sentinel_t<_Tp>, decltype (std::__detail::__ranges_begin(declval<_Container&>()))>' [with _Tp = std::ranges::take_while_view<std::ranges::ref_view<std::vector<int, std::allocator<int> > >, main::._anon_124>; _Container = std::ranges::take_while_view<std::ranges::ref_view<std::vector<int, std::allocator<int> > >, main::._anon_124>]
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h:557:8:   in requirements with 'const _Iter& __i', 'const _Sent& __s' [with _Arg = __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >; _Sent = std::ranges::take_while_view<std::ranges::ref_view<std::vector<int, std::allocator<int> > >, main::._anon_124>::_Sentinel<true>; _Iter = __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >]
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h:559:13: note: the required expression '(__s - __i)' is invalid
  559 |       { __s - __i } -> same_as<iter_difference_t<_Iter>>;
      |         ~~~~^~~~~
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h:560:13: note: the required expression '(__i - __s)' is invalid
  560 |       { __i - __s } -> same_as<iter_difference_t<_Iter>>;
      |         ~~~~^~~~~
cc1plus: note: set '-fconcepts-diagnostics-depth=' to at least 2 for more detail
In file included from prog.cc:5:
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/ranges:150:7: note: candidate: 'constexpr auto std::ranges::view_interface<_Derived>::size() const requires (forward_range<const _Derived>) && (sized_sentinel_for<decltype(std::ranges::__cust::end((declval<const _Range&>)())), decltype(std::__detail::__ranges_begin((declval<const _Range&>)()))>) [with _Derived = std::ranges::take_while_view<std::ranges::ref_view<std::vector<int> >, main()::<lambda(int)> >]'
  150 |       size() const
      |       ^~~~
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/ranges:150:7: note: constraints not satisfied
In file included from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/stl_iterator_base_types.h:71,
                 from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/stl_algobase.h:65,
                 from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/char_traits.h:39,
                 from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/ios:40,
                 from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/ostream:38,
                 from /opt/wandbox/gcc-10.2.0/include/c++/10.2.0/iostream:39,
                 from prog.cc:2:
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h: In instantiation of 'constexpr auto std::ranges::view_interface<_Derived>::size() const requires (forward_range<const _Derived>) && (sized_sentinel_for<decltype(std::ranges::__cust::end((declval<const _Range&>)())), decltype(std::__detail::__ranges_begin((declval<const _Range&>)()))>) [with _Derived = std::ranges::take_while_view<std::ranges::ref_view<std::vector<int> >, main()::<lambda(int)> >]':
prog.cc:16:23:   required from here
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h:555:13:   required for the satisfaction of 'sized_sentinel_for<std::ranges::sentinel_t<const _Range>, decltype (std::__detail::__ranges_begin(declval<const _Range&>()))>' [with _Range = std::ranges::take_while_view<std::ranges::ref_view<std::vector<int, std::allocator<int> > >, main::._anon_124>]
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h:557:8:   in requirements with 'const _Iter& __i', 'const _Sent& __s' [with _Arg = __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >; _Sent = std::ranges::take_while_view<std::ranges::ref_view<std::vector<int, std::allocator<int> > >, main::._anon_124>::_Sentinel<true>; _Iter = __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >]
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h:559:13: note: the required expression '(__s - __i)' is invalid
  559 |       { __s - __i } -> same_as<iter_difference_t<_Iter>>;
      |         ~~~~^~~~~
/opt/wandbox/gcc-10.2.0/include/c++/10.2.0/bits/iterator_concepts.h:560:13: note: the required expression '(__i - __s)' is invalid
  560 |       { __i - __s } -> same_as<iter_difference_t<_Iter>>;
      |         ~~~~^~~~~

>Solution :

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Since take_while and its ilk shorten the size of the list in unpredictable ways, those range adaptors cannot return a sized_range, even if the input itself is sized. sized_range requires that the range can compute the size in O(1) time, and take_while‘s view cannot do that.

So if you want the size (and you shouldn’t), you will have to compute it yourself. You could also use std::ranges::distance on the range.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading