0

I'm working with iterators on a set of elements of size greater that three almost all the time, but it happens that the generated set contains only one element, in this case, the following loop:

for(i = data_set.begin(); i != data_set.end(); i++)
{
//do something with the data
}

will never be entered even though "data_set" is not empty because data_set.begin()==data_set.end() I'm doing a test to handle this particular case alone but the code is turning to a mess and is no longer clean.

What should be done to handle this properly?

Thanks,

자스민

자스민
  • 21
  • 4
  • 4
    `data_set.end()` is "one past the end". It will be entered. – StoryTeller - Unslander Monica Jan 10 '18 at 14:15
  • 7
    You are mistaken `data_set.begin()==data_set.end()` only for empty set, period – Slava Jan 10 '18 at 14:15
  • 2
    This is supposed to work as is. Please make a [mcve] on for example http://coliru.stacked-crooked.com/ to show the error. – nwp Jan 10 '18 at 14:15
  • Because the above comments are true, the condition of your loop works for any set including the empty one. You don't need special handling for those cases. – patatahooligan Jan 10 '18 at 14:17
  • 1
    *will never be entered* -- Why didn't you write a small test? You will see it is entered. – PaulMcKenzie Jan 10 '18 at 14:17
  • I though it wouldn't be entered, I've never used iterators before! Thank you for your comments. I'll read a little more on this. – 자스민 Jan 10 '18 at 14:18
  • 1
    Strange thought, you really think everybody specially handle container of size 1? Huh – Slava Jan 10 '18 at 14:20
  • btw your logic is flawed. If your assumption was correct, then for any size one element would be skipped, there is no reason why a set with a single element would be special with respect to where `end()` and `begin()` point – 463035818_is_not_an_ai Jan 10 '18 at 14:23
  • It's not that, I thought it may use something different from "!=". never mind. – 자스민 Jan 10 '18 at 14:27
  • Sorry for asking this strange and not well thought out question! – 자스민 Jan 10 '18 at 14:28
  • 1
    There is nothing to be sorry about, there are much worse questions asked, you at least work on your code and then ask – Slava Jan 10 '18 at 14:29
  • dont worry. We all started somewhere. Btw it is not what you are asking about that can be critized, but how. If you created a [mcve] you maybe would have realized your misunderstanding by yourself ... and if not it would be much easier to resolve it with an answer – 463035818_is_not_an_ai Jan 10 '18 at 14:29
  • @Slava even experienced programmers coming to C++ have a hard time with `end` being _1 past the last element_. I am not surprised that this question is asked from time to time. It is a strange concept when coming from most other languages. @자스민 You'll want to take a look here: https://stackoverflow.com/a/15252207/368599 – Samaursa Jan 10 '18 at 14:32
  • @Samaursa how else would you define range? – Slava Jan 10 '18 at 14:34
  • @Slava Not arguing that at all. I understand the reasoning behind it. Generally new programmers or programmers not used to STL style iterators, are used to writing `index < size` in the loop condition, which is not the STL way of using iterators. – Samaursa Jan 10 '18 at 14:51

1 Answers1

0

If the set contains only 1 element, then: std::next( data_set.begin() ) == data_set.end(), because begin() iterator points at first element of the container, and end() points to the element that is next after the last one.

Nikita Smirnov
  • 813
  • 8
  • 17
  • OK. Thanks for your answer. – 자스민 Jan 10 '18 at 14:33
  • Is it valid to call `std::next` on an iterator that's already at the container's end? – Mark Ransom Jan 10 '18 at 14:34
  • 1
    @GoverNator -- no, the behavior is undefined. The example you link to is wrong. – Pete Becker Jan 10 '18 at 14:45
  • @PeteBecker i agree that it's strange, but what's wrong with example? It works not like UB. – Nikita Smirnov Jan 10 '18 at 14:51
  • 1
    @GoverNator -- it dereferences the container's past-the-end iterator. With two elements in the container, `std::next(s.begin(),2)` gives you the past-the-end iterator. You aren't allowed to dereference it or increment it. – Pete Becker Jan 10 '18 at 14:57
  • @GoverNator: No, the standard doesn't say anything about `std::next` needed to be circular. In fact, the standard says that it's equivalent to calling `std:;advance` which specifies that if you increment past the end iterator you enter undefined behavior territory. – AndyG Jan 10 '18 at 15:02
  • @GoverNator: And just because "it works" does not mean it is guaranteed to work on all standard-conforming implementations. – AndyG Jan 10 '18 at 15:03
  • Ok, agree with both commentators. It's UB. Looked through StlPort implementation as for example. Dislike for cpp shell(( – Nikita Smirnov Jan 10 '18 at 15:04