473,396 Members | 1,760 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

Does std::distance interate over its range?

24.1.1.3 says about InputIterators:
Algorithms on input iterators should never attempt to pass through the
same iterator twice. They should be single pass algorithms.

In 24.3.4.4 summarizes the effects of std::distance as:
Effects: Returns the number of increments or decrements needed to get
from first to last.

The wording of the latter seems somewhat ambiguous. Does it mean that
it actually performs the necessary increments or decrements, or that it
determines (by some unspecified means) the necessary number, and
returns it?

One of the following must then be true:
1) We assume that it does perform the necessary increments, in which
case std::distance is useless when writing algorithms for
InputIterators. If you determine the distance, you can no longer use
the range for which the distance was determined.
2) We assume that it determines the distance without performing the
increments. I can't prove it rigorously, but I suspect that this
really isn't possible to implement.

Unless my suspicion in #2 is incorrect, it seems that std::distance
should only be defined for ForwardIterators. Either way, the wording
for 24.3.4.4 is insufficient.

--
Alan Johnson

Nov 30 '06 #1
10 4698
JE
Alan Johnson wrote:
<snip>
2) We assume that it determines the distance without performing the
increments. I can't prove it rigorously, but I suspect that this
really isn't possible to implement.
For random access iterators, you don't need to iterate to calculate
distance.
- -
JE

Nov 30 '06 #2

JE wrote:
Alan Johnson wrote:
<snip>
2) We assume that it determines the distance without performing the
increments. I can't prove it rigorously, but I suspect that this
really isn't possible to implement.

For random access iterators, you don't need to iterate to calculate
distance.
True, but that doesn't prove the possibility of implementing
std::distance without performing increments. You can specialize it for
random access iterators, but you still have to handle input iterators
(without any refinements) in some manner.

--
Alan Johnson

Nov 30 '06 #3
Alan Johnson wrote:
24.1.1.3 says about InputIterators:
Algorithms on input iterators should never attempt to pass through the
same iterator twice. They should be single pass algorithms.

In 24.3.4.4 summarizes the effects of std::distance as:
Effects: Returns the number of increments or decrements needed to get
from first to last.

The wording of the latter seems somewhat ambiguous. Does it mean that
it actually performs the necessary increments or decrements, or that it
determines (by some unspecified means) the necessary number, and
returns it?

One of the following must then be true:
1) We assume that it does perform the necessary increments, in which
case std::distance is useless when writing algorithms for
InputIterators. If you determine the distance, you can no longer use
the range for which the distance was determined.
2) We assume that it determines the distance without performing the
increments. I can't prove it rigorously, but I suspect that this
really isn't possible to implement.

Unless my suspicion in #2 is incorrect, it seems that std::distance
should only be defined for ForwardIterators. Either way, the wording
for 24.3.4.4 is insufficient.
I believe that #1 is correct. However, that doesn't mean that
std::distance should only be defined for ForwardIterators. It may well
be the case that all one needs from an InputIterator range is the
distance between the two iterators, and std::distance can do that. If
you need the size of the range before you start doing something with the
elements, then you probably will have ForwardIterators anyway.

Nate
Nov 30 '06 #4

Alan Johnson wrote:
24.1.1.3 says about InputIterators:
Algorithms on input iterators should never attempt to pass through the
same iterator twice. They should be single pass algorithms.
Input iterators have read only access to the elements.
The best analogy i've found so far to explain forward iterators is a
keyboard's input (standard input).
It can only be read once an element at a time.
>
In 24.3.4.4 summarizes the effects of std::distance as:
So Effects: Returns the number of increments or decrements needed to
get
from first to last.

The wording of the latter seems somewhat ambiguous. Does it mean that
it actually performs the necessary increments or decrements, or that it
determines (by some unspecified means) the necessary number, and
returns it?
The distance() function uses iter2 - iter1 to calculate distance for
*random* iterators. For non-random iterators, iter1 is incremented
until iter2 is reached and that count or Dist is returned based on an
iterator trait:
iterator_traits<InputIterator>::difference_type

So its saying that for distance(iter1, iter2)...
a) iter1 and iter2 must be from the same container (obviously).
b) If the iterators are *not* random iterators, iter2 must be reachable
from iter1 (think: direction). If iter2 is found before iter1 and the
iterators are input iterators, for example, the behaviour is undefined.
>
One of the following must then be true:
1) We assume that it does perform the necessary increments, in which
case std::distance is useless when writing algorithms for
InputIterators. If you determine the distance, you can no longer use
the range for which the distance was determined.
2) We assume that it determines the distance without performing the
increments. I can't prove it rigorously, but I suspect that this
really isn't possible to implement.

