Topic: Singular iterators?


Author: "James Russell Kuyper Jr." <kuyper@wizard.net>
Date: Tue, 6 Aug 2002 02:23:15 GMT
Raw View
Randy Maddox wrote:
>
> The problem, in my mind, is that iterators are so close to being
> pointers that pointers are iterators, but iterators are not pointers.

That's not a problem, that's the design goal for the iterator
requirements. The whole purpose of the iterator requirements is to make
a iterator types a generalization of pointer types.

> This can lead to some difficulties when writing template code that
> takes an interator as a parameter.  Part of the problem arises from
> the difficulty of knowing whether or not an iterator is a class or a
> pointer.  This leads to the following:

If your code's written properly, you don't need to know.

> template <typename Iterator>
> void f(Iterator iter)
> {
>   Iterator    iter2;
>   Iterator    iter3(Iterator());
>
>   ...
> }
>
> Now, if Iterator is just a typedef for some pointer type, then iter2
> is uninitialized garbage, while iter3 is NULL.  If, on the other hand,
> Iterator is a class type, then iter2 and iter3 are both default
> constructed.

And since, for generic iterators, you know absolutely nothing about what
the default constructor does, there's absolutely nothing useful you can
do with either iter2 or iter3. In particular, the default constructor
might be a no-op, leaving iter2 incapable of even being safely compared
with iter3 for equality.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Carl Daniel" <cpdaniel@pacbell.net>
Date: Mon, 5 Aug 2002 04:27:31 GMT
Raw View
"Allan W" <Allan_W@my-dejanews.com> wrote in message
news:23b84d65.0208021357.78af1c1d@posting.google.com...
> rmaddox@isicns.com (Randy Maddox) wrote
> But then I think about how it's really going to be used. I want this
> code:
>     template<type T>foo(T iter) {
>         if (iter) { /* ... */ }
>     }
> to "work" whether T is a pointer or an iterator. So I'm back to
> agreeing with you that operator bool might be the best choice.

But then, this cannot be done, unless we change the language to require
initialization of all variables (a la Java) so that

int* p;

is guaranteed to produce the singular pointer (iterator) value 0 (or
whatever bit pattern actually compares equal to 0 on the particular
platform).

I suppose another alternative would be to require that iterators are NOT
pointers - somehow, I don't think that'd be a very popular change request...

-cd


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Daniel Pullwitt <pullwitt@informatik.uni-leipzig.de>
Date: Mon, 5 Aug 2002 10:00:55 CST
Raw View
John Potter wrote:

> On Sat,  3 Aug 2002 00:04:35 GMT, Daniel Pullwitt
> <pullwitt@informatik.uni-leipzig.de> wrote:
>
> > You should not rely on such assumptions in your program. There is a quite
> > simple
> > way to test it for the STL container iterators which also works for pointers:
>
> > template<typename I> bool is_singular(I const& it) { return I() == it; }
>
> Wrong.  Singular means has no defined value and the only operation
> allowed is assignment.  It is impossible to test for singular.  Your
> function has undefined behavior and may return anything given a
> singular iterator or format your hard drive.  Given a nul pointer it
> will return true and a nul pointer is not singular, it is nul.  See
> 24.1/5 for the meaning of singular as used in the C++ standard.
>
> John
>

I agree (... maybe except that part about my hard drive ...). I failed to distinct
between default constructed (0) and uninitialized pointers.


Daniel

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Andrew Koenig <ark@research.att.com>
Date: Mon, 5 Aug 2002 11:19:00 CST
Raw View
James> Andrew Koenig wrote:

>> Where do you find this definition?  In particular, remember that a
>> pointer is an iterator, and if you define

>> int* p;

>> then p has an undefined value.  That is, p is invalid, not singular.

James> If you examine the standard's definition of singular iterators,
James> you'll find that it exactly fits unitialized pointers, and does
James> NOT fit null pointers.

