(#7384) fix partial specialization of lower_bound/upper_bound
(#7384) fix partial specialization of lower_bound/upper_bound

Before templatizing ranger, the lower/upper_bound functions were
templated for generic container types, and specialized (overloaded)
for std::set in particular, to use the optimized std::set::lower_bound
instead of the generic std::lower_bound.

After adding a template parameter for ranger, this meant the std::set
version of our lower_bound function could not be fully specialized or
overloaded, since it still needed at least one template parameter in
all cases.

However, template functions can only be fully specialized, not partially
specialized.  Apparently any attempt to partially-specialize a template
function will silently be treated as a re-definition of any earlier
version of the function template with the same name, rather than overload
or specialize it.

The result was, in fact, the generic std::lower_bound versions were being
used even for a std::set-based container, rather than the intended
std::set::lower_bound.  This did not affect the correctness of any
functions or algorithms, but the effect is worse runtime performance.

...

Anyway, template classes, on the other hand (as opposed to template
functions), can be partially-specialized, so we'll make our custom
lower/upper_bound functions static members of a new helper class that
is partially specialized for a container type of std::set<R>.

htcondor/htcondor,htcondor/htcondor,htcondor/htcondor,htcondor/htcondor,htcondor/htcondor,htcondor/htcondor,htcondor/htcondor,htcondor/htcondor