-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathzip_iterator.h
More file actions
184 lines (149 loc) · 4.97 KB
/
Copy pathzip_iterator.h
File metadata and controls
184 lines (149 loc) · 4.97 KB
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#pragma once
#include <iterator>
#include <tuple>
#include "metautils.h"
namespace lambda {
template<typename _Type>
struct deref_return_type
{
typedef decltype(*std::declval<_Type>()) type;
};
template<typename... _Iterators>
struct iterators_tuple_return_type
{
typedef std::tuple<typename deref_return_type<_Iterators>::type...> type;
};
template<typename... _Iterators>
using iterators_tuple_return_type_t = typename iterators_tuple_return_type<_Iterators...>::type;
template<typename CurrentMax, typename... Tags>
struct maximum_iterator_catagory;
template<typename CurrentMax, typename Tag0, typename... Tags>
struct maximum_iterator_catagory<CurrentMax, Tag0, Tags...> :
std::conditional<std::is_base_of<CurrentMax, std::output_iterator_tag>::value,
type_define<std::output_iterator_tag>,
typename std::conditional <
std::is_base_of<Tag0, std::output_iterator_tag>::value,
type_define<std::output_iterator_tag>,
typename std::conditional <
std::is_base_of<Tag0, CurrentMax>::value,
type_define<Tag0>,
maximum_iterator_catagory<CurrentMax, Tags...> >::type>::type>::type
{};
template<typename CurrentMax>
struct maximum_iterator_catagory<CurrentMax>
{
typedef CurrentMax type;
};
template <typename... _Tags>
using maximum_iterator_catagory_t = typename maximum_iterator_catagory<_Tags...>::type;
template<typename... _Iterables>
class zip_iterator {};
template<typename _Ty, typename... _Iterables>
class zip_iterator<_Ty, _Iterables...> : public std::iterator < maximum_iterator_catagory_t<typename std::iterator_traits<_Ty>::iterator_category, typename std::iterator_traits<_Iterables>::iterator_category...>,
iterators_tuple_return_type_t < _Ty, _Iterables... >>
{
// the perfect forwarding will ensure that if we recieved rvalue refrence _Ty will by non-refrence and otherwise we have lvalue refrence
using IteratorType = _Ty;
using TupleReturnType = typename iterators_tuple_return_type<_Ty, _Iterables...>::type;
using HeadDerefRetType = decltype(std::get<0>(std::declval<TupleReturnType>()));
using ConstTupleReturnType = typename iterators_tuple_return_type<const _Ty, const _Iterables...>::type;
using ConstHeadDerefRetType = decltype(std::get<0>(std::declval<ConstTupleReturnType>()));
public:
template<typename _Uy, typename... __Iterables,
typename = std::enable_if_t <
zip_test < std::is_convertible,
types<_Uy&&, __Iterables&&...>,
types < _Ty, _Iterables... >> ::value >>
zip_iterator(_Uy&& head, __Iterables&&... tail) : // prevent copy-constructor confusion
m_head_iterator(std::forward<_Uy>(head)),
m_tail_iterator(std::forward<__Iterables>(tail)...)
{
}
zip_iterator<_Ty, _Iterables...> & operator++() {
++m_head_iterator;
++m_tail_iterator;
return *this;
}
template<typename _Uy>
std::enable_if_t<std::is_lvalue_reference<_Uy>::value, std::reference_wrapper<std::remove_reference_t<_Uy>>>
wrap_refrence_or_value(_Uy val) const
{
using ref_wrap_type = typename std::reference_wrapper<std::remove_reference_t<_Uy>>;
return ref_wrap_type(val);
}
template<typename _Uy>
std::enable_if_t<!std::is_reference<_Uy>::value, _Uy>
wrap_refrence_or_value(_Uy val) const
{
return val;
}
TupleReturnType operator*()
{
return std::tuple_cat(std::make_tuple(wrap_refrence_or_value<decltype(*m_head_iterator)>(*m_head_iterator)), *m_tail_iterator);
}
ConstTupleReturnType operator*() const
{
return std::tuple_cat(std::make_tuple(wrap_refrence_or_value<decltype(*m_head_iterator)>(*m_head_iterator)), *m_tail_iterator);
}
bool operator==(const zip_iterator & other) const
{
if (m_head_iterator == other.m_head_iterator) {
return true;
}
return m_tail_iterator == other.m_tail_iterator;
}
bool operator<(const zip_iterator & other) const
{
if (m_head_iterator < other.m_head_iterator) {
return m_tail_iterator < other.m_tail_iterator;
}
return false;
}
bool operator!=(const zip_iterator & other) const
{
return !(*this == other);
}
private:
// remove refrence to make it store the data internally
IteratorType m_head_iterator;
zip_iterator<_Iterables...> m_tail_iterator;
};
template<>
class zip_iterator<> : public std::iterator < std::random_access_iterator_tag, std::tuple<> >
{
// TODO implement every possible iterator property
public:
zip_iterator<> & operator++() {
return *this;
}
zip_iterator<> & operator++(int) {
return *this;
}
std::tuple<> operator*() const
{
return std::tuple<>();
}
std::tuple<> * operator->()
{
static std::tuple<> empty;
return ∅
}
bool operator==(const zip_iterator<> & other) const
{
return false;
}
bool operator!=(const zip_iterator<> & other) const
{
return !(*this == other);
}
bool operator<(const zip_iterator<> & other) const
{
return true;
}
};
template<typename... Iterables>
zip_iterator<Iterables...> zip_iterators(Iterables&&... iters)
{
return zip_iterator<Iterables...>(std::forward<Iterables>(iters)...);
}
}