Skip to content

Instantly share code, notes, and snippets.

@MatthewSteel
Created June 24, 2012 12:09
Show Gist options
  • Save MatthewSteel/2983004 to your computer and use it in GitHub Desktop.
Save MatthewSteel/2983004 to your computer and use it in GitHub Desktop.
A lazy zipper in C++11. Written before I heard about all of the LINQ-like libs coming out. Good demonstration of how nice Haskell can be...
#include <iostream>
#include <vector>
#include <tuple>
/*
* Roughly equivalent to the following two lines of Haskell:
* zip (x:xs) (y:ys) = (x,y) : zip xs ys
* zip xs ys = []
*/
template <class T, class Y>
class zipper {
class iterator {
public:
iterator(typename T::iterator tIt, typename Y::iterator yIt) : tIt(tIt), yIt(yIt) {}
bool operator==(const iterator &i) {
return (tIt==i.tIt || yIt==i.yIt);
}
std::tuple<typename T::value_type&, typename Y::value_type&> operator*() {
return std::forward_as_tuple(*tIt, *yIt);
}
iterator& operator++() {
++tIt;
++yIt;
return *this;
}
iterator operator++(int) {
iterator tmp = *this;
++*this;
return tmp;
}
bool operator!=(const iterator &i) {
return (tIt!=i.tIt && yIt!=i.yIt);
}
private:
typename T::iterator tIt;
typename Y::iterator yIt;
};
T& t;
Y& y;
public:
zipper(T& t, Y& y) : t(t), y(y) {}
iterator begin() { return iterator(t.begin(), y.begin()); }
iterator end() { return iterator(t.end(), y.end()); }
};
template<class T, class Y>
zipper<T,Y> zip(T& t, Y& y) { return zipper<T,Y>(t, y); }
using namespace std;
int main() {
vector<int> v{0,1,2};
vector<string> u{"five","four","three","two","one"};
for ( auto x : zip(u,v) ) {
cout << get<0>(x) << "\t" << get<1>(x) << endl;
}
}
/* Output:
* "five 0"
* "four 1"
* "three 2"
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment