• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Boost.Geometry Index
2 //
3 // Copyright (c) 2011-2019 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_INDEXABLE_HPP
10 #define BOOST_GEOMETRY_INDEX_INDEXABLE_HPP
11 
12 #include <boost/mpl/assert.hpp>
13 #include <boost/tuple/tuple.hpp>
14 #include <boost/type_traits/is_reference.hpp>
15 #include <boost/type_traits/is_same.hpp>
16 #include <boost/type_traits/remove_const.hpp>
17 #include <boost/type_traits/remove_reference.hpp>
18 
19 #include <boost/geometry/index/detail/is_indexable.hpp>
20 
21 namespace boost { namespace geometry { namespace index { namespace detail {
22 
23 template <typename T>
24 struct remove_cr
25     : boost::remove_const
26         <
27             typename boost::remove_reference<T>::type
28         >
29 {};
30 
31 template <typename From, typename To>
32 struct is_referencable
33     : boost::is_same
34         <
35             typename remove_cr<From>::type,
36             typename remove_cr<To>::type
37         >
38 {};
39 
40 template <typename Indexable, typename V>
indexable_prevent_any_type(V const &)41 inline Indexable const& indexable_prevent_any_type(V const& )
42 {
43     BOOST_MPL_ASSERT_MSG(
44         (false),
45         UNEXPECTED_TYPE,
46         (V)
47     );
48     return Indexable();
49 }
50 
51 /*!
52 \brief The function object extracting Indexable from Value.
53 
54 It translates Value object to Indexable object. The default version handles Values which are Indexables.
55 This template is also specialized for std::pair<Indexable, T2>, boost::tuple<Indexable, ...>
56 and std::tuple<Indexable, ...>.
57 
58 \tparam Value       The Value type which may be translated directly to the Indexable.
59 \tparam IsIndexable If true, the const reference to Value is returned.
60 */
61 template <typename Value, bool IsIndexable = is_indexable<Value>::value>
62 struct indexable
63 {
64     BOOST_MPL_ASSERT_MSG(
65         (detail::is_indexable<Value>::value),
66         NOT_VALID_INDEXABLE_TYPE,
67         (Value)
68     );
69 
70     /*! \brief The type of result returned by function object. */
71     typedef Value const& result_type;
72 
73     /*!
74     \brief Return indexable extracted from the value.
75 
76     \param v The value.
77     \return The indexable.
78     */
operator ()boost::geometry::index::detail::indexable79     inline result_type operator()(Value const& v) const
80     {
81         return v;
82     }
83 
84     /*!
85     \brief Prevent reference to temporary for types convertible to Value.
86     */
87     template <typename V>
operator ()boost::geometry::index::detail::indexable88     inline result_type operator()(V const& v) const
89     {
90         return indexable_prevent_any_type<Value>(v);
91     }
92 };
93 
94 /*!
95 \brief The function object extracting Indexable from Value.
96 
97 This specialization translates from std::pair<Indexable, T2>.
98 
99 \tparam Indexable       The Indexable type.
100 \tparam Second          The second type.
101 */
102 template <typename Indexable, typename Second>
103 struct indexable<std::pair<Indexable, Second>, false>
104 {
105     typedef std::pair<Indexable, Second> value_type;
106 
107     BOOST_MPL_ASSERT_MSG(
108         (detail::is_indexable<Indexable>::value),
109         NOT_VALID_INDEXABLE_TYPE,
110         (Indexable)
111     );
112 
113     /*! \brief The type of result returned by function object. */
114     typedef Indexable const& result_type;
115 
116     /*!
117     \brief Return indexable extracted from the value.
118 
119     \param v The value.
120     \return The indexable.
121     */
operator ()boost::geometry::index::detail::indexable122     inline result_type operator()(value_type const& v) const
123     {
124         return v.first;
125     }
126 
127     /*!
128     \brief Return indexable extracted from compatible type different than value_type.
129 
130     \param v The value.
131     \return The indexable.
132     */
133     template <typename I, typename S>
operator ()boost::geometry::index::detail::indexable134     inline result_type operator()(std::pair<I, S> const& v) const
135     {
136         BOOST_MPL_ASSERT_MSG(
137             (is_referencable<I, result_type>::value),
138             UNEXPECTED_TYPE,
139             (std::pair<I, S>)
140         );
141         return v.first;
142     }
143 
144     /*!
145     \brief Prevent reference to temporary for types convertible to Value.
146     */
147     template <typename V>
operator ()boost::geometry::index::detail::indexable148     inline result_type operator()(V const& v) const
149     {
150         return indexable_prevent_any_type<Indexable>(v);
151     }
152 };
153 
154 /*!
155 \brief The function object extracting Indexable from Value.
156 
157 This specialization translates from boost::tuple<Indexable, ...>
158   or boost::tuples::cons<Indexable, ...>.
159 
160 \tparam Value       The Value type.
161 \tparam Indexable   The Indexable type.
162 */
163 template <typename Value, typename Indexable>
164 struct indexable_boost_tuple
165 {
166     typedef Value value_type;
167 
168     BOOST_MPL_ASSERT_MSG(
169         (detail::is_indexable<Indexable>::value),
170         NOT_VALID_INDEXABLE_TYPE,
171         (Indexable)
172         );
173 
174     /*! \brief The type of result returned by function object. */
175     typedef Indexable const& result_type;
176 
177     /*!
178     \brief Return indexable extracted from the value.
179 
180     \param v The value.
181     \return The indexable.
182     */
operator ()boost::geometry::index::detail::indexable_boost_tuple183     inline result_type operator()(value_type const& v) const
184     {
185         return boost::get<0>(v);
186     }
187 
188     /*!
189     \brief Return indexable extracted from compatible type different than value_type.
190 
191     \param v The value.
192     \return The indexable.
193     */
194     template <typename I, typename U1, typename U2, typename U3, typename U4,
195               typename U5, typename U6, typename U7, typename U8, typename U9>
operator ()boost::geometry::index::detail::indexable_boost_tuple196     inline result_type operator()(boost::tuple<I, U1, U2, U3, U4, U5, U6, U7, U8, U9> const& v) const
197     {
198         BOOST_MPL_ASSERT_MSG(
199             (is_referencable<I, result_type>::value),
200             UNEXPECTED_TYPE,
201             (boost::tuple<I, U1, U2, U3, U4, U5, U6, U7, U8, U9>)
202         );
203         return boost::get<0>(v);
204     }
205 
206     /*!
207     \brief Return indexable extracted from compatible type different than value_type.
208 
209     \param v The value.
210     \return The indexable.
211     */
212     template <typename I, typename T>
operator ()boost::geometry::index::detail::indexable_boost_tuple213     inline result_type operator()(boost::tuples::cons<I, T> const& v) const
214     {
215         BOOST_MPL_ASSERT_MSG(
216             (is_referencable<I, result_type>::value),
217             UNEXPECTED_TYPE,
218             (boost::tuples::cons<I, T>)
219         );
220         return boost::get<0>(v);
221     }
222 
223     /*!
224     \brief Prevent reference to temporary for types convertible to Value.
225     */
226     template <typename V>
operator ()boost::geometry::index::detail::indexable_boost_tuple227     inline result_type operator()(V const& v) const
228     {
229         return indexable_prevent_any_type<Indexable>(v);
230     }
231 };
232 
233 /*!
234 \brief The function object extracting Indexable from Value.
235 
236 This specialization translates from boost::tuple<Indexable, ...>.
237 
238 \tparam Indexable   The Indexable type.
239 */
240 template <typename Indexable, typename T1, typename T2, typename T3, typename T4,
241           typename T5, typename T6, typename T7, typename T8, typename T9>
242 struct indexable<boost::tuple<Indexable, T1, T2, T3, T4, T5, T6, T7, T8, T9>, false>
243     : indexable_boost_tuple
244         <
245             boost::tuple<Indexable, T1, T2, T3, T4, T5, T6, T7, T8, T9>,
246             Indexable
247         >
248 {};
249 
250 /*!
251 \brief The function object extracting Indexable from Value.
252 
253 This specialization translates from boost::tuples::cons<Indexable, ...>.
254 
255 \tparam Indexable   The Indexable type.
256 */
257 template <typename Indexable, typename Tail>
258 struct indexable<boost::tuples::cons<Indexable, Tail>, false>
259     : indexable_boost_tuple
260         <
261             boost::tuples::cons<Indexable, Tail>,
262             Indexable
263         >
264 {};
265 
266 }}}} // namespace boost::geometry::index::detail
267 
268 #if !defined(BOOST_NO_CXX11_HDR_TUPLE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
269 
270 #include <tuple>
271 
272 namespace boost { namespace geometry { namespace index { namespace detail {
273 
274 /*!
275 \brief The function object extracting Indexable from Value.
276 
277 This specialization translates from std::tuple<Indexable, Args...>.
278 It's defined if the compiler supports tuples and variadic templates.
279 
280 \tparam Indexable   The Indexable type.
281 */
282 template <typename Indexable, typename ...Args>
283 struct indexable<std::tuple<Indexable, Args...>, false>
284 {
285     typedef std::tuple<Indexable, Args...> value_type;
286 
287     BOOST_MPL_ASSERT_MSG(
288         (detail::is_indexable<Indexable>::value),
289         NOT_VALID_INDEXABLE_TYPE,
290         (Indexable)
291         );
292 
293     /*! \brief The type of result returned by function object. */
294     typedef Indexable const& result_type;
295 
296     /*!
297     \brief Return indexable extracted from the value.
298 
299     \param v The value.
300     \return The indexable.
301     */
operator ()boost::geometry::index::detail::indexable302     result_type operator()(value_type const& v) const
303     {
304         return std::get<0>(v);
305     }
306 
307     /*!
308     \brief Return indexable extracted from compatible type different than value_type.
309 
310     \param v The value.
311     \return The indexable.
312     */
313     template <typename I, typename ...A>
operator ()boost::geometry::index::detail::indexable314     inline result_type operator()(std::tuple<I, A...> const& v) const
315     {
316         BOOST_MPL_ASSERT_MSG(
317             (is_referencable<I, result_type>::value),
318             UNEXPECTED_TYPE,
319             (std::tuple<I, A...>)
320         );
321         return std::get<0>(v);
322     }
323 
324     /*!
325     \brief Prevent reference to temporary for types convertible to Value.
326     */
327     template <typename V>
operator ()boost::geometry::index::detail::indexable328     inline result_type operator()(V const& v) const
329     {
330         return indexable_prevent_any_type<Indexable>(v);
331     }
332 };
333 
334 }}}} // namespace boost::geometry::index::detail
335 
336 #endif // !defined(BOOST_NO_CXX11_HDR_TUPLE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
337 
338 namespace boost { namespace geometry { namespace index {
339 
340 /*!
341 \brief The function object extracting Indexable from Value.
342 
343 It translates Value object to Indexable object. By default, it can handle Values which are Indexables,
344 std::pair<Indexable, T2>, boost::tuple<Indexable, ...> and std::tuple<Indexable, ...> if STD tuples
345 and variadic templates are supported.
346 
347 \tparam Value       The Value type which may be translated directly to the Indexable.
348 */
349 template <typename Value>
350 struct indexable
351     : detail::indexable<Value>
352 {
353     /*! \brief The type of result returned by function object. It should be const Indexable reference. */
354     typedef typename detail::indexable<Value>::result_type result_type;
355 
356     /*!
357     \brief Return indexable extracted from the value.
358 
359     \param v The value.
360     \return The indexable.
361     */
operator ()boost::geometry::index::indexable362     inline result_type operator()(Value const& v) const
363     {
364         return detail::indexable<Value>::operator()(v);
365     }
366 
367     /*!
368     \brief Return indexable extracted from the value. Overload for types
369            compatible with Value but different yet holding referencable
370            Indexable, e.g. tuple containing a reference.
371 
372     \param v The value.
373     \return The indexable.
374     */
375     template <typename V>
operator ()boost::geometry::index::indexable376     inline result_type operator()(V const& v) const
377     {
378         return detail::indexable<Value>::operator()(v);
379     }
380 };
381 
382 }}} // namespace boost::geometry::index
383 
384 #endif // BOOST_GEOMETRY_INDEX_INDEXABLE_HPP
385