std::reverse_iterator 是否适用于调整后的范围?
Does std::reverse_iterator work with adapted ranges?
我记得读过 [forward.iterators]/6 的动机(要求,给定两个迭代器 a
和 b
,a == b
当且仅当 *a
和 *b
绑定到同一个对象)是为了支持 reverse_iterator
s。我没记错吧?
cppreference.com 注意到
For a reverse iterator r
constructed from an iterator i
, the relationship &*r == &*(i-1)
is always true
(as long as r
is dereferenceable); thus a reverse iterator constructed from a one-past-the-end iterator dereferences to the last element in a sequence.
还有:
std::reverse_iterator
does not work with iterators whose dereference returns a reference to a member of *this
(so-called "stashing iterators"). An example of a stashing iterator is std::filesystem::path::iterator
.
不过,也说明:
std::reverse_iterator
is an iterator adaptor that reverses the direction of a given iterator, which must be at least a LegacyBidirectionalIterator
or model bidirectional_iterator
(since C++20).
这正是标准 says。
如果我没记错的话,C++20 bidirectional_iterator
s 不再需要 [forward.iterators]/6。例如,std::ranges::iota_view::iterator
是一个 std::random_access_iterator
但也是一个存储迭代器。因此,如果上述关于隐藏迭代器的声明是正确的,我不明白为什么 std::bidirectional_iterator
是 std::reverse_iterator
工作的充分要求。
确实,以下程序显示了预期的输出:
#include <iostream>
#include <ranges>
int main()
{
auto v = std::views::iota(0u, 10'000ul) | std::views::take(10);
for (auto it = std::make_reverse_iterator(v.end());
it != std::make_reverse_iterator(v.begin()); ++it)
std::cout << *it << std::endl;
}
将 std::reverse_iterator
与 C++20 迭代器一起使用并没有多大意义,因为我们有 std::ranges::reverse_view
,但我很想知道 [forward.iterators] /6 目前是必需的。
关于隐藏迭代器的注释不是关于 *
中的左值与右值 return,而是关于多遍保证。
std::forward_iterator
仍然有语义要求“((void)[](auto x){ ++x; }(i), *i)
等同于 *i
”, 是 满足 decltype(v.begin())
, 但不(必须)符合 std::filesystem::path::
(const_
)iterator
.
const_iterator
a constant LegacyBidirectionalIterator with a value_type
of path, except that for dereferenceable iterators a
and b
of type path::iterator
with a == b
, there is no requirement that *a
and *b
are bound to the same object
N.b。 std::reverse_view
被(对于某些表达式)定义为 return a ranges::subrange<reverse_iterator<...>>
,所以它仍然是相关的。
我记得读过 [forward.iterators]/6 的动机(要求,给定两个迭代器 a
和 b
,a == b
当且仅当 *a
和 *b
绑定到同一个对象)是为了支持 reverse_iterator
s。我没记错吧?
cppreference.com 注意到
For a reverse iterator
r
constructed from an iteratori
, the relationship&*r == &*(i-1)
is alwaystrue
(as long asr
is dereferenceable); thus a reverse iterator constructed from a one-past-the-end iterator dereferences to the last element in a sequence.
还有:
std::reverse_iterator
does not work with iterators whose dereference returns a reference to a member of*this
(so-called "stashing iterators"). An example of a stashing iterator isstd::filesystem::path::iterator
.
不过,也说明:
std::reverse_iterator
is an iterator adaptor that reverses the direction of a given iterator, which must be at least aLegacyBidirectionalIterator
or modelbidirectional_iterator
(since C++20).
这正是标准 says。
如果我没记错的话,C++20 bidirectional_iterator
s 不再需要 [forward.iterators]/6。例如,std::ranges::iota_view::iterator
是一个 std::random_access_iterator
但也是一个存储迭代器。因此,如果上述关于隐藏迭代器的声明是正确的,我不明白为什么 std::bidirectional_iterator
是 std::reverse_iterator
工作的充分要求。
确实,以下程序显示了预期的输出:
#include <iostream>
#include <ranges>
int main()
{
auto v = std::views::iota(0u, 10'000ul) | std::views::take(10);
for (auto it = std::make_reverse_iterator(v.end());
it != std::make_reverse_iterator(v.begin()); ++it)
std::cout << *it << std::endl;
}
将 std::reverse_iterator
与 C++20 迭代器一起使用并没有多大意义,因为我们有 std::ranges::reverse_view
,但我很想知道 [forward.iterators] /6 目前是必需的。
关于隐藏迭代器的注释不是关于 *
中的左值与右值 return,而是关于多遍保证。
std::forward_iterator
仍然有语义要求“((void)[](auto x){ ++x; }(i), *i)
等同于 *i
”, 是 满足 decltype(v.begin())
, 但不(必须)符合 std::filesystem::path::
(const_
)iterator
.
const_iterator
a constant LegacyBidirectionalIterator with avalue_type
of path, except that for dereferenceable iteratorsa
andb
of typepath::iterator
witha == b
, there is no requirement that*a
and*b
are bound to the same object
N.b。 std::reverse_view
被(对于某些表达式)定义为 return a ranges::subrange<reverse_iterator<...>>
,所以它仍然是相关的。