[英]std::distance for iterators worse then RandomAccessIterator
I recently reviewed not long ago implemented algorithm and found, that it can be improved to be able to operate on not just only RandomAccessIterator input range, but even on ForwardIterator one ( multipass guarantee is still the requirement). 我最近查看了不久前实现的算法 ,发现它可以改进为不仅可以在RandomAccessIterator输入范围上运行,甚至可以在ForwardIterator上运行(仍然需要多通道保证 )。
I decide to simply downgrade the requirement by modifying all the places in the code, that currently uses simple difference between iterators, in a way to use std::distance
instead. 我决定通过修改代码中的所有位置(目前使用迭代器之间使用简单的区别)来简单地降级需求,而改为使用
std::distance
。 The std::distance
algorithm described here . 这里描述的
std::distance
算法 。 Due to very nature of std::distance
algorithm the modifications was not just a search and replace one, namely: 由于
std::distance
算法的本质,修改不只是一种搜索和替换 ,即:
operator <
or std::less< iterator >
/ std::less<>
with: operator <
或std::less< iterator >
/ std::less<>
替换为: auto const less = [ibeg = std::cbegin(input)] (iterator const & l, iterator const & r)
{
return std::distance(ibeg, l) < std::distance(ibeg, r);
};
Say, std::set< iterator > x;
说,
std::set< iterator > x;
modified to be std::set< iterator, decltype(less) > x{less};
修改为
std::set< iterator, decltype(less) > x{less};
. 。
value_type
is iterator
) I use std::hash< std::intptr_t > h;
value_type
为iterator
),我使用std::hash< std::intptr_t > h;
hash function for simple difference h(lhs - rhs)
(actually xor combination of hash values, but it not matters here) for some fixed iterator lhs
and a number of varying iterator rhs
. iterator lhs
和许多可变iterator rhs
简单差分h(lhs - rhs)
(实际上是哈希值的异或组合,但在这里并不重要)的哈希iterator rhs
。 It modified to be h(std::distance(lhs, rhs))
. h(std::distance(lhs, rhs))
。 The former point is correct, but the latter is evidently no. 前一点是正确的,但后者显然不是。 Due to
rhs
can be unrecheable from lhs
just only by means of simple incrementation and there is no way to know what to do a priori: to increment lhs
to reach rhs
or to increment rhs
to reach lhs
. 由于
rhs
只能通过简单的递增而无法从lhs
,因此无法知道先验如何做:递增lhs
达到rhs
或递增rhs
达到lhs
。
But above hash still works. 但以上哈希仍然有效。 It is strange... because sometimes, when
lhs > rhs
(in some sense), there should be access violation (sometimes). 这很奇怪……因为有时候,当
lhs > rhs
(在某种意义上)时,应该出现访问冲突(有时)。 Say, if: 说,如果:
std::list< int > input{1, 2, 3, 4};
auto a = std::begin(input), b = std::next(lhs, 2);
then increments, contained into std::distance(b, a)
, should never stop and eventually reaches boundary of not yet allocated memory page. 然后,包含在
std::distance(b, a)
增量将永远不会停止,并最终到达尚未分配的内存页的边界。 But AV never happens in my program. 但是AV永远不会在我的程序中发生。
std::distance
always return non-negative number. std::distance
始终返回非负数。
Is it undefined behaviour or is it permittable to apply std::distance
for any pair of ForwardIterator-s? 它是未定义的行为,还是允许对任何ForwardIterator-s应用
std::distance
? The -stdlib=
is libc++
. -stdlib=
是libc++
。
[...] is it permittable to apply
std::distance
for any pair ofForwardIterator
-s?[...]是否可以对任何
ForwardIterator
-s对应用std::distance
?
If you want to stick to the standard, then clearly no, it's not permitted : 如果您要遵守标准,那么显然不可以,这是不允许的 :
template <class InputIterator> typename iterator_traits<InputIterator>::difference_type distance( InputIterator first, InputIterator last);
[...] Requires: If
InputIterator
meets the requirements of random access iterator,last
shall be reachable fromfirst
orfirst
shall be reachable fromlast
;[...]要求:如果
InputIterator
满足随机访问迭代器的要求,则last
应该是从first
first
可访问的,或者first
应该是从last
可以访问的; otherwise,last
shall be reachable fromfirst
.否则,
last
应该从first
到达 。[N4431 §24.4.4/5]
[N4431§24.4.4/ 5]
The reason is that for forward iterators the function is repeatedly applying operator++
to get from first
to last
: 原因是,对于前向迭代器的功能是重复应用
operator++
从获得first
到last
:
Since only random access iterators provide + and -operators, the library provides two function templates
advance
anddistance
.由于仅随机访问迭代器提供+和-运算符,因此该库提供了两个功能模板
advance
和distance
。 These function templates use+
and-
for random access iterators (and are, therefore, constant time for them);这些函数模板将
+
和-
用于随机访问迭代器(因此,它们的时间恒定)。 for input, forward and bidirectional iterators they use++
to provide linear time implementations.对于输入,正向和双向迭代器,它们使用
++
提供线性时间实现。[N4431 §24.4.4/1]
[N4431§24.4.4/ 1]
From the documentaton you linked "If InputIt
is not RandomAccessIterator
, the behavior is undefined if last
is not reachable from first
by (possibly repeatedly) incrementing first
". 在您链接的文档中,“如果
InputIt
不是RandomAccessIterator
,那么如果无法通过(可能重复地) first
递增而无法从first
到达last
行为,则该行为是不确定的”。
Undefined behaviour does not mean an access violation; 未定义的行为并不意味着访问冲突。 it means anything at all, including returning some positive number.
它意味着一切,包括返回一些正数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.