Sorry about that.  I was, of course, thinking about non-dereferencable
iterators, presumably because someone mentioned container.end() early
in the discussion in that context.

--
Andrew Koenig, ark@research.att.com, http://www.research.att.com/info/ark

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "James Russell Kuyper Jr." <kuyper@wizard.net>
Date: 5 Aug 2002 16:20:18 GMT
Raw View
Carl Daniel wrote:
....
> But then, this cannot be done, unless we change the language to require
> initialization of all variables (a la Java) so that
>
> int* p;
>
> is guaranteed to produce the singular pointer (iterator) value 0 (or
> whatever bit pattern actually compares equal to 0 on the particular
> platform).

(int*)0 is not a singular value. It's a null pointer, so it can be used
in equality comparisons, pointer conversions, and as the right-hand side
of an assignment statement, none of which would be legal for singular
values.

> I suppose another alternative would be to require that iterators are NOT
> pointers - somehow, I don't think that'd be a very popular change request...

It's exactly contrary to one of the key design goals for the iterator
requirements: that pointers must meet all of the requirements of a
random-access iterator.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: rmaddox@isicns.com (Randy Maddox)
Date: Mon, 5 Aug 2002 16:20:45 GMT
Raw View
The problem, in my mind, is that iterators are so close to being
pointers that pointers are iterators, but iterators are not pointers.
This can lead to some difficulties when writing template code that
takes an interator as a parameter.  Part of the problem arises from
the difficulty of knowing whether or not an iterator is a class or a
pointer.  This leads to the following:

template <typename Iterator>
void f(Iterator iter)
{
  Iterator    iter2;
  Iterator    iter3(Iterator());

  ...
}

Now, if Iterator is just a typedef for some pointer type, then iter2
is uninitialized garbage, while iter3 is NULL.  If, on the other hand,
Iterator is a class type, then iter2 and iter3 are both default
constructed.


Randy.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "James Russell Kuyper Jr." <kuyper@wizard.net>
Date: Mon, 5 Aug 2002 16:20:02 GMT
Raw View
Randy Maddox wrote:
....
> All that would be needed to provide this support would be to require
> each iterator type to provide an operator bool that returned true if
> the iterator is (possibly) valid, i.e., is associated with a position
> in a container, and false if the iterator is not valid, i.e., is not
> associated with a position in any container.

I don't think that's a good idea. Currently, conversion to bool of an
invalid iterator has undefined behavior; defining it as returning false
would be very inconvenient.

First of all, it would require adding operator bool() to the definition
of every iterator class. That's not just the iterators used by the
standard library containers; it would also apply to user-defined
iterators intended to be passt to the standard library algorithms that
require iterator arguments.
That would be a major breach of backwards compatibility, particularly
since the iterator arguments are frequently pointers (see below).  Also,
it would require that a default-constructed iterator have some method of
detecting the fact that it was default-constructed, which means that it
would have to have a non-trivial constructor, so iterators could never
be POD types.

In particular, iterators could never be ordinary pointers. One of the
key design goals for the iterator requirements, is to make sure that T*
meets all of the requirements of a random-access iterator. Under the
current rules, default construction of a pointer leaves it
uninitialized, which would make it expensive to determine whether or
not, by sheer chance, it points to a legitimate container. Also,
conversion of a pointer to bool performs a test of whether it compares
equal to 0. There's two options:

1. Abandon the idea that T* must qualify as an iterator.
This would render many standard library implementations non-conforming,
because many (most?) of them use T* as the iterator type for one or more
standard containers. It would also render incorrect a huge number of
programs that pass pointers to standard-library algorithms that are
specified as requiring iterator arguments.

2. Change the definition of how T* is converted to bool, so that it
performs a validity check, rather than a comparison with 0.
This would require that default construction of a pointer must set it's
value in some way that makes it testable for validity; the simplest
option would be to make default initialization the same as zero
initialization. Also, code which currently says if(pointer) would have
to be translated as performing a validity check on the pointer, rather
than simple null check. On many implementations, a validity check would
be several orders of magnitude more expensive than a null check.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: John Nagle <nagle@animats.com>
Date: Mon, 5 Aug 2002 17:15:51 GMT
Raw View
     Iterators are indeed not pointers.  Look at the STLport
