2

Unlike lower_bound, upper_bound does not return an iterator to the element if it compares equivalent to value, but only if it compares strictly greater.

Is there an alternative if I want an upper_bound algorithm that is greater than or equal to.

user788171
  • 16,753
  • 40
  • 98
  • 125
  • 1
    -1 the question is not clear. you say you want greater than or equal to. do you mean the first item greater or equal to the value you give? or the last item greater or equal to the value you give? or *any* item greater or equal to the value you give? these functions' names and contracts are already extremely confusing so please be very precise about what you are asking. – Don Hatch May 08 '14 at 23:05

3 Answers3

2

You could decrease the iterator by 1.

auto begin = ...;
auto end = ...;
auto it = std::upper_bound(begin, end, target);
if (it == begin)
  return it;
-- it;
if (*it < target)
  return ++it;
else
  return it;

The position of the iterator will be like this, assume you are searching for 2:

1 1 1 2 2 2 2 3 3 3 3
      ^     ^ ^
      lb    | ub
            this function


1 1 1 1 3 3 3 3
        ^
        lb & ub & this function
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
  • 1
    Can't you just use `lower_bound()`? – flight Jul 08 '12 at 07:44
  • Was hoping there would be something already built into STL but this is not a bad alternative. – user788171 Jul 08 '12 at 07:48
  • @quasiverse: It is different from `lower_bound()` when there are multiple appearances of the target (i.e. when `std::equal_range()` does not return an empty range). See the updated figure. – kennytm Jul 08 '12 at 07:50
  • @KennyTM In that case can't you use `lower_bound()` with a reversed comparator function? – flight Jul 08 '12 at 07:59
  • @quasiverse: It can't, because in that case the array will not be sorted according to `<`. – kennytm Jul 08 '12 at 08:01
  • ... hmm... okay, maybe you can do some trippy stuff with reverse itera... okay, +1 ;) – flight Jul 08 '12 at 08:03
2

Despite the confusing name, std::lower_bound actually does exactly what you want.

Returns an iterator pointing to the first element in the range [first, last) that does not satisfy element < value (or comp(element, value)), (i.e. greater or equal to), or last if no such element is found. https://en.cppreference.com/w/cpp/algorithm/lower_bound

std::set<int> s {0, 1, 3};
std::cout << s.lower_bound(2); // yields 3
std::cout << s.lower_bound(1); // yields 1
poolfork
  • 42
  • 6
0

I did this using option (2)

https://en.cppreference.com/w/cpp/algorithm/upper_bound?force_isolation=true

Assuming you know your data type (int in this case, but you could easily template this):

std::upper_bound(v.begin(), v.end(), target,
                 [](const int &a, const int &b) { return a <= b; });
Emile Cormier
  • 28,391
  • 15
  • 94
  • 122
kiwi
  • 1