c++ - 范围 View 大小不编译

标签 c++ size c++20 std-ranges

#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() 无法编译。你是怎么做到的?

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>>;
      |         ~~~~^~~~~

最佳答案

由于 take_while 及其同类产品以不可预测的方式缩短了列表的大小,这些范围适配器无法返回 sized_range,即使输入本身已调整大小。 sized_range 要求范围可以在 O(1) 时间内计算大小,而 take_while 的 View 不能做到这一点。

因此,如果您想要大小(而您不应该),则必须自己计算。您还可以在范围上使用 std::ranges::distance

关于c++ - 范围 View 大小不编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71092690/

相关文章:

c++ - 不创建 getter 的不可变成员变量?

javascript - JS 生成的 SVG 不填充空间

powershell - 在 Powershell 中显示具有大小的目录结构

c++ - 当变量用于初始化列表时,为什么 C++ 不知道在返回值中进行隐式 move ?

c++ - 未指定的隐式对象创建

c++ - 声明一个静态私有(private)数组成员

c++ - 如何在不使用 MFC 的情况下将用户输入捕获为变量、执行计算,然后在另一个控件中显示结果?

c++ - 什么是 C++ 中可变参数函数的良好类型安全替代方案?

ios - 更改即将出现的键盘上的 UITableView 大小

C++20:[[likely]]、[[unlikely]] 和 __builtin_expect 之间的区别?