473,770 Members | 1,901 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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 ForwardIterator s. Either way, the wording
for 24.3.4.4 is insufficient.

--
Alan Johnson

Nov 30 '06 #1
10 4737
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 ForwardIterator s. 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 ForwardIterator s. 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 ForwardIterator s 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_ty pe

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 ForwardIterator s. 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_i ter&, 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_ty pe
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_it erator<charbegi n(std::cin) ;
std::istream_it erator<charend ;
std::ostream_it erator<charout( std::cout, "") ;

std::cout << "Distance: " << std::distance(b egin, 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_ty pe

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_it erator<charbegi n(std::cin) ;
std::istream_it erator<charend ;
std::ostream_it erator<charout( std::cout, "") ;

std::cout << "Distance: " << std::distance(b egin, 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

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

Similar topics

12
1816
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 standard says that empty() has constant complexity. If it actually called the destructor for each object, it seems to me it would have linear complexity. Does empty() call the destructor for each object in the container? If yes, why is it described...
7
2639
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 position of the value within the container. std::string - for instance - does. How then do I get the actual position of the value when using std::set? # include <iostream> using std::cout; using std::cin;
2
4734
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> #include <iterator> int main() {
6
11510
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 example string str1; as a class member and then add text to it. or do I have to specify it's length when defining? 2. How to convert from std::string to LPCSTR
19
7552
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 in O(log K) time. Anyone knows if there is a way to do this in map<> or if map<> can be inherited/modified to do this? Thanks, --j
6
3238
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 std::search_n alot to find a particular value in a range of memory. I'm fairly pleased with std::search_n - in that my benchmark ( below ) shows on average an 8 second performance gain comparable to a for loop. The question. Since I haven't quite...
9
2324
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 list. For instance, if I did something like distance(list.end(), list.begin()), I would get -list.size(). The STL's iterator distance function amounts to something like this: distance_type distance(Iterator first, Iterator last) {...
7
5770
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 help, thank you. I am a freshman about the STL. The following is the code. #include <set> #include <iostream> #include <vector> int main() {
0
1694
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 understand quite well why this happens, and for witch documents this affirmation is valid, but the problem exists, probably,
0
9454
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 effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10259
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, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
10038
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9906
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 protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
6710
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5354
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5482
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
3609
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2849
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.