Задача такова: есть один едиственный контейнер с данными, есть несколько способов по нему пройтись, но для каждой итерации надо выполнять одинаковый код. Другими словами, нужно иметь возможность задавать алгоритм итерирования извне. Однако то, что выполняется на каждой итерации — должно быть внутренним.
Можно использовать все фичи 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}
}