1 // Boost.Geometry Index
3 // R-tree nodes based on Boost.Variant, storing dynamic-size containers
5 // Copyright (c) 2011-2014 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_NODE_VARIANT_DYNAMIC_HPP
12 #define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_VARIANT_DYNAMIC_HPP
14 namespace boost { namespace geometry { namespace index {
16 namespace detail { namespace rtree {
18 // nodes default types
20 template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
21 struct variant_internal_node
23 typedef boost::container::vector
25 rtree::ptr_pair<Box, typename Allocators::node_pointer>,
26 typename Allocators::node_allocator_type::template rebind
28 rtree::ptr_pair<Box, typename Allocators::node_pointer>
32 template <typename Al>
33 inline variant_internal_node(Al const& al)
37 elements_type elements;
40 template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
43 typedef boost::container::vector
46 typename Allocators::node_allocator_type::template rebind
52 template <typename Al>
53 inline variant_leaf(Al const& al)
57 elements_type elements;
62 template <typename Value, typename Parameters, typename Box, typename Allocators>
63 struct node<Value, Parameters, Box, Allocators, node_variant_dynamic_tag>
65 typedef boost::variant<
66 variant_leaf<Value, Parameters, Box, Allocators, node_variant_dynamic_tag>,
67 variant_internal_node<Value, Parameters, Box, Allocators, node_variant_dynamic_tag>
71 template <typename Value, typename Parameters, typename Box, typename Allocators>
72 struct internal_node<Value, Parameters, Box, Allocators, node_variant_dynamic_tag>
74 typedef variant_internal_node<Value, Parameters, Box, Allocators, node_variant_dynamic_tag> type;
77 template <typename Value, typename Parameters, typename Box, typename Allocators>
78 struct leaf<Value, Parameters, Box, Allocators, node_variant_dynamic_tag>
80 typedef variant_leaf<Value, Parameters, Box, Allocators, node_variant_dynamic_tag> type;
85 template <typename Value, typename Parameters, typename Box, typename Allocators, bool IsVisitableConst>
86 struct visitor<Value, Parameters, Box, Allocators, node_variant_dynamic_tag, IsVisitableConst>
88 typedef static_visitor<> type;
93 template <typename Allocator, typename Value, typename Parameters, typename Box>
94 class allocators<Allocator, Value, Parameters, Box, node_variant_dynamic_tag>
95 : public Allocator::template rebind<
97 Value, Parameters, Box,
98 allocators<Allocator, Value, Parameters, Box, node_variant_dynamic_tag>,
99 node_variant_dynamic_tag
103 typedef typename Allocator::template rebind<
105 >::other value_allocator_type;
108 typedef Allocator allocator_type;
110 typedef Value value_type;
111 typedef typename value_allocator_type::reference reference;
112 typedef typename value_allocator_type::const_reference const_reference;
113 typedef typename value_allocator_type::size_type size_type;
114 typedef typename value_allocator_type::difference_type difference_type;
115 typedef typename value_allocator_type::pointer pointer;
116 typedef typename value_allocator_type::const_pointer const_pointer;
118 typedef typename Allocator::template rebind<
119 typename node<Value, Parameters, Box, allocators, node_variant_dynamic_tag>::type
120 >::other::pointer node_pointer;
122 typedef typename Allocator::template rebind<
123 typename node<Value, Parameters, Box, allocators, node_variant_dynamic_tag>::type
124 >::other node_allocator_type;
127 : node_allocator_type()
130 template <typename Alloc>
131 inline explicit allocators(Alloc const& alloc)
132 : node_allocator_type(alloc)
135 inline allocators(BOOST_FWD_REF(allocators) a)
136 : node_allocator_type(boost::move(a.node_allocator()))
139 inline allocators & operator=(BOOST_FWD_REF(allocators) a)
141 node_allocator() = boost::move(a.node_allocator());
145 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
146 inline allocators & operator=(allocators const& a)
148 node_allocator() = a.node_allocator();
153 void swap(allocators & a)
155 boost::swap(node_allocator(), a.node_allocator());
158 bool operator==(allocators const& a) const { return node_allocator() == a.node_allocator(); }
159 template <typename Alloc>
160 bool operator==(Alloc const& a) const { return node_allocator() == node_allocator_type(a); }
162 Allocator allocator() const { return Allocator(node_allocator()); }
164 node_allocator_type & node_allocator() { return *this; }
165 node_allocator_type const& node_allocator() const { return *this; }
168 // create_node_variant
170 template <typename VariantPtr, typename Node>
171 struct create_variant_node
173 template <typename AllocNode>
174 static inline VariantPtr apply(AllocNode & alloc_node)
176 typedef boost::container::allocator_traits<AllocNode> Al;
177 typedef typename Al::pointer P;
179 P p = Al::allocate(alloc_node, 1);
182 throw_runtime_error("boost::geometry::index::rtree node creation failed");
184 scoped_deallocator<AllocNode> deallocator(p, alloc_node);
186 Al::construct(alloc_node, boost::addressof(*p), Node(alloc_node)); // implicit cast to Variant
188 deallocator.release();
193 // destroy_node_variant
195 template <typename Node>
196 struct destroy_variant_node
198 template <typename AllocNode, typename VariantPtr>
199 static inline void apply(AllocNode & alloc_node, VariantPtr n)
201 typedef boost::container::allocator_traits<AllocNode> Al;
203 Al::destroy(alloc_node, boost::addressof(*n));
204 Al::deallocate(alloc_node, n, 1);
210 template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>
213 variant_internal_node<Value, Parameters, Box, Allocators, Tag>
216 static inline typename Allocators::node_pointer
217 apply(Allocators & allocators)
219 return create_variant_node<
220 typename Allocators::node_pointer,
221 variant_internal_node<Value, Parameters, Box, Allocators, Tag>
222 >::apply(allocators.node_allocator());
226 template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>
229 variant_leaf<Value, Parameters, Box, Allocators, Tag>
232 static inline typename Allocators::node_pointer
233 apply(Allocators & allocators)
235 return create_variant_node<
236 typename Allocators::node_pointer,
237 variant_leaf<Value, Parameters, Box, Allocators, Tag>
238 >::apply(allocators.node_allocator());
244 template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>
247 variant_internal_node<Value, Parameters, Box, Allocators, Tag>
250 static inline void apply(Allocators & allocators, typename Allocators::node_pointer n)
252 destroy_variant_node<
253 variant_internal_node<Value, Parameters, Box, Allocators, Tag>
254 >::apply(allocators.node_allocator(), n);
258 template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>
261 variant_leaf<Value, Parameters, Box, Allocators, Tag>
264 static inline void apply(Allocators & allocators, typename Allocators::node_pointer n)
266 destroy_variant_node<
267 variant_leaf<Value, Parameters, Box, Allocators, Tag>
268 >::apply(allocators.node_allocator(), n);
272 }} // namespace detail::rtree
274 }}} // namespace boost::geometry::index
276 #endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_VARIANT_DYNAMIC_HPP