implementation in debug mode, which enforces most iterator
semantics.  It's instructive to see that iterators can
be checked.  Iterator operations have explicit preconditions,
which are much tighter than those on pointers.

     I would have designed iterators to bind to a specific
array at creation.  It would have been nice to have syntax
like

   for (iterator p(tab.begin()), p != tab.end(); p++) {}

But that's not what we've got.

    John Nagle
    Animats

Randy Maddox wrote:

> The problem, in my mind, is that iterators are so close to being
> pointers that pointers are iterators, but iterators are not pointers.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Allan_W@my-dejanews.com (Allan W)
Date: Mon, 5 Aug 2002 23:47:29 GMT
Raw View
> "Allan W" <Allan_W@my-dejanews.com> wrote
> > But then I think about how it's really going to be used. I want this
> > code:
> >     template<type T>foo(T iter) {
> >         if (iter) { /* ... */ }
> >     }
> > to "work" whether T is a pointer or an iterator. So I'm back to
> > agreeing with you that operator bool might be the best choice.

"Carl Daniel" <cpdaniel@pacbell.net> wrote
> But then, this cannot be done, unless we change the language to require
> initialization of all variables (a la Java) so that
>
> int* p;
>
> is guaranteed to produce the singular pointer (iterator) value 0 (or
> whatever bit pattern actually compares equal to 0 on the particular
> platform).

Why not?

    int buff[10];
    foo(&buff[0]); // Calls int* version
    foo((int*)0);  // Likewise, but with null value

    std::vector<int> vec;
    foo(vec.begin()); // Calls vector::iterator version
    foo(vec.end());   // Likewise, but past-the-end

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Andrew Koenig <ark@research.att.com>
Date: Fri, 2 Aug 2002 15:49:56 GMT
Raw View
Randy> Iterators too can be singular.  For example:

Randy>   std::string::iterator    iter;

Randy> When initially created an iterator is not associated with any
Randy> container and is, by definition, singular.

Where do you find this definition?  In particular, remember that a
pointer is an iterator, and if you define

        int* p;

then p has an undefined value.  That is, p is invalid, not singular.

Randy> With pointers the singular value NULL allows the pointer to
Randy> convey whether or not it is (possibly) valid.  This adds a bit
Randy> of bandwidth to use of a pointer since it can convey not just a
Randy> location but also information about whether that location is
Randy> valid or not.

Correct.

Randy> With iterators, however, the singular value is useless because
Randy> we have no way to test for it.  We can only assume that an
Randy> iterator is valid and hope that assumption is correct.

The phrase ``the singular value'' conceals the implicit, and incorrect,
assumption that every iterator has a corresponding singular value.

Randy> Since every iterator type must support construction without
Randy> association with any container, it follows that every iterator type
Randy> must support a singular value.

Why?

Randy> Since every iterator does in fact have such a singular value,
Randy> it seems that it would be reasonable, and useful, to be able to
Randy> detect that value, which would allow iterators to be used in
Randy> conditional statements the same way that pointers are.

Why do you think that every iterator has a singular value?

Randy> All that would be needed to provide this support would be to
Randy> require each iterator type to provide an operator bool that
Randy> returned true if the iterator is (possibly) valid, i.e., is
Randy> associated with a position in a container, and false if the
Randy> iterator is not valid, i.e., is not associated with a position
Randy> in any container.

Pointers are iterators.  How would you implement this bool for
a pointer?  Remember that if a pointer has an undefined value,
you are not even allowed to copy or otherwise inspect that value.

