#include <functional>
#include <numeric>
#include <iostream>
#include <tuple>
#include <vector>
template <typename...T>
class ZipIterator
{
public:
using reference = std::tuple<decltype(*std::declval<T>())...>;
public:
ZipIterator(T&&...i) : m(std::forward<T>(i)...) { };
reference operator * () const { return std::tie(*std::get<T>(m)...); }
ZipIterator operator ++ () { char c[]{ (++std::get<T>(m), 0)... }; return *this; }
bool operator == (const ZipIterator& other) const {
const bool eq[]{ (std::get<T>(m) == std::get<T>(other.m))... };
return std::accumulate(std::begin(eq), std::end(eq), false, std::logical_or<>());
}
bool operator != (const ZipIterator& other) const { return !(*this == other); }
private:
std::tuple<T...> m;
};
template <typename T>
struct IteratorRange
{
T m_begin;
T m_end;
const T& begin() const { return m_begin; }
const T& end() const { return m_end; }
};
template <typename...T>
using ZipRange = IteratorRange<ZipIterator<decltype(std::begin(std::declval<T>()))...>>;
template <typename...T>
ZipRange<T...> make_zip_range(T&&...t) { return {{std::begin(t)...},{ std::end(t)...} }; }
int main()
{
std::vector<int> a { 1, 2, 3 };
std::vector<std::string> b { "hello", "world", "foo", "bar" };
int c[] { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
for (auto&& entry : make_zip_range(a, b, c))
{
std::cout << std::get<0>(entry) << ", " << std::get<1>(entry) << ", " << std::get<2>(entry) << std::endl;
}
}
I2luY2x1ZGUgPGZ1bmN0aW9uYWw+CiNpbmNsdWRlIDxudW1lcmljPgojaW5jbHVkZSA8aW9zdHJlYW0+CiNpbmNsdWRlIDx0dXBsZT4KI2luY2x1ZGUgPHZlY3Rvcj4KCnRlbXBsYXRlIDx0eXBlbmFtZS4uLlQ+CmNsYXNzIFppcEl0ZXJhdG9yCnsKcHVibGljOgoKICAgdXNpbmcgcmVmZXJlbmNlID0gc3RkOjp0dXBsZTxkZWNsdHlwZSgqc3RkOjpkZWNsdmFsPFQ+KCkpLi4uPjsKCnB1YmxpYzoKCiAgIFppcEl0ZXJhdG9yKFQmJi4uLmkpIDogbShzdGQ6OmZvcndhcmQ8VD4oaSkuLi4pIHsgfTsKCiAgIHJlZmVyZW5jZSBvcGVyYXRvciAqICgpIGNvbnN0IHsgcmV0dXJuIHN0ZDo6dGllKCpzdGQ6OmdldDxUPihtKS4uLik7IH0KICAgWmlwSXRlcmF0b3Igb3BlcmF0b3IgKysgKCkgeyBjaGFyIGNbXXsgKCsrc3RkOjpnZXQ8VD4obSksIDApLi4uIH07IHJldHVybiAqdGhpczsgfQoKICAgYm9vbCBvcGVyYXRvciA9PSAoY29uc3QgWmlwSXRlcmF0b3ImIG90aGVyKSBjb25zdCB7CiAgICAgIGNvbnN0IGJvb2wgZXFbXXsgKHN0ZDo6Z2V0PFQ+KG0pID09IHN0ZDo6Z2V0PFQ+KG90aGVyLm0pKS4uLiB9OwogICAgICByZXR1cm4gc3RkOjphY2N1bXVsYXRlKHN0ZDo6YmVnaW4oZXEpLCBzdGQ6OmVuZChlcSksIGZhbHNlLCBzdGQ6OmxvZ2ljYWxfb3I8PigpKTsKICAgfQogICBib29sIG9wZXJhdG9yICE9IChjb25zdCBaaXBJdGVyYXRvciYgb3RoZXIpIGNvbnN0IHsgcmV0dXJuICEoKnRoaXMgPT0gb3RoZXIpOyB9Cgpwcml2YXRlOgogICBzdGQ6OnR1cGxlPFQuLi4+IG07Cn07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4Kc3RydWN0IEl0ZXJhdG9yUmFuZ2UKewogICBUIG1fYmVnaW47CiAgIFQgbV9lbmQ7CgogICBjb25zdCBUJiBiZWdpbigpIGNvbnN0IHsgcmV0dXJuIG1fYmVnaW47IH0KICAgY29uc3QgVCYgZW5kKCkgY29uc3QgeyByZXR1cm4gbV9lbmQ7IH0KfTsKCnRlbXBsYXRlIDx0eXBlbmFtZS4uLlQ+CnVzaW5nIFppcFJhbmdlID0gSXRlcmF0b3JSYW5nZTxaaXBJdGVyYXRvcjxkZWNsdHlwZShzdGQ6OmJlZ2luKHN0ZDo6ZGVjbHZhbDxUPigpKSkuLi4+PjsKCnRlbXBsYXRlIDx0eXBlbmFtZS4uLlQ+ClppcFJhbmdlPFQuLi4+IG1ha2VfemlwX3JhbmdlKFQmJi4uLnQpIHsgcmV0dXJuIHt7c3RkOjpiZWdpbih0KS4uLn0seyBzdGQ6OmVuZCh0KS4uLn0gfTsgfQoKaW50IG1haW4oKQp7CiAgIHN0ZDo6dmVjdG9yPGludD4gYSB7IDEsIDIsIDMgfTsKICAgc3RkOjp2ZWN0b3I8c3RkOjpzdHJpbmc+IGIgeyAiaGVsbG8iLCAid29ybGQiLCAiZm9vIiwgImJhciIgfTsKICAgaW50IGNbXSB7IDksIDgsIDcsIDYsIDUsIDQsIDMsIDIsIDEsIDAgfTsKCiAgIGZvciAoYXV0byYmIGVudHJ5IDogbWFrZV96aXBfcmFuZ2UoYSwgYiwgYykpCiAgIHsKICAgICAgc3RkOjpjb3V0IDw8IHN0ZDo6Z2V0PDA+KGVudHJ5KSA8PCAiLCAiIDw8IHN0ZDo6Z2V0PDE+KGVudHJ5KSA8PCAiLCAiIDw8IHN0ZDo6Z2V0PDI+KGVudHJ5KSA8PCBzdGQ6OmVuZGw7CiAgIH0KfQoK