Re: [Boost-bugs] [Boost C++ Libraries] #11701: Regression in boost::intrusive::set::equal_range

Subject: Re: [Boost-bugs] [Boost C++ Libraries] #11701: Regression in boost::intrusive::set::equal_range
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2015-10-01 21:02:03


#11701: Regression in boost::intrusive::set::equal_range
-------------------------------+------------------------
  Reporter: nyh@… | Owner: igaztanaga
      Type: Bugs | Status: new
 Milestone: To Be Determined | Component: intrusive
   Version: Boost 1.57.0 | Severity: Regression
Resolution: | Keywords:
-------------------------------+------------------------

Comment (by anonymous):

 Hi igaztanaga, thanks for the detailed response, although I have to admit
 I'm a little confused about all the "preconditions" on the given
 comparator which you mention. Can you please point me to some
 documentation which lays them out explicitly?

 But I have to admit I'm surprised by your statements about the various
 "preconditions" and "compatibility" of the two comparators and the fact
 that the second one also needs to define a set. To explain why I'm
 surprised, let's step back for a moment and ask ourselves - why am I using
 lower_bound (or upper_bound or equal_range) at all? Why am I not just
 doing a simple iteration on the set to compare the items in the set with
 the given item, using the given comparator?

 The answer is complexity: Simple iteration has linear complexity (O(N)),
 while upper_bound and friends are supposed to have logarithmic complexity
 O(ln N). BUT, there is one snag: while std::upper_bound
 (http://en.cppreference.com/w/cpp/algorithm/upper_bound) indeed does a
 logarithmic number of *comparisons*, it still needs to do a linear number
 of increments of the iterator when the iterator is not random-access,
 because it cannot skip half the list at once. Other than this snag (linear
 number of increments), std::upper_bound does exactly what I want, and does
 not have any of the "preconditions" you mention on the comparator - all
 you need a guarantee that the comparator in fact divides (partitions) the
 given iteratable list into "smaller than the given item" (according to the
 comparactor in the parameter) and "higher than the given item". That's it.
 And in my example, this condition definitely holds.

 Now, what I expected in boost::intrusive::set::upper_bound and friends, is
 to implement std::upper_bound with one added benefit: Because the set is
 not just a sorted list, but actually a tree, we can skip big parts of the
 list and get ourselves a logarithmic number of iterator updates instead of
 linear, as we hoped. In other words, I expected
 boost::intrusive::set::upper_bound to not be more limited - just better
 performing - than std::upper_bound.

 What most surprised me in your answer is that you seem to say that because
 the given list is known to be a set (according to its intrinsic
 comparator), with non-equal values, then the result of equal_range with a
 '''different''' comparator should always be a single value - no matter
 what the second comparator is (and in particular we're not allowed to
 choose a comparator which declares several items in the set to be equal
 under this comparator). This is really surprising, because
 std::equal_range was designed exactly for the purpose of choosing a
 comparator which does declare multiple items to be equal, and the idea is
 to find all the equal items.

 By the way, interestingly, std::set's upper_bound and friends do not let
 you specify the comparator at all. They always use the set's intrinsic
 comparator. I guess that while boost::intrusive::set's implementation does
 let you specify the comparator, it's really unsafe to do so unless you
 really know what you're doing. Perhaps http://www.open-
 std.org/jtc1/sc22/wg21/docs/papers/2012/n3465.pdf is relevant here. But it
 is apparently not useful to invent your own comparator and belive it would
 work - even if it would have worked just fine in std::upper_bound. The
 rules for a comparator for std::upper_bound and for
 boost::intrusive::set::upper_bound are apparently very different in
 surprising ways.

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/11701#comment:5>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:19 UTC