--
Andrew Koenig, ark@research.att.com, http://www.research.att.com/info/ark

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "John Hickin" <hickin@nortelnetworks.com>
Date: Fri, 2 Aug 2002 13:28:01 CST
Raw View
Andrew Koenig wrote:
>
> Randy> Iterators too can be singular.  For example:
>
> Randy>   std::string::iterator    iter;
>
> Randy> When initially created an iterator is not associated with any
> Randy> container and is, by definition, singular.
>
> Where do you find this definition?  In particular, remember that a
> pointer is an iterator, and if you define
>
>         int* p;
>
> then p has an undefined value.  That is, p is invalid, not singular.
>

I think that the original poster is using
http://www.sgi.com/tech/stl/trivial.html as the source of the definition
of _singular iterator_. To quote that source:

A Trivial Iterator may have a singular value, meaning that the results
of most operations, including comparison for equality, are undefined.
The only operation that a is guaranteed to be supported is assigning a
nonsingular iterator to a singular iterator.


Regards, John.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Allan_W@my-dejanews.com (Allan W)
Date: Fri, 2 Aug 2002 22:03:23 GMT
Raw View
rmaddox@isicns.com (Randy Maddox) wrote
> Iterators, like pointers, do have a singular value.
[It is easy to test for null pointers, for example:]
>   T    *ptr = some_initialization_expression;
>   if(ptr)
>   {
>     // here we know ptr is NOT singular
>   }
>
> Iterators too can be singular.  For example:
>
>   std::string::iterator    iter;
>
> When initially created an iterator is not associated with any
> container and is, by definition, singular.

I would consider the container.end() value to be the "singular" value,
but please continue...

> With pointers the singular value NULL allows the pointer to convey
> whether or not it is (possibly) valid.  This adds a bit of bandwidth
> to use of a pointer since it can convey not just a location but also
> information about whether that location is valid or not.
>
> With iterators, however, the singular value is useless because we have
> no way to test for it.

You can of course compare an iterator to end, but only if you already
have the container.

> We can only assume that an iterator is valid
> and hope that assumption is correct.
>
> Since every iterator type must support construction without
> association with any container, it follows that every iterator type
> must support a singular value.  Since every iterator does in fact have
> such a singular value, it seems that it would be reasonable, and
> useful, to be able to detect that value, which would allow iterators
> to be used in conditional statements the same way that pointers are.
>
> All that would be needed to provide this support would be to require
> each iterator type to provide an operator bool that returned true if
> the iterator is (possibly) valid, i.e., is associated with a position
> in a container, and false if the iterator is not valid, i.e., is not
> associated with a position in any container.
>
> Anybody have any thoughts on this?

My first thought is that I like the idea.

My second thought is that we ought to do something explicit instead,
because implicit conversions cause problems.

But then I think about how it's really going to be used. I want this
code:
    template<type T>foo(T iter) {
        if (iter) { /* ... */ }
    }
to "work" whether T is a pointer or an iterator. So I'm back to
agreeing with you that operator bool might be the best choice.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Daniel Pullwitt <pullwitt@informatik.uni-leipzig.de>
Date: Sat, 3 Aug 2002 00:04:35 GMT
Raw View
Randy Maddox wrote:

> Iterators, like pointers, do have a singular value.  For a pointer
> this is the value 0, and this value can be tested for by the default
> conversion of a pointer to a bool.  This leads to the common idiom of
> testing for a NULL (singular) pointer in a conditional.
>
> Iterators too can be singular.  For example:
>
>   std::string::iterator    iter;
>
> When initially created an iterator is not associated with any
> container and is, by definition, singular.

Not every iterator can be defined that way, just take a look at the STLs
output iterators like insert_iterator. You can also define iterators which
have no relation to containers (therefore are singular according to your
definition) but can always be accessed safely, for instance by generating
values on access.

> With pointers the singular value NULL allows the pointer to convey
> whether or not it is (possibly) valid.  This adds a bit of bandwidth
> to use of a pointer since it can convey not just a location but also
> information about whether that location is valid or not.
>
> With iterators, however, the singular value is useless because we have
> no way to test for it.  We can only assume that an iterator is valid
> and hope that assumption is correct.

