#include <iostream>
#include <vector>
#include <tuple>
#include <array>
template <std::size_t N>
bool increase(const std::array<std::size_t, N>& sizes, std::array<std::size_t, N>& it)
{
for (std::size_t i = 0; i != N; ++i) {
const std::size_t index = N - 1 - i;
++it[index];
if (it[index] >= sizes[index]) {
it[index] = 0;
} else {
return true;
}
}
return false;
}
template <typename F, std::size_t ... Is, std::size_t N, typename Tuple>
void apply_impl(F&& f,
std::index_sequence<Is...>,
const std::array<std::size_t, N>& it,
const Tuple& tuple)
{
f(std::get<Is>(tuple)[it[Is]]...);
}
template <typename F, typename ... Ts>
void iterate(F&& f, const std::vector<Ts>&... vs)
{
constexpr std::size_t N = sizeof...(Ts);
std::array<std::size_t, N> sizes{{vs.size()...}};
std::array<std::size_t, N> it{{(vs.size(), 0u)...}};
do {
apply_impl(f, std::index_sequence_for<Ts...>(), it, std::tie(vs...));
} while (increase(sizes, it));
}
void do_job(int a, const std::string& s, int b)
{
std::cout << a << s << b << std::endl;
}
int main()
{
std::vector<int> v1 = {1, 2, 3};
std::vector<std::string> v2 = {" A "," B "};
std::vector<int> v3 = {4, 5};
iterate(do_job, v1, v2, v3);
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8dHVwbGU+CiNpbmNsdWRlIDxhcnJheT4KCnRlbXBsYXRlIDxzdGQ6OnNpemVfdCBOPgpib29sIGluY3JlYXNlKGNvbnN0IHN0ZDo6YXJyYXk8c3RkOjpzaXplX3QsIE4+JiBzaXplcywgc3RkOjphcnJheTxzdGQ6OnNpemVfdCwgTj4mIGl0KQp7CiAgICBmb3IgKHN0ZDo6c2l6ZV90IGkgPSAwOyBpICE9IE47ICsraSkgewogICAgICAgIGNvbnN0IHN0ZDo6c2l6ZV90IGluZGV4ID0gTiAtIDEgLSBpOwogICAgICAgICsraXRbaW5kZXhdOwogICAgICAgIGlmIChpdFtpbmRleF0gPj0gc2l6ZXNbaW5kZXhdKSB7CiAgICAgICAgICAgIGl0W2luZGV4XSA9IDA7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgfQogICAgcmV0dXJuIGZhbHNlOwp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgRiwgc3RkOjpzaXplX3QgLi4uIElzLCBzdGQ6OnNpemVfdCBOLCB0eXBlbmFtZSBUdXBsZT4Kdm9pZCBhcHBseV9pbXBsKEYmJiBmLAogICAgICAgICAgICAgICAgc3RkOjppbmRleF9zZXF1ZW5jZTxJcy4uLj4sCiAgICAgICAgICAgICAgICBjb25zdCBzdGQ6OmFycmF5PHN0ZDo6c2l6ZV90LCBOPiYgaXQsCiAgICAgICAgICAgICAgICBjb25zdCBUdXBsZSYgdHVwbGUpCnsKICAgIGYoc3RkOjpnZXQ8SXM+KHR1cGxlKVtpdFtJc11dLi4uKTsKfQoKdGVtcGxhdGUgPHR5cGVuYW1lIEYsIHR5cGVuYW1lIC4uLiBUcz4Kdm9pZCBpdGVyYXRlKEYmJiBmLCBjb25zdCBzdGQ6OnZlY3RvcjxUcz4mLi4uIHZzKQp7CiAgICBjb25zdGV4cHIgc3RkOjpzaXplX3QgTiA9IHNpemVvZi4uLihUcyk7CiAgICBzdGQ6OmFycmF5PHN0ZDo6c2l6ZV90LCBOPiBzaXplc3t7dnMuc2l6ZSgpLi4ufX07CiAgICBzdGQ6OmFycmF5PHN0ZDo6c2l6ZV90LCBOPiBpdHt7KHZzLnNpemUoKSwgMHUpLi4ufX07CiAKICAgIGRvIHsKICAgICAgICBhcHBseV9pbXBsKGYsIHN0ZDo6aW5kZXhfc2VxdWVuY2VfZm9yPFRzLi4uPigpLCBpdCwgc3RkOjp0aWUodnMuLi4pKTsKICAgIH0gd2hpbGUgKGluY3JlYXNlKHNpemVzLCBpdCkpOwp9Cgp2b2lkIGRvX2pvYihpbnQgYSwgY29uc3Qgc3RkOjpzdHJpbmcmIHMsIGludCBiKQp7CiAgICBzdGQ6OmNvdXQgIDw8IGEgPDwgcyA8PCBiIDw8IHN0ZDo6ZW5kbDsKfQoKCmludCBtYWluKCkKewogICAgc3RkOjp2ZWN0b3I8aW50PiB2MSA9IHsxLCAyLCAzfTsKICAgIHN0ZDo6dmVjdG9yPHN0ZDo6c3RyaW5nPiB2MiA9IHsiIEEgIiwiIEIgIn07CiAgICBzdGQ6OnZlY3RvcjxpbnQ+IHYzID0gezQsIDV9OwogICAgaXRlcmF0ZShkb19qb2IsIHYxLCB2MiwgdjMpOwp9