Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't C++ set iterators be cast to bool?

For an STL set (s), it seems like you should be able to say:

if(s.find(x)) {
    //Something
}

as opposed to

if(s.find(x) != s.end()) {
    //Something
}

Furthermore, if set-iterators could be cast to bool (true if the internal pointer is not null), you would be able to. Why don't STL set iterators have this simple functionality? Was this intentionally left out?

CLARIFICATION:

Alternatively, set's could just have a set::contains(x) method which returns a bool directly, but this doesn't seem to be implemented either. I know it's only a couple characters, but in the case where s is a return value from some function, this can be frustrating because of the need to create a temporary variable, ie (supposing m is of type map<int,set<int>>)

const set<int>& s = m[i];
return s.find(x) != s.end();

as opposed to

return m[i].contains(x);

or

return m[i].find(x);

EDIT:

I didn't realize the count() method could be used as contains(). Voted to close since this question doesn't properly phrase what I really should have asked: Do STL::set's have a "contains" method?

like image 497
dspyz Avatar asked Dec 14 '13 23:12

dspyz


People also ask

How do I make a custom iterator?

To use custom iterators, you must create an Apex class that implements the Iterator interface. Returns true if there's another item in the collection being traversed, false otherwise. Returns the next item in the collection. All methods in the Iterator interface must be declared as global or public .

Are iterators part of STL?

Iterators are one of the four pillars of the Standard Template Library or STL in C++. An iterator is used to point to the memory address of the STL container classes. For better understanding, you can relate them with a pointer, to some extent.

How do you change an iterator to a pointer?

Unfortunately, there is no way to convert from an iterator directly to a pointer without dereferencing the iterator ( it[0] and &*it both dereference the iterator). As a result, the only way to convert iterators to pointers that is able to handle all valid iterators requires having access to the vector in question.


1 Answers

Iterators in the C++ standard library do not know about the container where they came from, and so they cannot in general know whether they've reached the end. This is deliberate, so as to allow iterators to be as light-weight as possible – you don't pay for what you don't use. (Iterators generalize the idea of pointers, and a pointer is an iterator.)

You can always build your own self-aware iterator as a pair of native iterators.

In fact, some people have argued that such a pair, or range is the more natural way to talk about collections, and there are libraries, as well as library adapters, to implement ranges (e.g. Boost.Range).

Update: Iterators are more low-level than ranges, and it is debatable which concept is a better solution (though one would need to define the problem first). Iterators are a bit more flexible; for example, if you mutate a container while iterating over it, you'd have to "update" all range-pairs to receive the new "end" value. (Or otherwise switch to a completely "range-centered" algorithmic style.) Alternatively you could store a reference to the container in the iterator and recompute end() each time it's needed. Already you can see how there are lots of non-trivial details, and the C++ standard library simply decided not to make those choices for you but instead only give you the building blocks to write the solution that fits your own problem best.

like image 144
Kerrek SB Avatar answered Oct 20 '22 05:10

Kerrek SB