You should not rely on such assumptions in your program. There is a quite
simple
way to test it for the STL container iterators which also works for pointers:

template<typename I> bool is_singular(I const& it) { return I() == it; }

While this test identifies singular iterators it can not determine validity.
An access might
still fail. As you can have (non zero) pointers to memory locations you can
not access,
you can also have (non singular) iterators you can not access.

> Since every iterator type must support construction without
> association with any container, it follows that every iterator type
> must support a singular value.  Since every iterator does in fact have
> such a singular value, it seems that it would be reasonable, and
> useful, to be able to detect that value, which would allow iterators
> to be used in conditional statements the same way that pointers are.

See my remarks above...

> All that would be needed to provide this support would be to require
> each iterator type to provide an operator bool that returned true if
> the iterator is (possibly) valid, i.e., is associated with a position
> in a container, and false if the iterator is not valid, i.e., is not
> associated with a position in any container.

Such a test would be of limited value. It would be reliable valid only for
default constructed iterators. If you operate on containers you always
have a iterator range to test against and you have to take care for iterator
invalidating container operations. I consider introducing an additional,
mostly useless operator as a bad idea.


> Anybody have any thoughts on this?
>
> Randy.
>

Daniel

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Louis Lavery" <Louis@devilschimney.co.uk>
Date: Sat, 3 Aug 2002 10:39:13 GMT
Raw View
Andrew Koenig <ark@research.att.com> wrote in message
news:yu9965yudvm6.fsf@europa.research.att.com...
> Randy> Iterators too can be singular.  For example:
>
> Randy>   std::string::iterator    iter;
>
> Randy> When initially created an iterator is not associated with any
> Randy> container and is, by definition, singular.
>
> Where do you find this definition?  In particular, remember that a
> pointer is an iterator, and if you define
>
>         int* p;
>
> then p has an undefined value.  That is, p is invalid, not singular.

Perhaps it's implied by 24.1 (para 5)  which, in part, says...

Iterators can also have singular values that are not associated with
any container. [Example: After the declaration of an uninitialized
pointer x (as in int* x;), x must always be assumed to have a
singular value of a pointer.]


Louis.






---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Sat, 3 Aug 2002 19:04:03 GMT
Raw View
On Thu,  1 Aug 2002 21:53:15 GMT, rmaddox@isicns.com (Randy Maddox)
wrote:

> Iterators, like pointers, do have a singular value.  For a pointer
> this is the value 0, and this value can be tested for by the default
> conversion of a pointer to a bool.  This leads to the common idiom of
> testing for a NULL (singular) pointer in a conditional.

Where did you get the definition of singular?  The term is only used
in two places in the C++ standard and clearly states that NULL is not
singular.

>   T    *ptr = some_initialization_expression;

Ptr is not singular, but may be nul.

   T* ptr2;

Ptr2 is singular.

>   if(ptr)
>   {
>     // here we know ptr is NOT singular

Because we know that ptr is not singular, here we know that ptr is not
nul.

>   }

   if (ptr2)

Here we have undefined behavior and know nothing from now onward.  It
is undefined behavior to look at the (non)value of an object with a
singular value.

> Iterators too can be singular.  For example:

>   std::string::iterator    iter;

Yes, this iter may be singular.

> When initially created an iterator is not associated with any
> container and is, by definition, singular.

No.  It may also have a unique value, like nul, which all default
constructed string iterators have for a particular implementation.
The standard does not specify whether it will be singular or not.

  if (iter == std::string::iterator())

may be well defined for any implementation.

> With pointers the singular value NULL allows the pointer to convey
> whether or not it is (possibly) valid.  This adds a bit of bandwidth
> to use of a pointer since it can convey not just a location but also
> information about whether that location is valid or not.

Regardless of common usage, the C++ standard only uses singular for
not initialized and allows assignment to as the only operation.

> With iterators, however, the singular value is useless because we have
> no way to test for it.  We can only assume that an iterator is valid
> and hope that assumption is correct.

