Initializing iterators to one past end() in for loops

Discussion in 'C++' started by Nikos Chantziaras, Apr 13, 2011.

  1. Is there some simple way to convert this:

    std::vector<int> vec;
    // ...
    for (size_t i = 1; i < vec.size(); ++i)
    // do something with vec

    to a for-loop that uses iterators? I've tried:

    typedef std::vector<int>::iterator it_t;
    for (it_t i = vec.begin() + 1; i != vec.end(); ++i)
    // do something with *i

    but I'm not surprised that it doesn't work.
    Nikos Chantziaras, Apr 13, 2011
    #1
    1. Advertising

  2. Nikos Chantziaras

    Kai-Uwe Bux Guest

    Nikos Chantziaras wrote:

    > Is there some simple way to convert this:
    >
    > std::vector<int> vec;
    > // ...
    > for (size_t i = 1; i < vec.size(); ++i)
    > // do something with vec
    >
    > to a for-loop that uses iterators? I've tried:
    >
    > typedef std::vector<int>::iterator it_t;
    > for (it_t i = vec.begin() + 1; i != vec.end(); ++i)
    > // do something with *i
    >
    > but I'm not surprised that it doesn't work.


    Iterators for std::vector<> are random access. Hence, they are <-comparable
    and you can add integers to them. So, you should be able to translate one-
    to-one:

    for ( std::vector<int>::iterator iter = vec.begin() + 1;
    iter < vec.end(); ++ iter ) {
    // do something with *iter
    }

    The stop-condition iter != vec.end() is broken for empty vectors.


    Best,

    Kai-Uwe Bux
    Kai-Uwe Bux, Apr 13, 2011
    #2
    1. Advertising

  3. Nikos Chantziaras

    gwowen Guest

    On Apr 13, 10:38 pm, Nikos Chantziaras <> wrote:

    >    typedef std::vector<int>::iterator it_t;
    >    for (it_t i = vec.begin() + 1; i != vec.end(); ++i)
    >        // do something with *i


    Unless you've got an empty vector, that should pretty much do it,
    unless the "do something with it" modifies the vector in such a way to
    invalidate the iterator (inserting elements will do this). If you have
    an empty vector, vec.begin() == vec.end(), so vec.begin() + 1 will be
    beyond the allowable range of iterators and bad things will happen.

    [To operate on every element want vec.begin(), not vec.begin() + 1 but
    you seem to be deliberately omitting the first element in both code
    samples, so I'm going to assume thats intentional.]
    gwowen, Apr 13, 2011
    #3
  4. On 04/14/2011 12:38 AM, Nikos Chantziaras wrote:
    > Is there some simple way to convert this:
    >
    > std::vector<int> vec;
    > // ...
    > for (size_t i = 1; i < vec.size(); ++i)
    > // do something with vec
    >
    > to a for-loop that uses iterators? I've tried:
    >
    > typedef std::vector<int>::iterator it_t;
    > for (it_t i = vec.begin() + 1; i != vec.end(); ++i)
    > // do something with *i
    >
    > but I'm not surprised that it doesn't work.


    Thanks for all the responses. But I've made a mistake in my provided
    example :p In the second loop, I'm using an std::list, not a vector:

    std::list<int> lst;
    typedef std::list<int>::iterator it_t;
    for (it_t i = lst.begin() + 1; i != lst.end(); ++i)
    // do something with *i

    (Converting some vectors to lists was the reason I came across this in
    the first place.)

    I know it's not difficult to simply do something like:

    it_t i = lst.begin();
    ++i;
    for ( ; i != lst.end(); ++i)

    but I was wondering whether there's some neat way to do that inside the
    for header, so that 'i' will not stay in scope after the loop.
    Nikos Chantziaras, Apr 13, 2011
    #4
  5. Nikos Chantziaras

    Ian Collins Guest

    On 04/14/11 10:07 AM, Nikos Chantziaras wrote:
    > On 04/14/2011 12:38 AM, Nikos Chantziaras wrote:
    >> Is there some simple way to convert this:
    >>
    >> std::vector<int> vec;
    >> // ...
    >> for (size_t i = 1; i < vec.size(); ++i)
    >> // do something with vec
    >>
    >> to a for-loop that uses iterators? I've tried:
    >>
    >> typedef std::vector<int>::iterator it_t;
    >> for (it_t i = vec.begin() + 1; i != vec.end(); ++i)
    >> // do something with *i
    >>
    >> but I'm not surprised that it doesn't work.

    >
    > Thanks for all the responses. But I've made a mistake in my provided
    > example :p In the second loop, I'm using an std::list, not a vector:
    >
    > std::list<int> lst;
    > typedef std::list<int>::iterator it_t;
    > for (it_t i = lst.begin() + 1; i != lst.end(); ++i)
    > // do something with *i
    >
    > (Converting some vectors to lists was the reason I came across this in
    > the first place.)
    >
    > I know it's not difficult to simply do something like:
    >
    > it_t i = lst.begin();
    > ++i;
    > for ( ; i != lst.end(); ++i)


    That would be the usual way.

    > but I was wondering whether there's some neat way to do that inside the
    > for header, so that 'i' will not stay in scope after the loop.


    Put the operation in its own scope (a function maybe)?

    --
    Ian Collins
    Ian Collins, Apr 13, 2011
    #5
  6. Nikos Chantziaras

    Kai-Uwe Bux Guest

    Leigh Johnston wrote:

    > On 13/04/2011 22:48, Kai-Uwe Bux wrote:
    >> Nikos Chantziaras wrote:
    >>
    >>> Is there some simple way to convert this:
    >>>
    >>> std::vector<int> vec;
    >>> // ...
    >>> for (size_t i = 1; i< vec.size(); ++i)
    >>> // do something with vec
    >>>
    >>> to a for-loop that uses iterators? I've tried:
    >>>
    >>> typedef std::vector<int>::iterator it_t;
    >>> for (it_t i = vec.begin() + 1; i != vec.end(); ++i)
    >>> // do something with *i
    >>>
    >>> but I'm not surprised that it doesn't work.

    >>
    >> Iterators for std::vector<> are random access. Hence, they
    >> are<-comparable and you can add integers to them. So, you should be able
    >> to translate one- to-one:
    >>
    >> for ( std::vector<int>::iterator iter = vec.begin() + 1;
    >> iter< vec.end(); ++ iter ) {
    >> // do something with *iter
    >> }

    >
    > If the vector is empty then surely vec.begin() + 1 is UB?


    Hm, my first impulse was to say: "oh, true; that kills it". However, upon
    looking up table 76 in the standard, it appears that

    r += n

    has no pre-condition (like r is dereferencable). Now, r+n is defined in
    terms of r += n. Also, the dereferencability precondition is mentioned at
    other places (e.g., for ++r in table 74 about forward iterators). So, maybe
    vec.begin()+1 is not undefined behavior after all. Of course, it could also
    be an omission in the standard, or it could be that I am too tired to figure
    it out correctly.


    Best,

    Kai-Uwe Bux
    Kai-Uwe Bux, Apr 13, 2011
    #6
  7. Nikos Chantziaras

    gwowen Guest

    On Apr 13, 11:07 pm, Nikos Chantziaras <> wrote:
    > I know it's not difficult to simply do something like:
    >
    >    it_t i = lst.begin();
    >    ++i;
    >    for ( ; i != lst.end(); ++i)
    >
    > but I was wondering whether there's some neat way to do that inside the
    > for header, so that 'i' will not stay in scope after the loop.


    Off the top of my, head and completely untested:

    for(it_t it=l.begin(); ++it != l.end();){
    std::cout << *it << std::endl;
    }

    (Again, you need to make sure you have started with an empty list...)

    for(it_t it=l.begin(); (it != l.end() && ++it != l.end());){
    std::cout << *it << std::endl;
    }

    It's not pretty, but it might work ;) Seems quite an ugly way to do it
    when you can create a scope specifically for the iterator at the cost
    of typing two braces.
    gwowen, Apr 13, 2011
    #7
  8. Nikos Chantziaras

    Kai-Uwe Bux Guest

    Kai-Uwe Bux wrote:

    > Leigh Johnston wrote:
    >
    >> On 13/04/2011 22:48, Kai-Uwe Bux wrote:
    >>> Nikos Chantziaras wrote:
    >>>
    >>>> Is there some simple way to convert this:
    >>>>
    >>>> std::vector<int> vec;
    >>>> // ...
    >>>> for (size_t i = 1; i< vec.size(); ++i)
    >>>> // do something with vec
    >>>>
    >>>> to a for-loop that uses iterators? I've tried:
    >>>>
    >>>> typedef std::vector<int>::iterator it_t;
    >>>> for (it_t i = vec.begin() + 1; i != vec.end(); ++i)
    >>>> // do something with *i
    >>>>
    >>>> but I'm not surprised that it doesn't work.
    >>>
    >>> Iterators for std::vector<> are random access. Hence, they
    >>> are<-comparable and you can add integers to them. So, you should be able
    >>> to translate one- to-one:
    >>>
    >>> for ( std::vector<int>::iterator iter = vec.begin() + 1;
    >>> iter< vec.end(); ++ iter ) {
    >>> // do something with *iter
    >>> }

    >>
    >> If the vector is empty then surely vec.begin() + 1 is UB?

    >
    > Hm, my first impulse was to say: "oh, true; that kills it". However, upon
    > looking up table 76 in the standard, it appears that
    >
    > r += n
    >
    > has no pre-condition (like r is dereferencable). Now, r+n is defined in
    > terms of r += n. Also, the dereferencability precondition is mentioned at
    > other places (e.g., for ++r in table 74 about forward iterators). So,
    > maybe vec.begin()+1 is not undefined behavior after all. Of course, it
    > could also be an omission in the standard, or it could be that I am too
    > tired to figure it out correctly.


    Seems, it was the third option:

    [24.1/5] Iterators can also have singular values that are not associated
    with any container. [Example: After the declaration of an uninitialized
    pointer x (as with int* x;), x must always be assumed to have a singular
    value of a pointer. ] 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. In this case the
    singular value is overwritten the same way as any other value.
    Dereferenceable values are always non-singular.

    Hence, vec.begin()+1 is not UB (as vec.begin() is non-singular), but
    assigning the resulting singular value to the iterator variable iter is UB.


    Best,

    Kai-Uwe Bux
    Kai-Uwe Bux, Apr 13, 2011
    #8
  9. Nikos Chantziaras

    Noah Roberts Guest

    On 4/13/2011 3:32 PM, Kai-Uwe Bux wrote:
    > Kai-Uwe Bux wrote:
    >
    >> Leigh Johnston wrote:
    >>
    >>> On 13/04/2011 22:48, Kai-Uwe Bux wrote:
    >>>> Nikos Chantziaras wrote:
    >>>>
    >>>>> Is there some simple way to convert this:
    >>>>>
    >>>>> std::vector<int> vec;
    >>>>> // ...
    >>>>> for (size_t i = 1; i< vec.size(); ++i)
    >>>>> // do something with vec
    >>>>>
    >>>>> to a for-loop that uses iterators? I've tried:
    >>>>>
    >>>>> typedef std::vector<int>::iterator it_t;
    >>>>> for (it_t i = vec.begin() + 1; i != vec.end(); ++i)
    >>>>> // do something with *i
    >>>>>
    >>>>> but I'm not surprised that it doesn't work.
    >>>>
    >>>> Iterators for std::vector<> are random access. Hence, they
    >>>> are<-comparable and you can add integers to them. So, you should be able
    >>>> to translate one- to-one:
    >>>>
    >>>> for ( std::vector<int>::iterator iter = vec.begin() + 1;
    >>>> iter< vec.end(); ++ iter ) {
    >>>> // do something with *iter
    >>>> }
    >>>
    >>> If the vector is empty then surely vec.begin() + 1 is UB?

    >>
    >> Hm, my first impulse was to say: "oh, true; that kills it". However, upon
    >> looking up table 76 in the standard, it appears that
    >>
    >> r += n
    >>
    >> has no pre-condition (like r is dereferencable). Now, r+n is defined in
    >> terms of r += n. Also, the dereferencability precondition is mentioned at
    >> other places (e.g., for ++r in table 74 about forward iterators). So,
    >> maybe vec.begin()+1 is not undefined behavior after all. Of course, it
    >> could also be an omission in the standard, or it could be that I am too
    >> tired to figure it out correctly.

    >
    > Seems, it was the third option:
    >
    > [24.1/5] Iterators can also have singular values that are not associated
    > with any container. [Example: After the declaration of an uninitialized
    > pointer x (as with int* x;), x must always be assumed to have a singular
    > value of a pointer. ] 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. In this case the
    > singular value is overwritten the same way as any other value.
    > Dereferenceable values are always non-singular.
    >
    > Hence, vec.begin()+1 is not UB (as vec.begin() is non-singular), but
    > assigning the resulting singular value to the iterator variable iter is UB.


    The problem here though is that if you where interpreting correctly then
    pointers could not be iterators since (arr + sizeof(arr))++ is UB.

    Luckily I believe you're interpreting incorrectly. The quote you show
    there quite explicitly calls "most expressions are undefined...". The
    only exception it provides is assignment FROM a non-singular. It seems
    to be quite clearly illustrating that default constructed and
    uninitialized iterators can exist but that you'd better not do anything
    with them but assign to them from a valid iterator value that actually
    iterates something. Further it isn't allowing for incrementing an
    iterator past end().

    --
    http://crazycpp.wordpress.com
    Noah Roberts, Apr 14, 2011
    #9
  10. Nikos Chantziaras

    Ian Collins Guest

    On 04/14/11 04:05 PM, Paavo Helde wrote:
    > Nikos Chantziaras<> wrote in news:io56qc$cu8$1
    > @news.grnet.gr:
    >> Thanks for all the responses. But I've made a mistake in my provided
    >> example :p In the second loop, I'm using an std::list, not a vector:
    >>
    >> std::list<int> lst;
    >> typedef std::list<int>::iterator it_t;
    >> for (it_t i = lst.begin() + 1; i != lst.end(); ++i)
    >> // do something with *i
    >>
    >> (Converting some vectors to lists was the reason I came across this in
    >> the first place.)
    >>
    >> I know it's not difficult to simply do something like:
    >>
    >> it_t i = lst.begin();
    >> ++i;
    >> for ( ; i != lst.end(); ++i)
    >>
    >> but I was wondering whether there's some neat way to do that inside the
    >> for header, so that 'i' will not stay in scope after the loop.

    >
    > std::list<int> lst;
    > typedef std::list<int>::iterator it_t;
    > // populate list
    >
    > if (!lst.empty()) {
    > for (it_t i = std::next(lst.begin()); i != lst.end(); ++i) {


    For those using C++0x compilers!

    --
    Ian Collins
    Ian Collins, Apr 14, 2011
    #10
  11. Nikos Chantziaras

    Jeff Flinn Guest

    Ian Collins wrote:
    > On 04/14/11 04:05 PM, Paavo Helde wrote:
    >> Nikos Chantziaras<> wrote in news:io56qc$cu8$1
    >> @news.grnet.gr:
    >>> Thanks for all the responses. But I've made a mistake in my provided
    >>> example :p In the second loop, I'm using an std::list, not a vector:
    >>>
    >>> std::list<int> lst;
    >>> typedef std::list<int>::iterator it_t;
    >>> for (it_t i = lst.begin() + 1; i != lst.end(); ++i)
    >>> // do something with *i
    >>>
    >>> (Converting some vectors to lists was the reason I came across this in
    >>> the first place.)
    >>>
    >>> I know it's not difficult to simply do something like:
    >>>
    >>> it_t i = lst.begin();
    >>> ++i;
    >>> for ( ; i != lst.end(); ++i)
    >>>
    >>> but I was wondering whether there's some neat way to do that inside the
    >>> for header, so that 'i' will not stay in scope after the loop.

    >>
    >> std::list<int> lst;
    >> typedef std::list<int>::iterator it_t;
    >> // populate list
    >>
    >> if (!lst.empty()) {
    >> for (it_t i = std::next(lst.begin()); i != lst.end(); ++i) {

    >
    > For those using C++0x compilers!
    >


    for (it_t i = boost::next(lst.begin()); i != lst.end(); ++i) {

    For those with most any compiler!

    Jeff
    Jeff Flinn, Apr 14, 2011
    #11
  12. Nikos Chantziaras

    Kai-Uwe Bux Guest

    Leigh Johnston wrote:

    > On 14/04/2011 04:57, Kai-Uwe Bux wrote:
    >>
    >> Something that also stirs up my curiosity is whether destructing an
    >> iterator object that holds a singular value is UB.
    >>

    >
    > Not UB according to the Standard.


    Good to know. Do you have chapter and verse where the behavior is defined?


    Best,

    Kai-Uwe Bux
    Kai-Uwe Bux, Apr 14, 2011
    #12
  13. Nikos Chantziaras

    Noah Roberts Guest

    On 4/13/2011 8:57 PM, Kai-Uwe Bux wrote:
    > Noah Roberts wrote:
    >
    >> On 4/13/2011 3:32 PM, Kai-Uwe Bux wrote:
    >>> Kai-Uwe Bux wrote:


    >>> Seems, it was the third option:
    >>>
    >>> [24.1/5] Iterators can also have singular values that are not
    >>> [associated
    >>> with any container. [Example: After the declaration of an
    >>> uninitialized pointer x (as with int* x;), x must always be assumed to
    >>> have a singular value of a pointer. ] 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. In
    >>> this case the singular value is overwritten the same way as any other
    >>> value. Dereferenceable values are always non-singular.
    >>>
    >>> Hence, vec.begin()+1 is not UB (as vec.begin() is non-singular), but
    >>> assigning the resulting singular value to the iterator variable iter is
    >>> UB.

    >>
    >> The problem here though is that if you where interpreting correctly then
    >> pointers could not be iterators since [incrementing past the past-the-end iterator] is UB.

    >
    > a) Why would that be UB according to my interpretation of [24.1/5]?


    It's not. It's UB because incrementing a pointer beyond what the
    standard explicitly allows (for example 1 past the end of an array) is
    UB. Thus if your interpretation of the quoted bits where accurate,
    std::vector<T>::iterator could not be a pointer because past_end_ptr+1
    is not defined, regardless of if its assigned to anything.

    > c) Why would it be bad if this expression involved UB?


    Practically speaking, most of the time, you probably wouldn't notice any
    unexpected behavior from this particular kind of UB.

    >
    > Exactly. I have a cold, so maybe my brain is not working properly; but the
    > way I read [24.1/5] is as follows:
    >
    > iterator iter = vec.begin(); // iter holds non-singular value.
    > vec.begin() + 1; // vec.begin() is a non-singular operand
    > iter = vec.begin() + 1; // if vec is empty, the rhs is singular.
    > // the operation of assignment is UB.


    24.1/5 isn't actually saying anything about "non-singular values" except
    how assignment of them into previously singular iterators works. You
    can't use 24.1/5 as evidence that vec.begin() + 1 is defined when
    vec.empty() == true.
    >
    >> It seems
    >> to be quite clearly illustrating that default constructed and
    >> uninitialized iterators can exist but that you'd better not do anything
    >> with them but assign to them from a valid iterator value that actually
    >> iterates something. Further it isn't allowing for incrementing an
    >> iterator past end().

    >
    > Well, vec.end() is a non-singular value. Hence, the expression vec.end()+1
    > has a singular _result_ but the operands are non-singular. The way I read
    > [24.1/5] is that the result is defined although singular, i.e., I take the
    > phrase
    >
    > Results of most expressions are undefined for singular values
    >
    > to mean "undefined for singular values of the operands".


    To show that it's not defined, we first have to realize that if it's not
    defined by the standard it's as UB as if the standard specifically says
    so. If you note table 76, r + n is defined in terms of r+= n, which is
    defined in terms of r+n. r+n is defined in terms of ++r. The
    precondition for r in this case is that it is dereferenceable (24.1/5.
    Since end() is not, ++end() is not defined. Since ++end() is not
    defined, neither is end() + n.

    Based on these clauses and tables it would seem to me that the only way
    to get "singular" iterators is to not initialize an iterator. There's
    no defined way to get one from a non-singular iterator because any
    operation that could create one is not defined to do anything in
    particular by the standard. In some cases (and I've written them)
    ++end() will crash or do something really stupid like return end().

    --
    http://crazycpp.wordpress.com
    Noah Roberts, Apr 14, 2011
    #13
  14. Nikos Chantziaras

    Kai-Uwe Bux Guest

    Leigh Johnston wrote:

    > On 14/04/2011 16:57, Kai-Uwe Bux wrote:
    >> Leigh Johnston wrote:
    >>
    >>> On 14/04/2011 04:57, Kai-Uwe Bux wrote:
    >>>>
    >>>> Something that also stirs up my curiosity is whether destructing an
    >>>> iterator object that holds a singular value is UB.
    >>>>
    >>>
    >>> Not UB according to the Standard.

    >>
    >> Good to know. Do you have chapter and verse where the behavior is
    >> defined?
    >>

    >
    > 24.2.1/5


    Ah, you are referring to C++0X.


    Thanks,

    Kai-Uwe Bux
    Kai-Uwe Bux, Apr 14, 2011
    #14
  15. Nikos Chantziaras

    Kai-Uwe Bux Guest

    Noah Roberts wrote:

    > On 4/13/2011 8:57 PM, Kai-Uwe Bux wrote:
    >> Noah Roberts wrote:
    >>
    >>> On 4/13/2011 3:32 PM, Kai-Uwe Bux wrote:
    >>>> Kai-Uwe Bux wrote:

    >
    >>>> Seems, it was the third option:
    >>>>
    >>>> [24.1/5] Iterators can also have singular values that are not
    >>>> [associated
    >>>> with any container. [Example: After the declaration of an
    >>>> uninitialized pointer x (as with int* x;), x must always be assumed
    >>>> to have a singular value of a pointer. ] 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. In this case the singular value is overwritten
    >>>> the same way as any other value. Dereferenceable values are always
    >>>> non-singular.
    >>>>
    >>>> Hence, vec.begin()+1 is not UB (as vec.begin() is non-singular), but
    >>>> assigning the resulting singular value to the iterator variable iter is
    >>>> UB.
    >>>
    >>> The problem here though is that if you where interpreting correctly then
    >>> pointers could not be iterators since [incrementing past the
    >>> past-the-end iterator] is UB.

    >>
    >> a) Why would that be UB according to my interpretation of [24.1/5]?

    >
    > It's not. It's UB because incrementing a pointer beyond what the
    > standard explicitly allows (for example 1 past the end of an array) is
    > UB. Thus if your interpretation of the quoted bits where accurate,
    > std::vector<T>::iterator could not be a pointer because past_end_ptr+1
    > is not defined, regardless of if its assigned to anything.


    Just to make sure, I grok the logic here:

    1) For a pointer, past_end_ptr+1 is undefined.

    2) According to my interpretation, vec.end()+1 is defined (as long as not
    assigned to anything).

    3) Hence: std::vector<T>::iterator could not be a pointer.

    I would phrase that point differently: under the proposed interpretation,
    pointers would not satisfy the requirements for random access iterators.


    >> c) Why would it be bad if this expression involved UB?

    >
    > Practically speaking, most of the time, you probably wouldn't notice any
    > unexpected behavior from this particular kind of UB.
    >
    >>
    >> Exactly. I have a cold, so maybe my brain is not working properly; but
    >> the way I read [24.1/5] is as follows:
    >>
    >> iterator iter = vec.begin(); // iter holds non-singular value.
    >> vec.begin() + 1; // vec.begin() is a non-singular operand
    >> iter = vec.begin() + 1; // if vec is empty, the rhs is singular.
    >> // the operation of assignment is UB.

    >
    > 24.1/5 isn't actually saying anything about "non-singular values" except
    > how assignment of them into previously singular iterators works. You
    > can't use 24.1/5 as evidence that vec.begin() + 1 is defined when
    > vec.empty() == true.
    >>
    >>> It seems
    >>> to be quite clearly illustrating that default constructed and
    >>> uninitialized iterators can exist but that you'd better not do anything
    >>> with them but assign to them from a valid iterator value that actually
    >>> iterates something. Further it isn't allowing for incrementing an
    >>> iterator past end().

    >>
    >> Well, vec.end() is a non-singular value. Hence, the expression
    >> vec.end()+1 has a singular _result_ but the operands are non-singular.
    >> The way I read
    >> [24.1/5] is that the result is defined although singular, i.e., I take
    >> [the
    >> phrase
    >>
    >> Results of most expressions are undefined for singular values
    >>
    >> to mean "undefined for singular values of the operands".

    >
    > To show that it's not defined, we first have to realize that if it's not
    > defined by the standard it's as UB as if the standard specifically says
    > so. If you note table 76, r + n is defined in terms of r+= n, which is
    > defined in terms of r+n. r+n is defined in terms of ++r. The
    > precondition for r in this case is that it is dereferenceable (24.1/5.
    > Since end() is not, ++end() is not defined. Since ++end() is not
    > defined, neither is end() + n.


    This definition in terms of ++r is what I missed. Thanks.


    > Based on these clauses and tables it would seem to me that the only way
    > to get "singular" iterators is to not initialize an iterator. There's
    > no defined way to get one from a non-singular iterator because any
    > operation that could create one is not defined to do anything in
    > particular by the standard. In some cases (and I've written them)
    > ++end() will crash or do something really stupid like return end().


    Yup, seems that way.


    Best,

    Kai-Uwe Bux
    Kai-Uwe Bux, Apr 14, 2011
    #15
  16. On 04/14/2011 07:05 AM, Paavo Helde wrote:
    > Nikos Chantziaras<> wrote in news:io56qc$cu8$1
    > @news.grnet.gr:
    >> Thanks for all the responses. But I've made a mistake in my provided
    >> example :p In the second loop, I'm using an std::list, not a vector:
    >>
    >> std::list<int> lst;
    >> typedef std::list<int>::iterator it_t;
    >> for (it_t i = lst.begin() + 1; i != lst.end(); ++i)
    >> // do something with *i
    >>
    >> (Converting some vectors to lists was the reason I came across this in
    >> the first place.)
    >>
    >> I know it's not difficult to simply do something like:
    >>
    >> it_t i = lst.begin();
    >> ++i;
    >> for ( ; i != lst.end(); ++i)
    >>
    >> but I was wondering whether there's some neat way to do that inside the
    >> for header, so that 'i' will not stay in scope after the loop.

    > [...]
    >
    > if (!lst.empty()) {
    > for (it_t i = std::next(lst.begin()); i != lst.end(); ++i) {
    > // do something
    > }
    > }


    Yep, that looks nicer! It's C++0x, but seems to be supported well
    enough by now.
    Nikos Chantziaras, Apr 14, 2011
    #16
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. ozbear

    One-past-end-of-object pointers

    ozbear, Sep 1, 2004, in forum: C Programming
    Replies:
    3
    Views:
    467
  2. Old Wolf

    Subtracting 0 from one-past-end pointer

    Old Wolf, Nov 17, 2004, in forum: C Programming
    Replies:
    7
    Views:
    356
    Dan Pop
    Nov 17, 2004
  3. Matthias Kaeppler

    Dereferencing past-the-end iterators

    Matthias Kaeppler, Jul 22, 2005, in forum: C++
    Replies:
    2
    Views:
    417
    Matthias Kaeppler
    Jul 23, 2005
  4. BigMan
    Replies:
    8
    Views:
    362
    Ben Pope
    Jul 30, 2005
  5. Mark Stijnman
    Replies:
    5
    Views:
    499
    Mark Stijnman
    Jan 28, 2006
Loading...

Share This Page