-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathzip.hpp
70 lines (58 loc) · 2.26 KB
/
zip.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#ifndef ZIP_HPP
#define ZIP_HPP
/* range view adaptor to represent groupings of elements from a number of ranges
Applying it on 3 ranges containing:
{ a,b }
{ 1,2 }
{ X,Y,Z }
produces a view seeing:
{
std::tuple(a,1,X),
std::tuple(b,2,Y)
}
*/
#include "iterator_range.hpp"
#include "variadic.hpp"
#include <iterator>
#include <tuple>
namespace ranges
{
template<typename... UnderlyingIterators>
class zip_iterator
: public std::iterator<
typename std::iterator_traits<get_type_t<0, UnderlyingIterators...>>::iterator_category,
std::tuple<typename std::iterator_traits<UnderlyingIterators>::reference...>,
typename std::iterator_traits<get_type_t<0, UnderlyingIterators...>>::difference_type,
const std::tuple<typename std::iterator_traits<UnderlyingIterators>::reference...>*,
const std::tuple<typename std::iterator_traits<UnderlyingIterators>::reference...>&
>
{
public:
zip_iterator(UnderlyingIterators... iterators) : iterators_(std::make_tuple(iterators...)) {}
zip_iterator operator++() {for_each_tuple(iterators_, [](auto& it){++it;}); return *this;}
zip_iterator& operator=(const zip_iterator& other) { iterators_ = other.iterators_;}
auto operator*() { return transform_tuple(iterators_, [](auto const& it){return *it;});}
bool operator==(const zip_iterator& other){ return iterators_ == other.iterators_;}
bool operator!=(const zip_iterator& other){ return !(*this == other); }
auto operator-(const zip_iterator& other) { return std::get<0>(iterators_) - std::get<0>(other.iterators_);}
private:
std::tuple<UnderlyingIterators...> iterators_;
};
template<typename... Iterators>
zip_iterator<Iterators...> make_zip_iterator(Iterators... underlyingIterators)
{
return zip_iterator<Iterators...>(underlyingIterators...);
}
namespace view
{
template<typename... Ranges>
iterator_range<zip_iterator<typename Ranges::const_iterator...>> zip(Ranges const&... ranges)
{
return iterator_range<zip_iterator<typename Ranges::const_iterator...>>(
make_zip_iterator(ranges.begin()...),
make_zip_iterator(ranges.end()...)
);
}
} // namespace view
} // namespace ranges
#endif