> Since every iterator type must support construction without
> association with any container, it follows that every iterator type
> must support a singular value.

Sorry, singular is like 1/0 or 0/0.  There is no value or an infinite
number of values.

You want a nul iterator.  Ask for it and do not confuse the issue with
singular which is ill understood by many.

You might also do a search for nul? iterator.  The subject has been
discussed before.  You might also indicate some real examples where a
nul iterator is useful.  Nul pointers are normally used as off the end
iterators for linked structures and absence of optional parameters.
What does a nul iterator mean?  Usage?  Is it possible for every
concievable iterator type to define a nul iterator value?  Remember
the problem of EOF for type char.

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Louis Lavery" <Louis@devilschimney.co.uk>
Date: Sat, 3 Aug 2002 19:04:29 GMT
Raw View
Daniel Pullwitt <pullwitt@informatik.uni-leipzig.de> wrote in message
news:3D4A8D34.704FBBCA@informatik.uni-leipzig.de...
> Randy Maddox wrote:
>
> > Iterators, like pointers, do have a singular value.  For a pointer
> > this is the value 0, and this value can be tested for by the default
> > conversion of a pointer to a bool.  This leads to the common idiom of
> > testing for a NULL (singular) pointer in a conditional.
> >
> > Iterators too can be singular.  For example:
> >
> >   std::string::iterator    iter;
> >
> > When initially created an iterator is not associated with any
> > container and is, by definition, singular.
>
> Not every iterator can be defined that way, just take a look at the STLs
> output iterators like insert_iterator. You can also define iterators which
> have no relation to containers (therefore are singular according to your
> definition) but can always be accessed safely, for instance by generating
> values on access.
>
> > With pointers the singular value NULL allows the pointer to convey
> > whether or not it is (possibly) valid.  This adds a bit of bandwidth
> > to use of a pointer since it can convey not just a location but also
> > information about whether that location is valid or not.
> >
> > With iterators, however, the singular value is useless because we have
> > no way to test for it.  We can only assume that an iterator is valid
> > and hope that assumption is correct.
>
> You should not rely on such assumptions in your program. There is a quite
> simple
> way to test it for the STL container iterators which also works for
pointers:
>
> template<typename I> bool is_singular(I const& it) { return I() == it; }
>

The standard (24.1 para 5), in part, says...

Results of most expressions are undefined for singular values; the only
exception is an assignment of a non-singular value to an iterator that
holds a singular value.

Louis.



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "James Russell Kuyper Jr." <kuyper@wizard.net>
Date: Mon, 5 Aug 2002 02:22:29 GMT
Raw View
Randy Maddox wrote:
>
> Iterators, like pointers, do have a singular value.  For a pointer
> this is the value 0, and this value can be tested for by the default
> conversion of a pointer to a bool.  This leads to the common idiom of
> testing for a NULL (singular) pointer in a conditional.

In section 24.1p5, where singular iterators are defined, it specifies
that only legal operation on a singular iterator is to assign to it a
non-singular value. Therefore, singular iterators are not analogous to
null pointers: null pointer can be compared for equality, and the value
of a null pointer may be stored in another pointer. Null pointers may be
converted to other pointer types, and the result will be a null pointer
of the new type. They can be converted to an integer type and back
again, resulting in a new pointer value equivalent to the first, (if the
integer type is large enough, which is implementation-defined). None of
these operations are permitted for singular iterators.

The singular iterators for the iterator type T*, are the unininitialized
iterators, such as:

 T* pt;

Those objects have precisely the same property that defines singular
iterators: the fact that the only thing you can safely do with them is
to assign a non-singular iterator's value to them.

....
> Since every iterator type must support construction without
> association with any container, it follows that every iterator type
> must support a singular value.  Since every iterator does in fact have

Table 74 says that default-constructed forward iterators might be
singular; but they're not required to be. They could instead correspond
to null pointers: safe for equality comparisons, assignment, and
conversion. Since forward iterators include bidirectional and
random-access iterators, that covers a lot of iterator types.
However, there's no mention of the possibility of default-constructed
input or output iterators being singular. It's unclear what we can
conclude from that silence.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "James Russell Kuyper Jr." <kuyper@wizard.net>
Date: Mon, 5 Aug 2002 02:22:39 GMT
Raw View
Andrew Koenig wrote:
....
> Where do you find this definition?  In particular, remember that a
> pointer is an iterator, and if you define
>
>         int* p;
>
> then p has an undefined value.  That is, p is invalid, not singular.

If you examine the standard's definition of singular iterators, you'll
find that it exactly fits unitialized pointers, and does NOT fit null
pointers.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Mon, 5 Aug 2002 02:22:43 GMT
Raw View
On Sat,  3 Aug 2002 00:04:35 GMT, Daniel Pullwitt
<pullwitt@informatik.uni-leipzig.de> wrote:

> You should not rely on such assumptions in your program. There is a quite
> simple
> way to test it for the STL container iterators which also works for pointers:

> template<typename I> bool is_singular(I const& it) { return I() == it; }

Wrong.  Singular means has no defined value and the only operation
allowed is assignment.  It is impossible to test for singular.  Your
function has undefined behavior and may return anything given a
singular iterator or format your hard drive.  Given a nul pointer it
will return true and a nul pointer is not singular, it is nul.  See
24.1/5 for the meaning of singular as used in the C++ standard.

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Louis Lavery" <Louis@devilschimney.co.uk>
Date: Mon, 5 Aug 2002 04:25:37 GMT
Raw View
Allan W <Allan_W@my-dejanews.com> wrote in message
news:23b84d65.0208021357.78af1c1d@posting.google.com...
> rmaddox@isicns.com (Randy Maddox) wrote
> > Iterators, like pointers, do have a singular value.
> [It is easy to test for null pointers, for example:]
> >   T    *ptr = some_initialization_expression;
> >   if(ptr)
> >   {
> >     // here we know ptr is NOT singular
> >   }
> >
> > Iterators too can be singular.  For example:
> >
> >   std::string::iterator    iter;
> >
> > When initially created an iterator is not associated with any
> > container and is, by definition, singular.
>
> I would consider the container.end() value to be the "singular" value,
> but please continue...
>

The standard (24.1 para5), in part, states...

Dereferenceable and past-the-end values are always non-singular.

Louis.



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: rmaddox@isicns.com (Randy Maddox)
Date: Thu, 1 Aug 2002 21:53:15 GMT
Raw View
Iterators, like pointers, do have a singular value.  For a pointer
this is the value 0, and this value can be tested for by the default
conversion of a pointer to a bool.  This leads to the common idiom of
testing for a NULL (singular) pointer in a conditional.

  T    *ptr = some_initialization_expression;

  if(ptr)
  {
    // here we know ptr is NOT singular
  }

Iterators too can be singular.  For example:

  std::string::iterator    iter;

When initially created an iterator is not associated with any
container and is, by definition, singular.

With pointers the singular value NULL allows the pointer to convey
whether or not it is (possibly) valid.  This adds a bit of bandwidth
to use of a pointer since it can convey not just a location but also
information about whether that location is valid or not.

With iterators, however, the singular value is useless because we have
no way to test for it.  We can only assume that an iterator is valid
and hope that assumption is correct.

Since every iterator type must support construction without
association with any container, it follows that every iterator type
must support a singular value.  Since every iterator does in fact have
such a singular value, it seems that it would be reasonable, and
useful, to be able to detect that value, which would allow iterators
to be used in conditional statements the same way that pointers are.

All that would be needed to provide this support would be to require
each iterator type to provide an operator bool that returned true if
the iterator is (possibly) valid, i.e., is associated with a position
in a container, and false if the iterator is not valid, i.e., is not
associated with a position in any container.

Anybody have any thoughts on this?

Randy.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]