Skip to content

Instantly share code, notes, and snippets.

@danshapero
Last active June 19, 2016 02:12
Show Gist options
  • Save danshapero/4cdac531587203a50bc141cadf8a92e9 to your computer and use it in GitHub Desktop.
Save danshapero/4cdac531587203a50bc141cadf8a92e9 to your computer and use it in GitHub Desktop.
C++11 multi-iterator
#include <tuple>
/* ==============
* Multi-iterator
* ============== */
template <size_t> struct int_{};
template <class... Args>
struct MultiIterator
{
static const size_t size = sizeof...(Args);
using value_type = std::tuple<Args...>;
using iterator = MultiIterator<Args...>;
value_type& operator*()
{
return its;
}
const value_type& operator*() const
{
return its;
}
template <size_t N>
iterator& increment(int_<N>)
{
++std::get<N>(its);
return increment(int_<N + 1>());
}
iterator& increment(int_<size>)
{
return *this;
}
iterator& operator++()
{
return increment(int_<0>());
}
bool operator!=(const iterator& multi_it) const
{
return its != multi_it.its;
}
value_type its;
};
template <class... Args>
MultiIterator<Args...> make_multi_iterator(Args&&... args)
{
return MultiIterator<Args...>{std::make_tuple(args...)};
}
template <size_t N, class Tuple, class T, class... Ts>
Tuple&
tuple_begin(int_<N>, Tuple& it, T&& t, Ts&&... ts)
{
std::get<N>(it) = std::begin(t);
return tuple_begin(int_<N + 1>(), it, std::forward<Ts>(ts)...);
}
template <class Tuple, class... Ts>
Tuple&
tuple_begin(int_<std::tuple_size<Tuple>::value>, Tuple& it, Ts&&...)
{
return it;
}
template <class... Args>
std::tuple<typename std::remove_reference<Args>::type::iterator...> tuple_begin(Args&&... args)
{
std::tuple<typename std::remove_reference<Args>::type::iterator...> it;
it = tuple_begin(int_<0>(), it, std::forward<Args>(args)...);
return it;
}
/* ============
* Test program
* ============ */
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v = {0, 1, 2, 3, 4};
std::vector<char> a = {'a', 'b', 'c', 'd', 'e'};
for (auto it = make_multi_iterator(v.begin(), a.begin());
it != make_multi_iterator(v.end(), a.end());
++it)
std::cout << *std::get<0>(*it) << ", " << *std::get<1>(*it) << std::endl;
auto it = tuple_begin(v, a);
std::cout << *std::get<0>(it) << ", " << *std::get<1>(it) << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment