Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #3599 > unrolled thread

Initializing iterators to one past end() in for loops

Started byNikos Chantziaras <realnc@arcor.de>
First post2011-04-14 00:38 +0300
Last post2011-04-14 21:45 +0300
Articles 20 on this page of 24 — 9 participants

Back to article view | Back to comp.lang.c++


Contents

  Initializing iterators to one past end() in for loops Nikos Chantziaras <realnc@arcor.de> - 2011-04-14 00:38 +0300
    Re: Initializing iterators to one past end() in for loops Leigh Johnston <leigh@i42.co.uk> - 2011-04-13 22:46 +0100
    Re: Initializing iterators to one past end() in for loops Kai-Uwe Bux <jkherciueh@gmx.net> - 2011-04-13 23:48 +0200
      Re: Initializing iterators to one past end() in for loops Leigh Johnston <leigh@i42.co.uk> - 2011-04-13 22:50 +0100
        Re: Initializing iterators to one past end() in for loops Kai-Uwe Bux <jkherciueh@gmx.net> - 2011-04-14 00:23 +0200
          Re: Initializing iterators to one past end() in for loops Kai-Uwe Bux <jkherciueh@gmx.net> - 2011-04-14 00:32 +0200
            Re: Initializing iterators to one past end() in for loops Noah Roberts <dont@email.me> - 2011-04-13 17:16 -0700
              Re: Initializing iterators to one past end() in for loops Kai-Uwe Bux <jkherciueh@gmx.net> - 2011-04-14 05:57 +0200
                Re: Initializing iterators to one past end() in for loops Leigh Johnston <leigh@i42.co.uk> - 2011-04-14 14:29 +0100
                  Re: Initializing iterators to one past end() in for loops Kai-Uwe Bux <jkherciueh@gmx.net> - 2011-04-14 17:57 +0200
                    Re: Initializing iterators to one past end() in for loops Leigh Johnston <leigh@i42.co.uk> - 2011-04-14 17:56 +0100
                      Re: Initializing iterators to one past end() in for loops Kai-Uwe Bux <jkherciueh@gmx.net> - 2011-04-14 19:33 +0200
                Re: Initializing iterators to one past end() in for loops Noah Roberts <dont@email.me> - 2011-04-14 09:54 -0700
                  Re: Initializing iterators to one past end() in for loops Kai-Uwe Bux <jkherciueh@gmx.net> - 2011-04-14 20:08 +0200
    Re: Initializing iterators to one past end() in for loops gwowen <gwowen@gmail.com> - 2011-04-13 14:49 -0700
    Re: Initializing iterators to one past end() in for loops Sam <sam@email-scan.com> - 2011-04-13 16:58 -0500
    Re: Initializing iterators to one past end() in for loops Nikos Chantziaras <realnc@arcor.de> - 2011-04-14 01:07 +0300
      Re: Initializing iterators to one past end() in for loops Ian Collins <ian-news@hotmail.com> - 2011-04-14 10:12 +1200
      Re: Initializing iterators to one past end() in for loops gwowen <gwowen@gmail.com> - 2011-04-13 15:24 -0700
      Re: Initializing iterators to one past end() in for loops Paavo Helde <myfirstname@osa.pri.ee> - 2011-04-13 23:05 -0500
        Re: Initializing iterators to one past end() in for loops Ian Collins <ian-news@hotmail.com> - 2011-04-14 16:20 +1200
          Re: Initializing iterators to one past end() in for loops Paavo Helde <myfirstname@osa.pri.ee> - 2011-04-13 23:52 -0500
          Re: Initializing iterators to one past end() in for loops Jeff Flinn <TriumphSprint2000@hotmail.com> - 2011-04-14 07:49 -0400
        Re: Initializing iterators to one past end() in for loops Nikos Chantziaras <realnc@arcor.de> - 2011-04-14 21:45 +0300

Page 1 of 2  [1] 2  Next page →


#3599 — Initializing iterators to one past end() in for loops

FromNikos Chantziaras <realnc@arcor.de>
Date2011-04-14 00:38 +0300
SubjectInitializing iterators to one past end() in for loops
Message-ID<io554k$9hn$1@news.grnet.gr>
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[i]

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.

[toc] | [next] | [standalone]


#3603

FromLeigh Johnston <leigh@i42.co.uk>
Date2011-04-13 22:46 +0100
Message-ID<17OdnRrTgaoHhDvQnZ2dnUVZ8gSdnZ2d@giganews.com>
In reply to#3599
On 13/04/2011 22:38, 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[i]
>
> 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.

Simple: check that the vector is not empty before the for loop.

/Leigh

[toc] | [prev] | [next] | [standalone]


#3604

FromKai-Uwe Bux <jkherciueh@gmx.net>
Date2011-04-13 23:48 +0200
Message-ID<io55na$qog$1@hoshi.visyn.net>
In reply to#3599
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[i]
> 
> 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

[toc] | [prev] | [next] | [standalone]


#3607

FromLeigh Johnston <leigh@i42.co.uk>
Date2011-04-13 22:50 +0100
Message-ID<J4GdnRzOQoMOhzvQnZ2dnUVZ8hednZ2d@giganews.com>
In reply to#3604
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[i]
>>
>> 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?

/Leigh

[toc] | [prev] | [next] | [standalone]


#3616

FromKai-Uwe Bux <jkherciueh@gmx.net>
Date2011-04-14 00:23 +0200
Message-ID<io57ov$rjf$1@hoshi.visyn.net>
In reply to#3607
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[i]
>>>
>>> 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

[toc] | [prev] | [next] | [standalone]


#3619

FromKai-Uwe Bux <jkherciueh@gmx.net>
Date2011-04-14 00:32 +0200
Message-ID<io5893$rjf$2@hoshi.visyn.net>
In reply to#3616
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[i]
>>>>
>>>> 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

[toc] | [prev] | [next] | [standalone]


#3629

FromNoah Roberts <dont@email.me>
Date2011-04-13 17:16 -0700
Message-ID<4da63ccd$0$14279$cc2e38e6@news.uslec.net>
In reply to#3619
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[i]
>>>>>
>>>>> 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

[toc] | [prev] | [next] | [standalone]


#3635

FromKai-Uwe Bux <jkherciueh@gmx.net>
Date2011-04-14 05:57 +0200
Message-ID<io5rak$3a4$1@hoshi.visyn.net>
In reply to#3629
Noah Roberts wrote:

> 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[i]
>>>>>>
>>>>>> 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.

a) Why would that be UB according to my interpretation of [24.1/5]?
b) It seems UB for iterators according to table 74: r++ is defined in terms 
of ++r which needs r to be dereferencable.
c) Why would it be bad if this expression involved UB?
d) Is sizeof(arr) really what you mean?

> 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.

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.

> 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".


Something that also stirs up my curiosity is whether destructing an iterator 
object that holds a singular value is UB.


Best,

Kai-Uwe Bux

[toc] | [prev] | [next] | [standalone]


#3673

FromLeigh Johnston <leigh@i42.co.uk>
Date2011-04-14 14:29 +0100
Message-ID<weudnVZcmYU0azvQnZ2dnUVZ8sydnZ2d@giganews.com>
In reply to#3635
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.

/Leigh

[toc] | [prev] | [next] | [standalone]


#3683

FromKai-Uwe Bux <jkherciueh@gmx.net>
Date2011-04-14 17:57 +0200
Message-ID<io75hu$iu6$1@hoshi.visyn.net>
In reply to#3673
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

[toc] | [prev] | [next] | [standalone]


#3702

FromLeigh Johnston <leigh@i42.co.uk>
Date2011-04-14 17:56 +0100
Message-ID<V_2dnS9ujayyujrQnZ2dnUVZ7sednZ2d@giganews.com>
In reply to#3683
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

/Leigh

[toc] | [prev] | [next] | [standalone]


#3709

FromKai-Uwe Bux <jkherciueh@gmx.net>
Date2011-04-14 19:33 +0200
Message-ID<io7b58$kuh$1@hoshi.visyn.net>
In reply to#3702
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

[toc] | [prev] | [next] | [standalone]


#3701

FromNoah Roberts <dont@email.me>
Date2011-04-14 09:54 -0700
Message-ID<4da726ca$0$17551$cc2e38e6@news.uslec.net>
In reply to#3635
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

[toc] | [prev] | [next] | [standalone]


#3713

FromKai-Uwe Bux <jkherciueh@gmx.net>
Date2011-04-14 20:08 +0200
Message-ID<io7d7a$lj2$1@hoshi.visyn.net>
In reply to#3701
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

[toc] | [prev] | [next] | [standalone]


#3605

Fromgwowen <gwowen@gmail.com>
Date2011-04-13 14:49 -0700
Message-ID<3b15728a-c425-4df6-b071-cd73c019fdd2@w7g2000pre.googlegroups.com>
In reply to#3599
On Apr 13, 10:38 pm, Nikos Chantziaras <rea...@arcor.de> 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.]

[toc] | [prev] | [next] | [standalone]


#3610

FromSam <sam@email-scan.com>
Date2011-04-13 16:58 -0500
Message-ID<cone.1302731935.197306.29607.500@monster.email-scan.com>
In reply to#3599

[Multipart message — attachments visible in raw view] — view raw

Nikos Chantziaras writes:

> 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[i]

Any reference to vec[vec.size()] is undefined behavior.

> 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.

That's because it's undefined behavior, as well.

The only thing that's undefined behavior can be converted to, is more  
undefined behavior.

However, the only time your iterator example produces undefined behavior,  
and "doesn't work" would be if vec is empty. As long as the vec array is not  
empty, your iterator will end up iterating over all elements of the array,  
except the first one.

[toc] | [prev] | [next] | [standalone]


#3611

FromNikos Chantziaras <realnc@arcor.de>
Date2011-04-14 01:07 +0300
Message-ID<io56qc$cu8$1@news.grnet.gr>
In reply to#3599
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[i]
>
> 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.

[toc] | [prev] | [next] | [standalone]


#3613

FromIan Collins <ian-news@hotmail.com>
Date2011-04-14 10:12 +1200
Message-ID<90mleiFeeiU10@mid.individual.net>
In reply to#3611
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[i]
>>
>> 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

[toc] | [prev] | [next] | [standalone]


#3617

Fromgwowen <gwowen@gmail.com>
Date2011-04-13 15:24 -0700
Message-ID<f2daf917-43a9-4775-a962-c06dc72d7e69@x12g2000prg.googlegroups.com>
In reply to#3611
On Apr 13, 11:07 pm, Nikos Chantziaras <rea...@arcor.de> 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.

[toc] | [prev] | [next] | [standalone]


#3637

FromPaavo Helde <myfirstname@osa.pri.ee>
Date2011-04-13 23:05 -0500
Message-ID<Xns9EC7481B07908myfirstnameosapriee@216.196.109.131>
In reply to#3611
Nikos Chantziaras <realnc@arcor.de> 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) {
        // do something
    }
}

cheers
Paavo

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.c++


csiph-web