C++20范围和排序

14

我正在处理C++ 20的最后四个主要特性,尝试学习新的主要功能。我从网上找到与范围相关的一些代码,写成了:

std::vector ints{ 6, 5, 2, 8 };
auto even = [](int i) {
    return 0 == i % 2;
};

// ranges...
auto rr = ints | std::views::filter(even) 
               | std::views::transform([](auto i) {
                   return i * i;
                 })
               | std::views::reverse;

那么我会进行排序,就像range-v3使用的|action::sort一样,但我已经理解这个实现不同。

我发现的排序方式是:

ints = std::vector(std::ranges::begin(rr), std::ranges::end(rr));
std::ranges::sort(ints);

我错了吗?有人知道如何使用管道样式对视图进行排序吗?


9
@BitTickler,我认为选择使用|是因为它类比于Unix管道,对于习惯这个环境的人来说非常自然。无论如何,你所说的按位与运算的短路是什么意思? - cigien
1
@BitTickler | 语法来自于 boost::range,大约是在2010年左右被引入的。 - Caleth
1
@BitTickler & 没有短路语义。 - Barry
好吧——我承认&|一样糟糕。但是,那些声称某些操作系统的命令行shell使用类似符号的论点是一个弱论点,在我看来,因为C++程序员来自不同领域。而且,无论是现在还是明年后年,总会有一些使用“|”作为注释的编程语言或环境... 但对于C/C++人员来说,&|已经具有固定的含义。此外,我认为这个特性应该由编译器支持(循环折叠),因此它可以拥有自己的新语法。 - BitTickler
@BitTickler 很难想象有人使用像C++这样的低级语言却从未使用过基于Unix的操作系统,或者不知道什么是管道。我猜95%的程序员都自动熟悉了这种语法。 - user904963
显示剩余4条评论
1个回答

13

然后我会排序,就像range-v3使用|action::sort一样......

不,你实际上不能像这样对rr进行排序:

rr |= ranges::actions::sort; // error

因为rr是一个view。虽然view可以提供对基础范围的可变访问,但sort还需要该范围支持随机访问。像rr这样的惰性生成的view不允许这样做。

您可以像所做的那样从rr创建一个vector,然后您可以在该范围上使用actions

ints |= ranges::actions::sort;  // ok

c++20目前没有任何actions(希望在c++23中能得到),所以在那之前,您必须不使用管道语法调用算法sort

std::ranges::sort(ints);  // ok

视图可以被修改。 - Barry
@Barry 哦,怎么了?我以为 view 就像 span 一样,它不拥有底层范围,但与 span 不同的是,view 也不允许修改范围。 - cigien
@Barry 好的,那很有道理。我重新措辞了答案,这样可以吗? - cigien
1
没错,这里的问题与视图无关。您可以对“视图”进行“排序” - 只是“排序”需要随机访问,并且在“过滤器”中会丢失(而且您也不能对prvalues范围进行“排序”)。 - Barry
2
反转随机访问迭代器仍然会给你一个随机访问迭代器,这一部分没问题。transform会给你一个prvalue,这使得事情变得不可排序,但如果它给出一个lvalue,那就没问题了。例如:sort(iota(0u, v.size()) | transform([&v](int i) -> int& { return v[i]; }));是一种有效的,虽然荒谬的方法来做sort(v); - Barry
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接