1 // Boost.Geometry Index
3 // R-tree query iterators
5 // Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
7 // Use, modification and distribution is subject to the Boost Software License,
8 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
11 #ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUERY_ITERATORS_HPP
12 #define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUERY_ITERATORS_HPP
14 #define BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_VIRTUAL
15 //#define BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_FUNCTION
16 //#define BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_TYPE_ERASURE
17 //#define BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE
19 namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace iterators {
21 template <typename Value, typename Allocators>
22 struct end_query_iterator
24 typedef std::input_iterator_tag iterator_category;
25 typedef Value value_type;
26 typedef typename Allocators::const_reference reference;
27 typedef typename Allocators::difference_type difference_type;
28 typedef typename Allocators::const_pointer pointer;
30 reference operator*() const
32 BOOST_ASSERT_MSG(false, "iterator not dereferencable");
37 const value_type * operator->() const
39 BOOST_ASSERT_MSG(false, "iterator not dereferencable");
40 const value_type * p = 0;
44 end_query_iterator & operator++()
46 BOOST_ASSERT_MSG(false, "iterator not incrementable");
50 end_query_iterator operator++(int)
52 BOOST_ASSERT_MSG(false, "iterator not incrementable");
56 friend bool operator==(end_query_iterator const& /*l*/, end_query_iterator const& /*r*/)
62 template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename Predicates>
63 class spatial_query_iterator
65 typedef visitors::spatial_query_incremental<Value, Options, Translator, Box, Allocators, Predicates> visitor_type;
66 typedef typename visitor_type::node_pointer node_pointer;
69 typedef std::input_iterator_tag iterator_category;
70 typedef Value value_type;
71 typedef typename Allocators::const_reference reference;
72 typedef typename Allocators::difference_type difference_type;
73 typedef typename Allocators::const_pointer pointer;
75 inline spatial_query_iterator(Translator const& t, Predicates const& p)
79 inline spatial_query_iterator(node_pointer root, Translator const& t, Predicates const& p)
82 m_visitor.initialize(root);
85 reference operator*() const
87 return m_visitor.dereference();
90 const value_type * operator->() const
92 return boost::addressof(m_visitor.dereference());
95 spatial_query_iterator & operator++()
97 m_visitor.increment();
101 spatial_query_iterator operator++(int)
103 spatial_query_iterator temp = *this;
108 friend bool operator==(spatial_query_iterator const& l, spatial_query_iterator const& r)
110 return l.m_visitor == r.m_visitor;
113 friend bool operator==(spatial_query_iterator const& l, end_query_iterator<Value, Allocators> const& /*r*/)
115 return l.m_visitor.is_end();
118 friend bool operator==(end_query_iterator<Value, Allocators> const& /*l*/, spatial_query_iterator const& r)
120 return r.m_visitor.is_end();
124 visitor_type m_visitor;
127 template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename Predicates, unsigned NearestPredicateIndex>
128 class distance_query_iterator
130 typedef visitors::distance_query_incremental<Value, Options, Translator, Box, Allocators, Predicates, NearestPredicateIndex> visitor_type;
131 typedef typename visitor_type::node_pointer node_pointer;
134 typedef std::input_iterator_tag iterator_category;
135 typedef Value value_type;
136 typedef typename Allocators::const_reference reference;
137 typedef typename Allocators::difference_type difference_type;
138 typedef typename Allocators::const_pointer pointer;
140 inline distance_query_iterator(Translator const& t, Predicates const& p)
144 inline distance_query_iterator(node_pointer root, Translator const& t, Predicates const& p)
147 m_visitor.initialize(root);
150 reference operator*() const
152 return m_visitor.dereference();
155 const value_type * operator->() const
157 return boost::addressof(m_visitor.dereference());
160 distance_query_iterator & operator++()
162 m_visitor.increment();
166 distance_query_iterator operator++(int)
168 distance_query_iterator temp = *this;
173 friend bool operator==(distance_query_iterator const& l, distance_query_iterator const& r)
175 return l.m_visitor == r.m_visitor;
178 friend bool operator==(distance_query_iterator const& l, end_query_iterator<Value, Allocators> const& /*r*/)
180 return l.m_visitor.is_end();
183 friend bool operator==(end_query_iterator<Value, Allocators> const& /*l*/, distance_query_iterator const& r)
185 return r.m_visitor.is_end();
189 visitor_type m_visitor;
192 template <typename L, typename R>
193 inline bool operator!=(L const& l, R const& r)
198 }}}}}} // namespace boost::geometry::index::detail::rtree::iterators
200 #if defined(BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_VIRTUAL) || defined(BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_FUNCTION)
202 #if defined(BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_VIRTUAL)
204 namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace iterators {
206 template <typename Value, typename Allocators>
207 class query_iterator_base
210 typedef std::input_iterator_tag iterator_category;
211 typedef Value value_type;
212 typedef typename Allocators::const_reference reference;
213 typedef typename Allocators::difference_type difference_type;
214 typedef typename Allocators::const_pointer pointer;
216 virtual ~query_iterator_base() {}
218 virtual query_iterator_base * clone() const = 0;
220 virtual bool is_end() const = 0;
221 virtual reference dereference() const = 0;
222 virtual void increment() = 0;
223 virtual bool equals(query_iterator_base const&) const = 0;
226 template <typename Value, typename Allocators, typename Iterator>
227 class query_iterator_wrapper
228 : public query_iterator_base<Value, Allocators>
230 typedef query_iterator_base<Value, Allocators> base_t;
233 typedef std::input_iterator_tag iterator_category;
234 typedef Value value_type;
235 typedef typename Allocators::const_reference reference;
236 typedef typename Allocators::difference_type difference_type;
237 typedef typename Allocators::const_pointer pointer;
239 explicit query_iterator_wrapper(Iterator const& it) : m_iterator(it) {}
241 virtual base_t * clone() const { return new query_iterator_wrapper(m_iterator); }
243 virtual bool is_end() const { return m_iterator == end_query_iterator<Value, Allocators>(); }
244 virtual reference dereference() const { return *m_iterator; }
245 virtual void increment() { ++m_iterator; }
246 virtual bool equals(base_t const& r) const
248 const query_iterator_wrapper * p = dynamic_cast<const query_iterator_wrapper *>(boost::addressof(r));
249 BOOST_ASSERT_MSG(p, "those iterators can't be compared");
250 return m_iterator == p->m_iterator;
257 #elif defined(BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_FUNCTION)
259 #include <boost/function.hpp>
260 #include <boost/bind.hpp>
262 namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace iterators {
264 template <typename Value, typename Allocators>
265 class query_iterator_base
268 typedef std::input_iterator_tag iterator_category;
269 typedef Value value_type;
270 typedef typename Allocators::const_reference reference;
271 typedef typename Allocators::difference_type difference_type;
272 typedef typename Allocators::const_pointer pointer;
274 virtual ~query_iterator_base() {}
276 boost::function<query_iterator_base*()> clone;
277 boost::function<bool()> is_end;
278 boost::function<reference()> dereference;
279 boost::function<void()> increment;
280 boost::function<bool(query_iterator_base const&)> equals;
283 template <typename Value, typename Allocators, typename Iterator>
284 class query_iterator_wrapper
285 : public query_iterator_base<Value, Allocators>
287 typedef query_iterator_base<Value, Allocators> base_t;
290 typedef std::input_iterator_tag iterator_category;
291 typedef Value value_type;
292 typedef typename Allocators::const_reference reference;
293 typedef typename Allocators::difference_type difference_type;
294 typedef typename Allocators::const_pointer pointer;
296 explicit query_iterator_wrapper(Iterator const& it)
299 base_t::clone = boost::bind(&query_iterator_wrapper::clone_, this);
300 base_t::is_end = boost::bind(&query_iterator_wrapper::is_end_, this);
301 base_t::dereference = boost::bind(&query_iterator_wrapper::dereference_, this);
302 base_t::increment = boost::bind(&query_iterator_wrapper::increment_, this);
303 base_t::equals = boost::bind(&query_iterator_wrapper::equals_, this, _1);
307 base_t * clone_() const { return new query_iterator_wrapper(m_iterator); }
309 bool is_end_() const { return m_iterator == end_query_iterator<Value, Allocators>(); }
310 reference dereference_() const { return *m_iterator; }
311 void increment_() { ++m_iterator; }
312 bool equals_(base_t const& r) const
314 const query_iterator_wrapper * p = dynamic_cast<const query_iterator_wrapper *>(boost::addressof(r));
315 BOOST_ASSERT_MSG(p, "those iterators can't be compared");
316 return m_iterator == p->m_iterator;
325 template <typename Value, typename Allocators>
328 typedef query_iterator_base<Value, Allocators> iterator_base;
329 typedef std::auto_ptr<iterator_base> iterator_ptr;
332 typedef std::input_iterator_tag iterator_category;
333 typedef Value value_type;
334 typedef typename Allocators::const_reference reference;
335 typedef typename Allocators::difference_type difference_type;
336 typedef typename Allocators::const_pointer pointer;
340 template <typename It>
341 query_iterator(It const& it)
342 : m_ptr(static_cast<iterator_base*>(
343 new query_iterator_wrapper<Value, Allocators, It>(it) ))
346 query_iterator(end_query_iterator<Value, Allocators> const& /*it*/)
349 query_iterator(query_iterator const& o)
350 : m_ptr(o.m_ptr.get() ? o.m_ptr->clone() : 0)
353 #ifndef BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE
354 query_iterator & operator=(query_iterator const& o)
356 m_ptr.reset(o.m_ptr.get() ? o.m_ptr->clone() : 0);
359 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
360 query_iterator(query_iterator && o)
361 : m_ptr(o.m_ptr.get())
365 query_iterator & operator=(query_iterator && o)
367 if ( this != boost::addressof(o) )
369 m_ptr.reset(o.m_ptr.get());
375 #else // !BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE
377 BOOST_COPYABLE_AND_MOVABLE(query_iterator)
379 query_iterator & operator=(BOOST_COPY_ASSIGN_REF(query_iterator) o)
381 m_ptr.reset(o.m_ptr.get() ? o.m_ptr->clone() : 0);
384 query_iterator(BOOST_RV_REF(query_iterator) o)
385 : m_ptr(o.m_ptr.get())
389 query_iterator & operator=(BOOST_RV_REF(query_iterator) o)
391 if ( this != boost::addressof(o) )
393 m_ptr.reset(o.m_ptr.get());
398 #endif // BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE
400 reference operator*() const
402 return m_ptr->dereference();
405 const value_type * operator->() const
407 return boost::addressof(m_ptr->dereference());
410 query_iterator & operator++()
416 query_iterator operator++(int)
418 query_iterator temp = *this;
423 friend bool operator==(query_iterator const& l, query_iterator const& r)
428 return l.m_ptr->equals(*r.m_ptr);
430 return l.m_ptr->is_end();
435 return r.m_ptr->is_end();
445 }}}}}} // namespace boost::geometry::index::detail::rtree::iterators
447 #elif defined(BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_TYPE_ERASURE)
449 #include <boost/type_erasure/any.hpp>
450 #include <boost/type_erasure/operators.hpp>
451 #include <boost/type_erasure/is_empty.hpp>
453 namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace iterators {
455 template<typename T, typename Value, typename Allocators>
456 struct single_pass_iterator_concept :
457 ::boost::mpl::vector<
458 ::boost::type_erasure::copy_constructible<T>,
459 ::boost::type_erasure::equality_comparable<T>,
460 ::boost::type_erasure::dereferenceable<typename Allocators::const_reference, T>,
461 ::boost::type_erasure::assignable<T>,
462 ::boost::type_erasure::incrementable<T>,
463 ::boost::type_erasure::equality_comparable<T, end_query_iterator<Value, Allocators> >,
464 ::boost::type_erasure::relaxed // default ctor
468 template <typename Value, typename Allocators>
469 struct single_pass_iterator_type
471 typedef ::boost::type_erasure::any<
472 single_pass_iterator_concept<
473 ::boost::type_erasure::_self, Value, Allocators
478 }}}}}} // namespace boost::geometry::index::detail::rtree::iterators
480 namespace boost { namespace type_erasure {
482 template<typename T, typename Value, typename Allocators, typename Base>
483 struct concept_interface<
484 ::boost::geometry::index::detail::rtree::single_pass_iterator_concept<
489 typedef Value value_type;
490 typedef typename Allocators::const_reference reference;
491 typedef typename Allocators::const_pointer pointer;
492 typedef typename Allocators::difference_type difference_type;
493 typedef ::std::input_iterator_tag iterator_category;
496 }} // boost::type_erasure
498 namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace iterators {
500 template <typename Value, typename Allocators>
504 typedef std::input_iterator_tag iterator_category;
505 typedef Value value_type;
506 typedef typename Allocators::const_reference reference;
507 typedef typename Allocators::difference_type difference_type;
508 typedef typename Allocators::const_pointer pointer;
511 typedef typename rtree::single_pass_iterator_type<Value, Allocators>::type iterator_type;
517 template <typename It>
518 query_iterator(It const& it)
522 query_iterator(end_query_iterator<Value, Allocators> const& /*it*/)
525 #ifdef BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE
527 BOOST_COPYABLE_AND_MOVABLE(query_iterator)
529 query_iterator(query_iterator const& o)
530 : m_iterator(o.m_iterator)
532 query_iterator & operator=(BOOST_COPY_ASSIGN_REF(query_iterator) o)
534 m_iterator = o.m_iterator;
537 query_iterator(BOOST_RV_REF(query_iterator) o)
538 : m_iterator(boost::move(o.m_iterator))
540 query_iterator & operator=(BOOST_RV_REF(query_iterator) o)
542 if ( this != boost::addressof(o) )
544 m_iterator = boost::move(o.m_iterator);
548 #endif // BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE
550 reference operator*() const
555 const value_type * operator->() const
557 return boost::addressof(*m_iterator);
560 query_iterator & operator++()
566 query_iterator operator++(int)
568 query_iterator temp = *this;
573 friend bool operator==(query_iterator const& l, query_iterator const& r)
575 if ( !::boost::type_erasure::is_empty(l.m_iterator) )
577 if ( !::boost::type_erasure::is_empty(r.m_iterator) )
578 return l.m_iterator == r.m_iterator;
580 return l.m_iterator == end_query_iterator<Value, Allocators>();
584 if ( !::boost::type_erasure::is_empty(r.m_iterator) )
585 return r.m_iterator == end_query_iterator<Value, Allocators>();
592 iterator_type m_iterator;
595 }}}}}} // namespace boost::geometry::index::detail::rtree::iterators
597 #endif // BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_TYPE_ERASURE
599 #endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUERY_ITERATORS_HPP