1 | // Boost.Geometry Index |
2 | // |
3 | // Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland. |
4 | // |
5 | // Use, modification and distribution is subject to the Boost Software License, |
6 | // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
7 | // http://www.boost.org/LICENSE_1_0.txt) |
8 | |
9 | #ifndef BOOST_GEOMETRY_INDEX_DETAIL_TUPLES_HPP |
10 | #define BOOST_GEOMETRY_INDEX_DETAIL_TUPLES_HPP |
11 | |
12 | #include <boost/tuple/tuple.hpp> |
13 | #include <boost/type_traits/is_same.hpp> |
14 | |
15 | // TODO move this to index/tuples and separate algorithms |
16 | |
17 | namespace boost { namespace geometry { namespace index { namespace detail { |
18 | |
19 | namespace tuples { |
20 | |
21 | // find_index |
22 | |
23 | namespace detail { |
24 | |
25 | template <typename Tuple, typename El, size_t N> |
26 | struct find_index; |
27 | |
28 | template <typename Tuple, typename El, size_t N, typename CurrentEl> |
29 | struct find_index_impl |
30 | { |
31 | static const size_t value = find_index<Tuple, El, N - 1>::value; |
32 | }; |
33 | |
34 | template <typename Tuple, typename El, size_t N> |
35 | struct find_index_impl<Tuple, El, N, El> |
36 | { |
37 | static const size_t value = N - 1; |
38 | }; |
39 | |
40 | template <typename Tuple, typename El, typename CurrentEl> |
41 | struct find_index_impl<Tuple, El, 1, CurrentEl> |
42 | { |
43 | BOOST_MPL_ASSERT_MSG( |
44 | (false), |
45 | ELEMENT_NOT_FOUND, |
46 | (find_index_impl)); |
47 | }; |
48 | |
49 | template <typename Tuple, typename El> |
50 | struct find_index_impl<Tuple, El, 1, El> |
51 | { |
52 | static const size_t value = 0; |
53 | }; |
54 | |
55 | template <typename Tuple, typename El, size_t N> |
56 | struct find_index |
57 | { |
58 | static const size_t value = |
59 | find_index_impl< |
60 | Tuple, |
61 | El, |
62 | N, |
63 | typename boost::tuples::element<N - 1, Tuple>::type |
64 | >::value; |
65 | }; |
66 | |
67 | } // namespace detail |
68 | |
69 | template <typename Tuple, typename El> |
70 | struct find_index |
71 | { |
72 | static const size_t value = |
73 | detail::find_index< |
74 | Tuple, |
75 | El, |
76 | boost::tuples::length<Tuple>::value |
77 | >::value; |
78 | }; |
79 | |
80 | // has |
81 | |
82 | namespace detail { |
83 | |
84 | template <typename Tuple, typename El, size_t N> |
85 | struct has |
86 | { |
87 | static const bool value |
88 | = boost::is_same< |
89 | typename boost::tuples::element<N - 1, Tuple>::type, |
90 | El |
91 | >::value |
92 | || has<Tuple, El, N - 1>::value; |
93 | }; |
94 | |
95 | template <typename Tuple, typename El> |
96 | struct has<Tuple, El, 1> |
97 | { |
98 | static const bool value |
99 | = boost::is_same< |
100 | typename boost::tuples::element<0, Tuple>::type, |
101 | El |
102 | >::value; |
103 | }; |
104 | |
105 | } // namespace detail |
106 | |
107 | template <typename Tuple, typename El> |
108 | struct has |
109 | { |
110 | static const bool value |
111 | = detail::has< |
112 | Tuple, |
113 | El, |
114 | boost::tuples::length<Tuple>::value |
115 | >::value; |
116 | }; |
117 | |
118 | // add |
119 | |
120 | template <typename Tuple, typename El> |
121 | struct add |
122 | { |
123 | BOOST_MPL_ASSERT_MSG( |
124 | (false), |
125 | NOT_IMPLEMENTED_FOR_THIS_TUPLE_TYPE, |
126 | (add)); |
127 | }; |
128 | |
129 | template <typename T1, typename T> |
130 | struct add<boost::tuple<T1>, T> |
131 | { |
132 | typedef boost::tuple<T1, T> type; |
133 | }; |
134 | |
135 | template <typename T1, typename T2, typename T> |
136 | struct add<boost::tuple<T1, T2>, T> |
137 | { |
138 | typedef boost::tuple<T1, T2, T> type; |
139 | }; |
140 | |
141 | // add_if |
142 | |
143 | template <typename Tuple, typename El, bool Cond> |
144 | struct add_if |
145 | { |
146 | typedef Tuple type; |
147 | }; |
148 | |
149 | template <typename Tuple, typename El> |
150 | struct add_if<Tuple, El, true> |
151 | { |
152 | typedef typename add<Tuple, El>::type type; |
153 | }; |
154 | |
155 | // add_unique |
156 | |
157 | template <typename Tuple, typename El> |
158 | struct add_unique |
159 | { |
160 | typedef typename add_if< |
161 | Tuple, |
162 | El, |
163 | !has<Tuple, El>::value |
164 | >::type type; |
165 | }; |
166 | |
167 | template <typename Tuple, |
168 | typename T, |
169 | size_t I = 0, |
170 | size_t N = boost::tuples::length<Tuple>::value> |
171 | struct push_back |
172 | { |
173 | typedef |
174 | boost::tuples::cons< |
175 | typename boost::tuples::element<I, Tuple>::type, |
176 | typename push_back<Tuple, T, I+1, N>::type |
177 | > type; |
178 | |
179 | static type apply(Tuple const& tup, T const& t) |
180 | { |
181 | return |
182 | type( |
183 | boost::get<I>(tup), |
184 | push_back<Tuple, T, I+1, N>::apply(tup, t) |
185 | ); |
186 | } |
187 | }; |
188 | |
189 | template <typename Tuple, typename T, size_t N> |
190 | struct push_back<Tuple, T, N, N> |
191 | { |
192 | typedef boost::tuples::cons<T, boost::tuples::null_type> type; |
193 | |
194 | static type apply(Tuple const&, T const& t) |
195 | { |
196 | return type(t, boost::tuples::null_type()); |
197 | } |
198 | }; |
199 | |
200 | } // namespace tuples |
201 | |
202 | }}}} // namespace boost::geometry::index::detail |
203 | |
204 | #endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_TAGS_HPP |
205 | |