#include <iostream>
#include <iterator>
#include <algorithm>
#include <vector>
#include <queue>
#include <cassert>


template<typename Iterator, typename Operation>
void iterate_ranges (Iterator from, Iterator to, Operation op) {
  using R = typename std::iterator_traits<Iterator>::value_type;
  using N = typename std::decay<decltype(std::declval<R>().first)>::type;
  using P = std::pair<N, R>;
  auto compare = [](P const & left, P const & right) {
    return left.first > right.first;};

  std::priority_queue<P, std::vector<P>, decltype(compare)> queue(compare);

  auto push = [& queue] (P p) {
    if (p.first < p.second.last) queue.push(p); };
  auto next = [](P const & p) -> P {
    assert(p.second.step > 0);
    return {p.first + p.second.step, p.second}; };
  auto init = [&push] (R const & r) {
    push({r.first, r}); };

  std::for_each(from, to, init);

  if (queue.empty()) return;
  
  N last = queue.top().first;
  push(next(queue.top()));
  queue.pop();
  op(last);

  while (! queue.empty()) {
    P current = queue.top();
    queue.pop();
    if (current.first != last) {
      op(current.first);
      last = current.first;
    }
    push(next(current));
  }
}

struct Range {
  int first;
  int last;
  int step;
};


int main() {
  Range ranges [] = {
    {1, 10, 2},
    {2, 50, 5}};

  auto print = [](auto n) { std::cout << n << std::endl; };

  iterate_ranges(std::begin(ranges), std::end(ranges), print);
}