The book, "Effective STL," (by Scott Meyers), suggests that using sorted vectors instead of associative containers is efficient in some conditions. It shows the example of using std::lower_bound on std::vector. But I found some code in it that looks incorrect:
vector<Widget> vw; // alternative to set<Widget>
...... // Setup phase: lots of
// insertions, few lookups
sort(vw.begin(), vw.end()); // end of Setup phase.
Widget w; // object for value to look up
...... // start Lookup phase
vector<Widget>::iterator i =
lower_bound(vw.begin(), vw.end(), w); // lookup via lower_bound;
(1) Below is the weird part!
if (i != vw.end() && !(*i < w))... // see Item 45 for an explana-
// tion of the"!(*i < w)" test
... // end Lookup phase, start
When you see (1), it checks returned iterator from lower_bound so that it can tell if w is in the vector or not. But I think !(w < *i) is right because std::lower_bound would be using less(w, iterating element). The *i only has two choices: either it is equivalent with w (i.e. w is an element of vector) or it is greater than w. So, as far as I know, to tell these two cases the example code should have used !(w < *i).
Am I correct? Or is there any other reason for above example code?
The
!(*i < w)is clearly wrong (or, at the very least, redundant) because, if thestd::lower_bound()search does not returnvw.end(), then the result of that test must be true. From cppreference:Here's a trivial test that shows it does not correctly determine whether or not a given value is in your vector:
Output (clearly wrong):
However, changing the second test from the above
!(*i < w)form, to your!(w < *i)works, as shown in the following modified code:Output (correct):
So, unless you have somehow inadvertently misrepresented the code from the book you quote (which I am not accusing you of doing), then its author should be contacted to point out their error.