Unless my suspicion in #2 is incorrect, it seems that std::distance
should only be defined for ForwardIterators. Either way, the wording
for 24.3.4.4 is insufficient.
You can still use the distance returned from input iterators, although
distance() is slower on such containers. Its just telling you that the
way you calculate that distance has to be respected.
Consider using advance(input_iter&, dist) if you need to increment the
position of an input iterator.

I hope this is helpfull in some way.

Nov 30 '06 #5
Salt_Peter wrote:
The wording of the latter seems somewhat ambiguous. Does it mean that
it actually performs the necessary increments or decrements, or that it
determines (by some unspecified means) the necessary number, and
returns it?

The distance() function uses iter2 - iter1 to calculate distance for
*random* iterators. For non-random iterators, iter1 is incremented
until iter2 is reached and that count or Dist is returned based on an
iterator trait:
iterator_traits<InputIterator>::difference_type
I agree that this might be a possible implementation, depending on how
you interpret the standard, but I don't see where the standard requires
this implementation. In fact, that was sort of my point. One possible
interpretation is that this would NOT be a valid implementation.

Consider the following program:

#include <iostream>
#include <iterator>
#include <algorithm>

int main()
{
std::istream_iterator<charbegin(std::cin) ;
std::istream_iterator<charend ;
std::ostream_iterator<charout(std::cout, "") ;

std::cout << "Distance: " << std::distance(begin, end) << std::endl
;
std::copy(begin, end, out) ;
std::cout << std::endl ;
}
What should it print when executed with the input "Hello, world!\n"?

Under one interpretation it should print:
Distance: 12
Hello,world!

Under another it is undefined behavior, because you are using a range
of input iterators more than once, which is forbidden by 24.1.1.3.

Probably it is impossible to implement std::distance such that the
first interpretation is possible, and the second indicates to me that
std::distance should not even be defined for anything less than a
forward iterator.

--
Alan Johnson

Nov 30 '06 #6
JE
<snip>
Alan Johnson wrote:
True, but that doesn't prove the possibility of implementing
std::distance without performing increments. You can specialize it for
random access iterators, but you still have to handle input iterators
(without any refinements) in some manner.
If you look at the input iterator concept, it is possible to write a
distance algorithm in terms of a subset of the operations available in
that concept (increment, comparison, and copy). Anything that models
the concept of an input iterator provides enough of an interface to
write a distance algorithm. That doesn't say that it's efficient or
makes sense for everything that models an input iterator, but that the
_necessary operations_ are there for the distance algorithm.
--
JE

Nov 30 '06 #7
JE

Alan Johnson wrote:
Salt_Peter wrote:
The wording of the latter seems somewhat ambiguous. Does it mean that
it actually performs the necessary increments or decrements, or that it
determines (by some unspecified means) the necessary number, and
returns it?
The distance() function uses iter2 - iter1 to calculate distance for
*random* iterators. For non-random iterators, iter1 is incremented
until iter2 is reached and that count or Dist is returned based on an
iterator trait:
iterator_traits<InputIterator>::difference_type

I agree that this might be a possible implementation, depending on how
you interpret the standard, but I don't see where the standard requires
this implementation. In fact, that was sort of my point. One possible
interpretation is that this would NOT be a valid implementation.

Consider the following program:

#include <iostream>
#include <iterator>
#include <algorithm>

int main()
{
std::istream_iterator<charbegin(std::cin) ;
std::istream_iterator<charend ;
std::ostream_iterator<charout(std::cout, "") ;

std::cout << "Distance: " << std::distance(begin, end) << std::endl
;
std::copy(begin, end, out) ;
std::cout << std::endl ;
}
What should it print when executed with the input "Hello, world!\n"?

Under one interpretation it should print:
Distance: 12
Hello,world!

Under another it is undefined behavior, because you are using a range
of input iterators more than once, which is forbidden by 24.1.1.3.

Probably it is impossible to implement std::distance such that the
first interpretation is possible, and the second indicates to me that
std::distance should not even be defined for anything less than a
forward iterator.
You're confusing the restrictions imposed by the requirements of the
input iterator concept on the algorithm (distance, or your code) with
restrictions on types that model input iterator. You can only read an
input iterator _once_, and only traverse _once_. Your code traverses
_twice_, and requires more than just an input iterator. distance
algorithm only traverses _once_, and doesn't do any reading or
dereferencing at all.
--
JE

