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 
applyboost::geometry::index::detail::tuples::push_back179     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 
applyboost::geometry::index::detail::tuples::push_back194     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