What is the precondition of the algorithms std::lower_bound
, std::upper_bound
and std::equal_range
?
template <class FwIt, class T>
FwIt lower_bound(FwIt first, FwIt last, const T& val);
template <class FwIt, class T>
FwIt upper_bound(FwIt first, FwIt last, const T& val);
template <class FwIt, class T>
pair<FwIt, FwIt> equal_range(FwIt first, FwIt last, const T& val);
The linked cplusplus.com documentations say that the given range [first
, last
) has to be partitioned with respect to val
. This does not clarify anything, as std::partition
and std::is_partitioned
does not have a val
parameter, instead they have a unary predicate pred
.
template <class FwIt, class UnaryPredicate>
FwIt partition(FwIt first, FwIt last, UnaryPredicate pred);
template <class InputIt, class UnaryPredicate>
bool is_partitioned(InputIt first, InputIt last, UnaryPredicate pred);
The more prominent cppreference.com uses the term partitioned range [first
, last
), which is even more vague. See std::lower_bound
, std::upper_bound
and std::equal_range
.
The source of information is the standard. It’s the source of these sites too.
In this case we could use [alg.binary.search] from C++17. According to this the three functions have different preconditions.
std::lower_bound
The elements e
of [first
, last
) shall be partitioned with respect to the expression e < value
.
std::upper_bound
The elements e
of [first
, last
) shall be partitioned with respect to the expression !(value < e)
.
std::equal_range
The elements e
of [first
, last
) shall be partitioned with respect to the expressions e < value
and !(value < e)
. Also, for all elements e
of [first
, last
), e < value
shall imply !(value < e)
.