-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathzip_range_02.cpp
110 lines (94 loc) · 2.82 KB
/
zip_range_02.cpp
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
#include <iostream>
#include <utility>
#include <vector>
#include <tuple>
/*
If you like operator overloading, here are three possibilities. The first two are using std::pair<> and std::tuple<>,
respectively, as iterators; the third extends this to range-based for. Note that not everyone will like these definitions of
the operators, so it's best to keep them in a separate namespace and have a using namespace in the functions (not files!)
where you'd like to use these.
*/
// put these in namespaces so we don't pollute global
namespace pair_iterators
{
template<typename T1, typename T2>
std::pair<T1, T2> operator++(std::pair<T1, T2>& it)
{
++it.first;
++it.second;
return it;
}
}
namespace tuple_iterators
{
// you might want to make this generic (via param pack)
template<typename T1, typename T2, typename T3>
auto operator++(std::tuple<T1, T2, T3>& it)
{
++(std::get<0>(it));
++(std::get<1>(it));
++(std::get<2>(it));
return it;
}
template<typename T1, typename T2, typename T3>
auto operator*(const std::tuple<T1, T2, T3>& it)
{
return std::tie(*(std::get<0>(it)),
*(std::get<1>(it)),
*(std::get<2>(it)));
}
// needed due to ADL-only lookup
template<typename... Args>
struct tuple_c
{
std::tuple<Args...> containers;
};
template<typename... Args>
auto tie_c(const Args&... args)
{
tuple_c<Args...> ret = { std::tie(args...) };
return ret;
}
template<typename T1, typename T2, typename T3>
auto begin(const tuple_c<T1, T2, T3>& c)
{
return std::make_tuple(std::get<0>(c.containers).begin(),
std::get<1>(c.containers).begin(),
std::get<2>(c.containers).begin());
}
template<typename T1, typename T2, typename T3>
auto end(const tuple_c<T1, T2, T3>& c)
{
return std::make_tuple(std::get<0>(c.containers).end(),
std::get<1>(c.containers).end(),
std::get<2>(c.containers).end());
}
// implement cbegin(), cend() as needed
}
int main()
{
using namespace pair_iterators;
using namespace tuple_iterators;
std::vector<double> ds = { 0.0, 0.1, 0.2 };
std::vector<int > is = { 1, 2, 3 };
std::vector<char > cs = { 'a', 'b', 'c' };
// classical, iterator-style using pairs
for (auto its = std::make_pair(ds.begin(), is.begin()),
end = std::make_pair(ds.end(), is.end()); its != end; ++its)
{
std::cout << "1. " << *(its.first) + *(its.second) << " " << std::endl;
}
// classical, iterator-style using tuples
for (auto its = std::make_tuple(ds.begin(), is.begin(), cs.begin()),
end = std::make_tuple(ds.end(), is.end(), cs.end()); its != end; ++its)
{
std::cout << "2. " << *(std::get<0>(its)) + *(std::get<1>(its)) << " "
<< *(std::get<2>(its)) << " " << std::endl;
}
// range for using tuples
for (const auto& d_i_c : tie_c(ds, is, cs))
{
std::cout << "3. " << std::get<0>(d_i_c) + std::get<1>(d_i_c) << " "
<< std::get<2>(d_i_c) << " " << std::endl;
}
}