Задача такова: есть один едиственный контейнер с данными, есть несколько способов по нему пройтись, но для каждой итерации надо выполнять одинаковый код. Другими словами, нужно иметь возможность задавать алгоритм итерирования извне. Однако то, что выполняется на каждой итерации — должно быть внутренним.
Можно использовать все фичи C++17.
Для себя наклепал вот такой рабочий пример: https://wandbox.org/permlink/kQc59EAs5MSMCxTE
Поревьювьте код, пожалуйста.
using Storage = std::vector<std::string_view>;
using PointType = Storage::const_iterator;
// пример функции итерирования, которая должна вызывать коллбек для каждой итерации
// template для дедукции лямбды
template <typename Callback>
struct IterateArrivals {
  void operator()(const Storage &storage, Callback callback) const {
    for (auto pointBegin = storage.rbegin(); pointBegin != storage.rend(); pointBegin += 2) {
      callback(pointBegin.base() - 1, pointBegin.base() - 2);
    }
  }
};
namespace {
// хелпер, чтоб задедуктить тип лямбды (его не можно задать explicit)
template <template <typename...> class Iterate, typename Callback, typename... Args>
void callIterate(Callback&& callback, Args&&... args) {
    Iterate<Callback>{}(std::forward<Args>(args)..., std::forward<Callback>(callback));
}
} // namespace
template <template <typename...> class Iterate>
void print(const Storage &storage) {
  unsigned int count = 0;
  
  // тут выполняем что-то для каждой итерации (лямбду)
  callIterate<Iterate>([&](PointType loc1, PointType loc2) {
    std::cout << '[' << ++count << "] {" << *loc1 << ", " << *loc2 << "}\n";
    return true;
  }, storage);
}
int main() {
  Storage itin{"A", "B", "B", "C", "E", "F"}; 
  print<IterateArrivals>(itin);
  // печатает:
  // [1] {F, E}
  // [2] {C, B}
  // [3] {B, A}
}



