1// Boost.Bimap
2//
3// Copyright (c) 2006-2007 Matias Capeletto
4//
5// Distributed under the Boost Software License, Version 1.0.
6// (See accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8
9/// \file detail/bimap_core.hpp
10/// \brief Bimap base definition.
11
12#ifndef BOOST_BIMAP_DETAIL_BIMAP_CORE_HPP
13#define BOOST_BIMAP_DETAIL_BIMAP_CORE_HPP
14
15#if defined(_MSC_VER)
16#pragma once
17#endif
18
19#include <boost/config.hpp>
20
21#include <boost/mpl/placeholders.hpp>
22#include <boost/mpl/push_front.hpp>
23#include <boost/mpl/if.hpp>
24#include <boost/mpl/and.hpp>
25#include <boost/mpl/not.hpp>
26#include <boost/mpl/vector.hpp>
27
28#include <boost/type_traits/add_const.hpp>
29#include <boost/type_traits/is_same.hpp>
30
31#include <boost/concept_check.hpp>
32
33// Boost.MultiIndex
34#include <boost/multi_index_container.hpp>
35#include <boost/multi_index/member.hpp>
36
37// Boost.Bimap
38#include <boost/bimap/relation/mutant_relation.hpp>
39#include <boost/bimap/relation/member_at.hpp>
40#include <boost/bimap/relation/support/data_extractor.hpp>
41#include <boost/bimap/tags/support/default_tagged.hpp>
42#include <boost/bimap/tags/tagged.hpp>
43#include <boost/bimap/detail/manage_bimap_key.hpp>
44#include <boost/bimap/detail/manage_additional_parameters.hpp>
45#include <boost/bimap/detail/map_view_iterator.hpp>
46#include <boost/bimap/detail/set_view_iterator.hpp>
47
48#include <boost/bimap/set_of.hpp>
49#include <boost/bimap/unconstrained_set_of.hpp>
50#include <boost/core/allocator_access.hpp>
51
52namespace boost {
53namespace bimaps {
54
55/// \brief Library details
56
57namespace detail {
58
59#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
60
61template< class Type >
62struct get_value_type
63{
64 typedef BOOST_DEDUCED_TYPENAME Type::value_type type;
65};
66
67struct independent_index_tag {};
68
69#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES
70
71
72/// \brief Base for the bimap class.
73/**
74
75
76See also bimap.
77 **/
78
79
80template< class LeftSetType, class RightSetType, class AP1, class AP2, class AP3 >
81class bimap_core
82{
83 // Manage bimap key instantiation
84 // --------------------------------------------------------------------
85 public:
86
87 typedef BOOST_DEDUCED_TYPENAME manage_bimap_key
88 <
89 LeftSetType
90
91 >::type left_set_type;
92
93 typedef BOOST_DEDUCED_TYPENAME manage_bimap_key
94 <
95 RightSetType
96
97 >::type right_set_type;
98
99
100 private:
101
102 typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support::default_tagged
103 <
104 BOOST_DEDUCED_TYPENAME left_set_type::user_type,
105 ::boost::bimaps::relation::member_at::left
106
107 >::type left_tagged_type;
108
109 typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support::default_tagged
110 <
111 BOOST_DEDUCED_TYPENAME right_set_type::user_type,
112 ::boost::bimaps::relation::member_at::right
113
114 >::type right_tagged_type;
115
116 public:
117
118 //@{
119
120 typedef BOOST_DEDUCED_TYPENAME left_tagged_type::tag left_tag;
121 typedef BOOST_DEDUCED_TYPENAME right_tagged_type::tag right_tag;
122
123 //@}
124
125 //@{
126
127 typedef BOOST_DEDUCED_TYPENAME left_set_type::value_type left_key_type;
128 typedef BOOST_DEDUCED_TYPENAME right_set_type::value_type right_key_type;
129
130 //@}
131
132 //@{
133
134 typedef right_key_type left_data_type;
135 typedef left_key_type right_data_type;
136
137 //@}
138
139 // Manage the additional parameters
140 // --------------------------------------------------------------------
141 private:
142
143 typedef BOOST_DEDUCED_TYPENAME manage_additional_parameters<AP1,AP2,AP3>::type parameters;
144
145 /// \brief Relation type stored by the bimap.
146 // --------------------------------------------------------------------
147 public:
148
149 typedef ::boost::bimaps::relation::mutant_relation
150 <
151
152 ::boost::bimaps::tags::tagged<
153 BOOST_DEDUCED_TYPENAME mpl::if_<
154 mpl::and_
155 <
156 BOOST_DEDUCED_TYPENAME left_set_type::mutable_key,
157 BOOST_DEDUCED_TYPENAME parameters::set_type_of_relation::left_mutable_key
158 >,
159 // {
160 left_key_type,
161 // }
162 // else
163 // {
164 BOOST_DEDUCED_TYPENAME ::boost::add_const< left_key_type >::type
165 // }
166
167 >::type,
168 left_tag
169 >,
170
171 ::boost::bimaps::tags::tagged<
172 BOOST_DEDUCED_TYPENAME mpl::if_<
173 mpl::and_
174 <
175 BOOST_DEDUCED_TYPENAME right_set_type::mutable_key,
176 BOOST_DEDUCED_TYPENAME parameters::set_type_of_relation::right_mutable_key
177 >,
178 // {
179 right_key_type,
180 // }
181 // else
182 // {
183 BOOST_DEDUCED_TYPENAME ::boost::add_const< right_key_type >::type
184 // }
185
186 >::type,
187 right_tag
188 >,
189
190 // It is ::boost::mpl::na if no info_hook was included
191 BOOST_DEDUCED_TYPENAME parameters::additional_info,
192
193 // Force mutable keys
194 true
195
196 > relation;
197
198 //@{
199
200 typedef BOOST_DEDUCED_TYPENAME relation::left_pair left_value_type;
201 typedef BOOST_DEDUCED_TYPENAME relation::right_pair right_value_type;
202
203 //@}
204
205 // Bind the member of the relation, so multi_index can manage them
206 // --------------------------------------------------------------------
207 private:
208
209 typedef BOOST_DEDUCED_TYPENAME relation::storage_base relation_storage_base;
210
211 typedef BOOST_MULTI_INDEX_MEMBER(relation_storage_base, left_key_type, left)
212 left_member_extractor;
213
214 typedef BOOST_MULTI_INDEX_MEMBER(relation_storage_base,right_key_type,right)
215 right_member_extractor;
216
217 // The core indices are somewhat complicated to calculate, because they
218 // can be zero, one, two or three indices, depending on the use of
219 // {side}_based set type of relations and unconstrained_set_of and
220 // unconstrained_set_of_relation specifications.
221
222 typedef BOOST_DEDUCED_TYPENAME mpl::if_<
223 ::boost::bimaps::detail::is_unconstrained_set_of< left_set_type >,
224 // {
225 mpl::vector<>,
226 // }
227 // else
228 // {
229 mpl::vector
230 <
231 BOOST_DEDUCED_TYPENAME left_set_type::
232 BOOST_NESTED_TEMPLATE index_bind
233 <
234 left_member_extractor,
235 left_tag
236
237 >::type
238 >
239 // }
240 >::type left_core_indices;
241
242 typedef BOOST_DEDUCED_TYPENAME mpl::if_<
243 ::boost::bimaps::detail::is_unconstrained_set_of< right_set_type >,
244 // {
245 left_core_indices,
246 // }
247 // else
248 // {
249 BOOST_DEDUCED_TYPENAME mpl::push_front
250 <
251 left_core_indices,
252
253 BOOST_DEDUCED_TYPENAME right_set_type::
254 BOOST_NESTED_TEMPLATE index_bind
255 <
256 right_member_extractor,
257 right_tag
258
259 >::type
260
261 >::type
262 // }
263 >::type basic_core_indices;
264
265 // If it is based either on the left or on the right, then only the side
266 // indices are needed. But the set type of the relation can be completely
267 // different from the one used for the sides in which case we have to add yet
268 // another index to the core.
269
270 // TODO
271 // If all the set types are unsconstrained there must be readable compile
272 // time error.
273
274 typedef BOOST_DEDUCED_TYPENAME mpl::if_<
275
276 is_same< BOOST_DEDUCED_TYPENAME parameters::set_type_of_relation, left_based >,
277 // {
278 ::boost::bimaps::tags::tagged< left_set_type, left_tag >,
279 // }
280 /* else */ BOOST_DEDUCED_TYPENAME mpl::if_<
281 is_same< BOOST_DEDUCED_TYPENAME parameters::set_type_of_relation, right_based >,
282 // {
283 ::boost::bimaps::tags::tagged< right_set_type, right_tag >,
284 // }
285 // else
286 // {
287 tags::tagged
288 <
289 BOOST_DEDUCED_TYPENAME parameters::
290 set_type_of_relation::BOOST_NESTED_TEMPLATE bind_to
291 <
292 relation
293
294 >::type,
295 independent_index_tag
296 >
297 // }
298 >::type
299 >::type tagged_set_of_relation_type;
300
301 protected:
302
303 typedef BOOST_DEDUCED_TYPENAME tagged_set_of_relation_type::tag
304 relation_set_tag;
305
306 typedef BOOST_DEDUCED_TYPENAME tagged_set_of_relation_type::value_type
307 relation_set_type_of;
308
309 // Logic tags
310 // This is a necessary extra level of indirection to allow unconstrained
311 // sets to be plug in the design. The bimap constructors use this logic
312 // tags.
313
314 typedef BOOST_DEDUCED_TYPENAME mpl::if_<
315 ::boost::bimaps::detail::is_unconstrained_set_of< left_set_type >,
316
317 BOOST_DEDUCED_TYPENAME mpl::if_<
318 ::boost::bimaps::detail::is_unconstrained_set_of< right_set_type >,
319
320 independent_index_tag,
321 right_tag
322
323 >::type,
324
325 left_tag
326
327 >::type logic_left_tag;
328
329 typedef BOOST_DEDUCED_TYPENAME mpl::if_<
330 ::boost::bimaps::detail::is_unconstrained_set_of< right_set_type >,
331
332 BOOST_DEDUCED_TYPENAME mpl::if_<
333 ::boost::bimaps::detail::is_unconstrained_set_of< left_set_type >,
334
335 independent_index_tag,
336 left_tag
337
338 >::type,
339
340 right_tag
341
342 >::type logic_right_tag;
343
344 typedef BOOST_DEDUCED_TYPENAME mpl::if_<
345 is_same< relation_set_tag, independent_index_tag >,
346
347 BOOST_DEDUCED_TYPENAME mpl::if_<
348 ::boost::bimaps::detail::
349 is_unconstrained_set_of< relation_set_type_of >,
350
351 logic_left_tag,
352 independent_index_tag
353
354 >::type,
355
356 BOOST_DEDUCED_TYPENAME mpl::if_<
357 is_same< BOOST_DEDUCED_TYPENAME parameters::set_type_of_relation, left_based >,
358
359 logic_left_tag,
360 logic_right_tag
361
362 >::type
363
364 >::type logic_relation_set_tag;
365
366 private:
367
368 typedef BOOST_DEDUCED_TYPENAME mpl::if_<
369 mpl::and_< is_same< relation_set_tag, independent_index_tag >,
370 mpl::not_<
371 ::boost::bimaps::detail::
372 is_unconstrained_set_of< relation_set_type_of >
373 >
374 >,
375 // {
376 BOOST_DEDUCED_TYPENAME mpl::push_front
377 <
378 basic_core_indices,
379
380 BOOST_DEDUCED_TYPENAME relation_set_type_of::
381 BOOST_NESTED_TEMPLATE index_bind
382 <
383 ::boost::bimaps::relation::support::both_keys_extractor<relation>,
384 independent_index_tag
385
386 >::type
387
388 >::type,
389 // }
390 // else
391 // {
392 basic_core_indices
393 // }
394
395 >::type complete_core_indices;
396
397 struct core_indices : public complete_core_indices {};
398
399 // Define the core using compute_index_type to translate the
400 // set type to an multi-index specification
401 // --------------------------------------------------------------------
402 public:
403
404 typedef multi_index::multi_index_container
405 <
406 relation,
407 core_indices,
408 BOOST_DEDUCED_TYPENAME boost::allocator_rebind<BOOST_DEDUCED_TYPENAME
409 parameters::allocator, relation>::type
410
411 > core_type;
412
413 // Core metadata
414 // --------------------------------------------------------------------
415 public:
416
417 typedef BOOST_DEDUCED_TYPENAME ::boost::multi_index::
418 index<core_type, logic_left_tag>::type left_index;
419
420 typedef BOOST_DEDUCED_TYPENAME ::boost::multi_index::
421 index<core_type,logic_right_tag>::type right_index;
422
423 typedef BOOST_DEDUCED_TYPENAME left_index::iterator left_core_iterator;
424 typedef BOOST_DEDUCED_TYPENAME left_index::const_iterator left_core_const_iterator;
425
426 typedef BOOST_DEDUCED_TYPENAME right_index::iterator right_core_iterator;
427 typedef BOOST_DEDUCED_TYPENAME right_index::const_iterator right_core_const_iterator;
428
429 // Relation set view
430
431 typedef BOOST_DEDUCED_TYPENAME ::boost::multi_index::index
432 <
433 core_type, logic_relation_set_tag
434
435 >::type relation_set_core_index;
436
437 typedef BOOST_DEDUCED_TYPENAME relation_set_type_of::
438 BOOST_NESTED_TEMPLATE set_view_bind
439 <
440 relation_set_core_index
441
442 >::type relation_set;
443
444 public:
445
446 typedef bimap_core bimap_core_;
447};
448
449// Two auxiliary metafunctions to compute the map view types
450// The map view type can not be computed inside the bimap core because a
451// they need the bimap core to be parsed first.
452
453template< class BimapBaseType >
454struct left_map_view_type
455{
456 typedef BOOST_DEDUCED_TYPENAME BimapBaseType::left_set_type left_set_type;
457 typedef BOOST_DEDUCED_TYPENAME
458 left_set_type::BOOST_NESTED_TEMPLATE map_view_bind<
459 BOOST_DEDUCED_TYPENAME BimapBaseType::left_tag, BimapBaseType
460 >::type type;
461};
462
463template< class BimapBaseType >
464struct right_map_view_type
465{
466 typedef BOOST_DEDUCED_TYPENAME BimapBaseType::right_set_type right_set_type;
467 typedef BOOST_DEDUCED_TYPENAME
468 right_set_type::BOOST_NESTED_TEMPLATE map_view_bind<
469 BOOST_DEDUCED_TYPENAME BimapBaseType::right_tag, BimapBaseType
470 >::type type;
471};
472
473
474} // namespace detail
475} // namespace bimaps
476} // namespace boost
477
478#endif // BOOST_BIMAP_DETAIL_BIMAP_CORE_HPP
479

source code of boost/libs/bimap/include/boost/bimap/detail/bimap_core.hpp