gpt4 book ai didi

C++20 范围太多 |运营商?

转载 作者:行者123 更新时间:2023-12-04 10:26:57 27 4
gpt4 key购买 nike

我正在为此代码使用 g++ 10.2。有谁知道为什么我在最后一次 std::views::reverse 中收到编译器错误?在 results3 ?

#include <vector>
#include <ranges>

int main() {
auto values = std::vector{1,2,3,4,5,6,7,8,9,10};
auto even = [](const auto value) {
return value % 2 == 0;
};
auto square = [](const auto value) {
return value * value;
};

auto results1 = values
| std::views::filter(even)
| std::views::reverse
| std::views::take(4)
| std::views::reverse;

auto results2 = values
| std::views::transform(square)
| std::views::reverse
| std::views::take(4)
| std::views::reverse;

auto results3 = values
| std::views::filter(even)
| std::views::transform(square)
| std::views::reverse
| std::views::take(4)
| std::views::reverse; // Error happens on this line.
}
错误片段:
...
<source>: In function 'int main()':
<source>:30:9: error: no match for 'operator|' (operand types are 'std::ranges::take_view<std::ranges::reverse_view<std::ranges::transform_view<std::ranges::filter_view<std::ranges::ref_view<std::vector<int, std::allocator<int> > >, main()::<lambda(auto:13)> >, main()::<lambda(auto:14)> > > >' and 'const std::ranges::views::__adaptor::_RangeAdaptorClosure<std::ranges::views::<lambda(_Range&&)> >')
25 | auto results3 = values
| ~~~~~~
26 | | std::views::filter(even)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
27 | | std::views::transform(square)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
28 | | std::views::reverse
| ~~~~~~~~~~~~~~~~~~~~~
29 | | std::views::take(4)
| ~~~~~~~~~~~~~~~~~~~~~
| |
| std::ranges::take_view<std::ranges::reverse_view<std::ranges::transform_view<std::ranges::filter_view<std::ranges::ref_view<std::vector<int, std::allocator<int> > >, main()::<lambda(auto:13)> >, main()::<lambda(auto:14)> > > >
30 | | std::views::reverse;
| ^ ~~~~~~~~~~~~~~~~~~~
| |
| const std::ranges::views::__adaptor::_RangeAdaptorClosure<std::ranges::views::<lambda(_Range&&)> >
...
完整的错误集可以在这里看到: https://godbolt.org/z/Y7Gjqd

最佳答案

TL;DR:在这种情况下,std::views::take 的结果的迭代器类型是 std::counted_iterator ,它有时无法在预期不会失败的情况下对迭代器概念进行建模。这是 LWG 3408并由 P2259 解决.

这涉及一些非常复杂的机制。

  • Tvalues | std::views::filter(even) | std::views::transform(square) 的迭代器类型,
  • Rstd::reverse_iterator<T> .

  • result3 的初始化器中:
  • ... | take(4)的迭代器类型是 std::counted_iterator<R> .
  • iterator_traitsstd::counted_iterator<R>匹配偏特化 std::iterator_traits<std::counted_iterator<I>> .
  • 所述部分特化源自 std::iterator_traits<I> .
  • std::iterator_traits<R>从主模板生成:它提供了一个名为 iterator_category 的成员,但不是名为 iterator_concept 的成员.
  • iterator_categoryRT相同.
  • iterator_categoryTinput_iterator_tag ,因为它的解引用运算符不返回引用,这是 C++17 ForwardIterator 要求所不允许的。 (iterator_conceptTbidirectional_iterator_tag 。)

  • 所以最后, std::iterator_traits<std::counted_iterator<R>>不提供 iterator_concept ,及其 iterator_categoryinput_iterator_tag .
    因此, ... | take(4) 的结果无法建模 bidirectional_range ,因此被 views::reverse 拒绝.
    (当 ... | take(4) 从管道中移除时, counted_iterator 的迭代器类型不是 filter;当 iterator_category 从管道中移除时, input_iterator_tag 不是 transform。所以 |1046|1045| | 不要触发此错误。)
    这基本上是 LWG 3408 .

    关于C++20 范围太多 |运营商?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66130679/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com