Nov 30 '06 #8
JE wrote:
You're confusing the restrictions imposed by the requirements of the
input iterator concept on the algorithm (distance, or your code) with
restrictions on types that model input iterator.
I don't think I've mentioned anything about restrictions on types. The
code sample I gave was mere an example, chosen because the type was an
input iterator (rather than a refinement thereof).
You can only read an input iterator _once_, and only traverse _once_.
We agree here. "Algorithms on input iterators should never attempt to
pass through the
same iterator twice. They should be single pass algorithms." I quoted
that from the standard in my original post.

I've reordered some of the rest of your statements so that I can
address them more clearly.
distance algorithm only traverses _once_, and doesn't do any reading or
dereferencing at all.
Show me where in the standard the implementation is required to
traverse the range. This is in fact the whole point of this thread.
I'm arguing that the standard is too ambiguous about that.

You probably assume that std::distance must traverse the given range
because you can't think of any other way to implement it. And neither
can I, but unless you can rigorously prove that there isn't another way
(and probably even if you can) then the standard should be more clear.

In my reading of the standard, the effects of std::distance are not
very well defined for (strict) input iterators.
Your code traverses _twice_, and requires more than just an input iterator.
This depends on whether you interpret the effects of std::distance as
traversing the range. I would argue that in the most literal reading
of the standard, my code only traverses the given range once.

--
Alan Johnson

Nov 30 '06 #9

Nate Barney wrote:
I believe that #1 is correct.
That is also my guess.

Dec 1 '06 #10
JE

Alan Johnson wrote:
JE wrote:
You're confusing the restrictions imposed by the requirements of the
input iterator concept on the algorithm (distance, or your code) with
restrictions on types that model input iterator.

I don't think I've mentioned anything about restrictions on types. The
code sample I gave was mere an example, chosen because the type was an
input iterator (rather than a refinement thereof).
You can only read an input iterator _once_, and only traverse _once_.

We agree here. "Algorithms on input iterators should never attempt to
pass through the
same iterator twice. They should be single pass algorithms." I quoted
that from the standard in my original post.

I've reordered some of the rest of your statements so that I can
address them more clearly.
distance algorithm only traverses _once_, and doesn't do any reading or
dereferencing at all.

Show me where in the standard the implementation is required to
traverse the range. This is in fact the whole point of this thread.
I'm arguing that the standard is too ambiguous about that.
You probably assume that std::distance must traverse the given range
because you can't think of any other way to implement it. And neither
can I, but unless you can rigorously prove that there isn't another way
(and probably even if you can) then the standard should be more clear.

In my reading of the standard, the effects of std::distance are not
very well defined for (strict) input iterators.
Your code traverses _twice_, and requires more than just an input iterator.

This depends on whether you interpret the effects of std::distance as
traversing the range. I would argue that in the most literal reading
of the standard, my code only traverses the given range once.
;) OK - I think I see where you're coming from.

If you use an algorithm for input iterators, there is no guarantee
that the algorithm has _not_ used iteration. Therefore, it behooves you
to pass in a refinement of input iterators that supports re-iteration,
if you intend to re-iterate.

--
Best regards, JE

Dec 1 '06 #11

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

12
by: Ross Boylan | last post by:
I am trying to understand under what circumstances destructors get called with std::vector. I have an application in which I will put real objects, not just pointers, in the vector. 1. The...
7
by: ma740988 | last post by:
The position returned via the STL std::set container never made much sense to me. When you insert elements within the container, the position returned - via find - does not reflect the actual...
2
by: tron.thomas | last post by:
I have tried the following code on three different compilers and all three produce programs that hang and fail to complete successfully. #include <map> #include <string> #include <iostream>...
6
by: Nemok | last post by:
Hi, I am new to STD so I have some questions about std::string because I want use it in one of my projects instead of CString. 1. Is memory set dinamicaly (like CString), can I define for...
19
by: John | last post by:
In STL's map implementation, the distance between two iterators it1, it2 takes O(K) to compute where K is the actual distance between the two iterators. In theory, a red black tree can do this...
6
by: ma740988 | last post by:
I've been perusing for some time now - I suppose some of the algorithms in Josuttis. 'Today', I do alot of funny math on data resident within memory. As part of this. I find myself using...
9
by: nottheartistinquestion | last post by:
As an intellectual exercise, I've implemented an STL-esque List<and List<>::Iterator. Now, I would like a signed distance between two iterators which corresponds to their relative position in the...
7
by: Renzr | last post by:
I have a problem about the std::set<>iterator. After finding a term in the std::set<>, i want to know the distance from the current term to the begin(). But i have got a error. Please offer me...
0
by: serhio | last post by:
Hello, I have a problem with Microsoft.Office.Interop.Excel.Range.Group() method. The problem is that I can call this method only 7 times, before it throws me an exception. I don't...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.