为什么范围库为每个视图定义两个名称?

问题描述 投票:0回答:2

在 c++20 的范围库中,所有视图都有第二个版本。

例如,std::ranges::views::filter

根据cppreference:

表达式views::filter(E, P) 的表达式等价于 filter_view{E, P} 对于任何合适的子表达式 E 和 P。

我们有实际的类,

std::ranges::filter_view
,然后放入我们拥有的视图命名空间中
std::ranges::views::filter
。两者之间有什么区别,还是纯粹是风格问题?

c++ range c++20
2个回答
10
投票

所有视图都有第二个版本

不,他们没有。

filter_view
是一种类型。
filter
是一个 函子。通过调用
filter
函子,您可以创建相应
filter_view
类型(或接近足够类型)的对象。

但是您也可以仅使用一个参数来调用

filter
函子:过滤谓词。此类调用的返回值是一个对象,您可以
|
针对范围来 also 创建一个
filter_view
等效项,如您链接到的页面上所述:

ints | std::views::filter(even)

您不能直接使用

filter_view
来做到这一点。

因此,您可以使用常见的 C++ 表示法创建过滤视图:

filter_view(range, predicate)
,也可以使用更实用的样式谓词表示法:
range | views::filter(predicate)


0
投票

补充 Nicol Bolas 的答案:Barry Revzin 的博客文章“更喜欢

views::meow
(2023-03-14)对此进行了很好的介绍。

Nicol 指出你可以说

std::views::filter(isEven)
,但不能说
std::ranges::filter_view(isEven)
。那些不考虑语法的视图呢?仍然有理由更喜欢,例如
std::views::all(rg)
超过
std::ranges::ref_view(rg)
?是的,因为
std::views::all(rg)
并不总是创建
ref_view
如果
rg
已经是一个视图(例如
filter_view
),那么
views::all(rg)
将只是 be(的副本)
 rg
,而不是成为
ref_view
包裹(参考)
rg

template<std::ranges::range R>
auto very_bad(R&& rg) {
    return std::ranges::ref_view(rg);
}
template<std::ranges::range R>
auto still_not_great(R&& rg) {
    return std::views::all(rg);
}
auto goofus = very_bad(std::views::iota(1, 10));
auto gallant = still_not_great(std::views::iota(1, 10));

这里

gallant
是一个
std::ranges::iota_view<int, int>
,(在本例中)非常漂亮。但
goofus
是一个悬空的
std::ranges::ref_view<std::ranges::iota_view<int, int>>
,这是UB的使用方式。 (当然,这是一个人为的情况;实际上,您永远不应该从 any 函数返回 Ranges 视图。也就是说,
still_not_great
...仍然不是很好。但是您可以看到 UB 的潜力是如何相关的所涉及类型的复杂性使用
views::all
可以使复杂性低于替代方案。)


Barry 还展示了

views::reverse
reverse_view
的示例:

std::vector<int> v = {1,2,3};
auto rv = v | std::views::reverse;

auto goofus = std::ranges::reverse_view(rv);
auto gallant = std::views::reverse(rv);

这里

rv
v
颠倒过来的:它的元素序列为 {3,2,1}。

那么

gallant
rv
的逆过程:它的元素又是 {1,2,3}。

但是

goofus
实际上正在使用CTAD这是邪恶的),所以
goofus
只是
rv
的直接副本。
goofus
的元素仍保持 {3,2,1} 的顺序。这几乎肯定不是您想要的!


TLDR:总是更喜欢

views::meow
——这个好听的简称,Just Works。切勿手动实例化
ranges::meow_view
— 更麻烦的名称,有时会出错。

© www.soinside.com 2019 - 2024. All rights reserved.