|
1 // (C) Copyright Jeremy Siek 1999-2001. |
|
2 // Distributed under the Boost Software License, Version 1.0. (See |
|
3 // accompanying file LICENSE_1_0.txt or copy at |
|
4 // http://www.boost.org/LICENSE_1_0.txt) |
|
5 |
|
6 // See http://www.boost.org/libs/property_map for documentation. |
|
7 |
|
8 #ifndef BOOST_PROPERTY_MAP_HPP |
|
9 #define BOOST_PROPERTY_MAP_HPP |
|
10 |
|
11 #include <cassert> |
|
12 #include <boost/config.hpp> |
|
13 #include <boost/pending/cstddef.hpp> |
|
14 #include <boost/detail/iterator.hpp> |
|
15 #include <boost/concept_check.hpp> |
|
16 #include <boost/concept_archetype.hpp> |
|
17 |
|
18 namespace boost { |
|
19 |
|
20 //========================================================================= |
|
21 // property_traits class |
|
22 |
|
23 template <typename PA> |
|
24 struct property_traits { |
|
25 typedef typename PA::key_type key_type; |
|
26 typedef typename PA::value_type value_type; |
|
27 typedef typename PA::reference reference; |
|
28 typedef typename PA::category category; |
|
29 }; |
|
30 |
|
31 //========================================================================= |
|
32 // property_traits category tags |
|
33 |
|
34 namespace detail { |
|
35 enum ePropertyMapID { READABLE_PA, WRITABLE_PA, |
|
36 READ_WRITE_PA, LVALUE_PA, OP_BRACKET_PA, |
|
37 RAND_ACCESS_ITER_PA, LAST_PA }; |
|
38 } |
|
39 struct readable_property_map_tag { enum { id = detail::READABLE_PA }; }; |
|
40 struct writable_property_map_tag { enum { id = detail::WRITABLE_PA }; }; |
|
41 struct read_write_property_map_tag : |
|
42 public readable_property_map_tag, |
|
43 public writable_property_map_tag |
|
44 { enum { id = detail::READ_WRITE_PA }; }; |
|
45 |
|
46 struct lvalue_property_map_tag : public read_write_property_map_tag |
|
47 { enum { id = detail::LVALUE_PA }; }; |
|
48 |
|
49 //========================================================================= |
|
50 // property_traits specialization for pointers |
|
51 |
|
52 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
|
53 // The user will just have to create their own specializations for |
|
54 // other pointers types if the compiler does not have partial |
|
55 // specializations. Sorry! |
|
56 #define BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(TYPE) \ |
|
57 template <> \ |
|
58 struct property_traits<TYPE*> { \ |
|
59 typedef TYPE value_type; \ |
|
60 typedef value_type& reference; \ |
|
61 typedef std::ptrdiff_t key_type; \ |
|
62 typedef lvalue_property_map_tag category; \ |
|
63 }; \ |
|
64 template <> \ |
|
65 struct property_traits<const TYPE*> { \ |
|
66 typedef TYPE value_type; \ |
|
67 typedef const value_type& reference; \ |
|
68 typedef std::ptrdiff_t key_type; \ |
|
69 typedef lvalue_property_map_tag category; \ |
|
70 } |
|
71 |
|
72 BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(long); |
|
73 BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(unsigned long); |
|
74 BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(int); |
|
75 BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(unsigned int); |
|
76 BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(short); |
|
77 BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(unsigned short); |
|
78 BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(char); |
|
79 BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(unsigned char); |
|
80 BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(signed char); |
|
81 BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(bool); |
|
82 BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(float); |
|
83 BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(double); |
|
84 BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(long double); |
|
85 |
|
86 // This may need to be turned off for some older compilers that don't have |
|
87 // wchar_t intrinsically. |
|
88 # ifndef BOOST_NO_INTRINSIC_WCHAR_T |
|
89 template <> |
|
90 struct property_traits<wchar_t*> { |
|
91 typedef wchar_t value_type; |
|
92 typedef value_type& reference; |
|
93 typedef std::ptrdiff_t key_type; |
|
94 typedef lvalue_property_map_tag category; |
|
95 }; |
|
96 template <> |
|
97 struct property_traits<const wchar_t*> { |
|
98 typedef wchar_t value_type; |
|
99 typedef const value_type& reference; |
|
100 typedef std::ptrdiff_t key_type; |
|
101 typedef lvalue_property_map_tag category; |
|
102 }; |
|
103 # endif |
|
104 |
|
105 #else |
|
106 template <class T> |
|
107 struct property_traits<T*> { |
|
108 typedef T value_type; |
|
109 typedef value_type& reference; |
|
110 typedef std::ptrdiff_t key_type; |
|
111 typedef lvalue_property_map_tag category; |
|
112 }; |
|
113 template <class T> |
|
114 struct property_traits<const T*> { |
|
115 typedef T value_type; |
|
116 typedef const value_type& reference; |
|
117 typedef std::ptrdiff_t key_type; |
|
118 typedef lvalue_property_map_tag category; |
|
119 }; |
|
120 #endif |
|
121 |
|
122 #if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) |
|
123 // MSVC doesn't have Koenig lookup, so the user has to |
|
124 // do boost::get() anyways, and the using clause |
|
125 // doesn't really work for MSVC. |
|
126 } // namespace boost |
|
127 #endif |
|
128 |
|
129 // These need to go in global namespace because Koenig |
|
130 // lookup does not apply to T*. |
|
131 |
|
132 // V must be convertible to T |
|
133 template <class T, class V> |
|
134 inline void put(T* pa, std::ptrdiff_t k, const V& val) { pa[k] = val; } |
|
135 |
|
136 template <class T> |
|
137 inline const T& get(const T* pa, std::ptrdiff_t k) { return pa[k]; } |
|
138 |
|
139 #if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) |
|
140 namespace boost { |
|
141 using ::put; |
|
142 using ::get; |
|
143 #endif |
|
144 |
|
145 //========================================================================= |
|
146 // concept checks for property maps |
|
147 |
|
148 template <class PMap, class Key> |
|
149 struct ReadablePropertyMapConcept |
|
150 { |
|
151 typedef typename property_traits<PMap>::key_type key_type; |
|
152 typedef typename property_traits<PMap>::reference reference; |
|
153 typedef typename property_traits<PMap>::category Category; |
|
154 typedef boost::readable_property_map_tag ReadableTag; |
|
155 void constraints() { |
|
156 function_requires< ConvertibleConcept<Category, ReadableTag> >(); |
|
157 |
|
158 val = get(pmap, k); |
|
159 } |
|
160 PMap pmap; |
|
161 Key k; |
|
162 typename property_traits<PMap>::value_type val; |
|
163 }; |
|
164 template <typename KeyArchetype, typename ValueArchetype> |
|
165 struct readable_property_map_archetype { |
|
166 typedef KeyArchetype key_type; |
|
167 typedef ValueArchetype value_type; |
|
168 typedef convertible_to_archetype<ValueArchetype> reference; |
|
169 typedef readable_property_map_tag category; |
|
170 }; |
|
171 template <typename K, typename V> |
|
172 const typename readable_property_map_archetype<K,V>::reference& |
|
173 get(const readable_property_map_archetype<K,V>&, |
|
174 const typename readable_property_map_archetype<K,V>::key_type&) |
|
175 { |
|
176 typedef typename readable_property_map_archetype<K,V>::reference R; |
|
177 return static_object<R>::get(); |
|
178 } |
|
179 |
|
180 |
|
181 template <class PMap, class Key> |
|
182 struct WritablePropertyMapConcept |
|
183 { |
|
184 typedef typename property_traits<PMap>::key_type key_type; |
|
185 typedef typename property_traits<PMap>::category Category; |
|
186 typedef boost::writable_property_map_tag WritableTag; |
|
187 void constraints() { |
|
188 function_requires< ConvertibleConcept<Category, WritableTag> >(); |
|
189 put(pmap, k, val); |
|
190 } |
|
191 PMap pmap; |
|
192 Key k; |
|
193 typename property_traits<PMap>::value_type val; |
|
194 }; |
|
195 template <typename KeyArchetype, typename ValueArchetype> |
|
196 struct writable_property_map_archetype { |
|
197 typedef KeyArchetype key_type; |
|
198 typedef ValueArchetype value_type; |
|
199 typedef void reference; |
|
200 typedef writable_property_map_tag category; |
|
201 }; |
|
202 template <typename K, typename V> |
|
203 void put(const writable_property_map_archetype<K,V>&, |
|
204 const typename writable_property_map_archetype<K,V>::key_type&, |
|
205 const typename writable_property_map_archetype<K,V>::value_type&) { } |
|
206 |
|
207 |
|
208 template <class PMap, class Key> |
|
209 struct ReadWritePropertyMapConcept |
|
210 { |
|
211 typedef typename property_traits<PMap>::category Category; |
|
212 typedef boost::read_write_property_map_tag ReadWriteTag; |
|
213 void constraints() { |
|
214 function_requires< ReadablePropertyMapConcept<PMap, Key> >(); |
|
215 function_requires< WritablePropertyMapConcept<PMap, Key> >(); |
|
216 function_requires< ConvertibleConcept<Category, ReadWriteTag> >(); |
|
217 } |
|
218 }; |
|
219 template <typename KeyArchetype, typename ValueArchetype> |
|
220 struct read_write_property_map_archetype |
|
221 : public readable_property_map_archetype<KeyArchetype, ValueArchetype>, |
|
222 public writable_property_map_archetype<KeyArchetype, ValueArchetype> |
|
223 { |
|
224 typedef KeyArchetype key_type; |
|
225 typedef ValueArchetype value_type; |
|
226 typedef convertible_to_archetype<ValueArchetype> reference; |
|
227 typedef read_write_property_map_tag category; |
|
228 }; |
|
229 |
|
230 |
|
231 template <class PMap, class Key> |
|
232 struct LvaluePropertyMapConcept |
|
233 { |
|
234 typedef typename property_traits<PMap>::category Category; |
|
235 typedef boost::lvalue_property_map_tag LvalueTag; |
|
236 typedef typename property_traits<PMap>::reference reference; |
|
237 |
|
238 void constraints() { |
|
239 function_requires< ReadablePropertyMapConcept<PMap, Key> >(); |
|
240 function_requires< ConvertibleConcept<Category, LvalueTag> >(); |
|
241 |
|
242 typedef typename property_traits<PMap>::value_type value_type; |
|
243 typedef typename require_same< |
|
244 const value_type&, reference>::type req; |
|
245 |
|
246 reference ref = pmap[k]; |
|
247 ignore_unused_variable_warning(ref); |
|
248 } |
|
249 PMap pmap; |
|
250 Key k; |
|
251 }; |
|
252 template <typename KeyArchetype, typename ValueArchetype> |
|
253 struct lvalue_property_map_archetype |
|
254 : public readable_property_map_archetype<KeyArchetype, ValueArchetype> |
|
255 { |
|
256 typedef KeyArchetype key_type; |
|
257 typedef ValueArchetype value_type; |
|
258 typedef const ValueArchetype& reference; |
|
259 typedef lvalue_property_map_tag category; |
|
260 const value_type& operator[](const key_type&) const { |
|
261 return static_object<value_type>::get(); |
|
262 } |
|
263 }; |
|
264 |
|
265 template <class PMap, class Key> |
|
266 struct Mutable_LvaluePropertyMapConcept |
|
267 { |
|
268 typedef typename property_traits<PMap>::category Category; |
|
269 typedef boost::lvalue_property_map_tag LvalueTag; |
|
270 typedef typename property_traits<PMap>::reference reference; |
|
271 void constraints() { |
|
272 boost::function_requires< ReadWritePropertyMapConcept<PMap, Key> >(); |
|
273 boost::function_requires<ConvertibleConcept<Category, LvalueTag> >(); |
|
274 |
|
275 typedef typename property_traits<PMap>::value_type value_type; |
|
276 typedef typename require_same< |
|
277 value_type&, |
|
278 reference>::type req; |
|
279 |
|
280 reference ref = pmap[k]; |
|
281 ignore_unused_variable_warning(ref); |
|
282 } |
|
283 PMap pmap; |
|
284 Key k; |
|
285 }; |
|
286 template <typename KeyArchetype, typename ValueArchetype> |
|
287 struct mutable_lvalue_property_map_archetype |
|
288 : public readable_property_map_archetype<KeyArchetype, ValueArchetype>, |
|
289 public writable_property_map_archetype<KeyArchetype, ValueArchetype> |
|
290 { |
|
291 typedef KeyArchetype key_type; |
|
292 typedef ValueArchetype value_type; |
|
293 typedef ValueArchetype& reference; |
|
294 typedef lvalue_property_map_tag category; |
|
295 value_type& operator[](const key_type&) const { |
|
296 return static_object<value_type>::get(); |
|
297 } |
|
298 }; |
|
299 |
|
300 struct identity_property_map; |
|
301 |
|
302 // A helper class for constructing a property map |
|
303 // from a class that implements operator[] |
|
304 |
|
305 template <class Reference, class LvaluePropertyMap> |
|
306 struct put_get_helper { }; |
|
307 |
|
308 template <class PropertyMap, class Reference, class K> |
|
309 inline Reference |
|
310 get(const put_get_helper<Reference, PropertyMap>& pa, const K& k) |
|
311 { |
|
312 Reference v = static_cast<const PropertyMap&>(pa)[k]; |
|
313 return v; |
|
314 } |
|
315 template <class PropertyMap, class Reference, class K, class V> |
|
316 inline void |
|
317 put(const put_get_helper<Reference, PropertyMap>& pa, K k, const V& v) |
|
318 { |
|
319 static_cast<const PropertyMap&>(pa)[k] = v; |
|
320 } |
|
321 |
|
322 //========================================================================= |
|
323 // Adapter to turn a RandomAccessIterator into a property map |
|
324 |
|
325 template <class RandomAccessIterator, |
|
326 class IndexMap |
|
327 #ifdef BOOST_NO_STD_ITERATOR_TRAITS |
|
328 , class T, class R |
|
329 #else |
|
330 , class T = typename std::iterator_traits<RandomAccessIterator>::value_type |
|
331 , class R = typename std::iterator_traits<RandomAccessIterator>::reference |
|
332 #endif |
|
333 > |
|
334 class iterator_property_map |
|
335 : public boost::put_get_helper< R, |
|
336 iterator_property_map<RandomAccessIterator, IndexMap, |
|
337 T, R> > |
|
338 { |
|
339 public: |
|
340 typedef typename property_traits<IndexMap>::key_type key_type; |
|
341 typedef T value_type; |
|
342 typedef R reference; |
|
343 typedef boost::lvalue_property_map_tag category; |
|
344 |
|
345 inline iterator_property_map( |
|
346 RandomAccessIterator cc = RandomAccessIterator(), |
|
347 const IndexMap& _id = IndexMap() ) |
|
348 : iter(cc), index(_id) { } |
|
349 inline R operator[](key_type v) const { return *(iter + get(index, v)) ; } |
|
350 protected: |
|
351 RandomAccessIterator iter; |
|
352 IndexMap index; |
|
353 }; |
|
354 |
|
355 #if !defined BOOST_NO_STD_ITERATOR_TRAITS |
|
356 template <class RAIter, class ID> |
|
357 inline iterator_property_map< |
|
358 RAIter, ID, |
|
359 typename std::iterator_traits<RAIter>::value_type, |
|
360 typename std::iterator_traits<RAIter>::reference> |
|
361 make_iterator_property_map(RAIter iter, ID id) { |
|
362 function_requires< RandomAccessIteratorConcept<RAIter> >(); |
|
363 typedef iterator_property_map< |
|
364 RAIter, ID, |
|
365 typename std::iterator_traits<RAIter>::value_type, |
|
366 typename std::iterator_traits<RAIter>::reference> PA; |
|
367 return PA(iter, id); |
|
368 } |
|
369 #endif |
|
370 template <class RAIter, class Value, class ID> |
|
371 inline iterator_property_map<RAIter, ID, Value, Value&> |
|
372 make_iterator_property_map(RAIter iter, ID id, Value) { |
|
373 function_requires< RandomAccessIteratorConcept<RAIter> >(); |
|
374 typedef iterator_property_map<RAIter, ID, Value, Value&> PMap; |
|
375 return PMap(iter, id); |
|
376 } |
|
377 |
|
378 template <class RandomAccessIterator, |
|
379 class IndexMap |
|
380 #ifdef BOOST_NO_STD_ITERATOR_TRAITS |
|
381 , class T, class R |
|
382 #else |
|
383 , class T = typename std::iterator_traits<RandomAccessIterator>::value_type |
|
384 , class R = typename std::iterator_traits<RandomAccessIterator>::reference |
|
385 #endif |
|
386 > |
|
387 class safe_iterator_property_map |
|
388 : public boost::put_get_helper< R, |
|
389 safe_iterator_property_map<RandomAccessIterator, IndexMap, |
|
390 T, R> > |
|
391 { |
|
392 public: |
|
393 typedef typename property_traits<IndexMap>::key_type key_type; |
|
394 typedef T value_type; |
|
395 typedef R reference; |
|
396 typedef boost::lvalue_property_map_tag category; |
|
397 |
|
398 inline safe_iterator_property_map( |
|
399 RandomAccessIterator first, |
|
400 std::size_t n_ = 0, |
|
401 const IndexMap& _id = IndexMap() ) |
|
402 : iter(first), n(n_), index(_id) { } |
|
403 inline safe_iterator_property_map() { } |
|
404 inline R operator[](key_type v) const { |
|
405 assert(get(index, v) < n); |
|
406 return *(iter + get(index, v)) ; |
|
407 } |
|
408 typename property_traits<IndexMap>::value_type size() const { return n; } |
|
409 protected: |
|
410 RandomAccessIterator iter; |
|
411 typename property_traits<IndexMap>::value_type n; |
|
412 IndexMap index; |
|
413 }; |
|
414 |
|
415 #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
|
416 template <class RAIter, class ID> |
|
417 inline safe_iterator_property_map< |
|
418 RAIter, ID, |
|
419 typename boost::detail::iterator_traits<RAIter>::value_type, |
|
420 typename boost::detail::iterator_traits<RAIter>::reference> |
|
421 make_safe_iterator_property_map(RAIter iter, std::size_t n, ID id) { |
|
422 function_requires< RandomAccessIteratorConcept<RAIter> >(); |
|
423 typedef safe_iterator_property_map< |
|
424 RAIter, ID, |
|
425 typename boost::detail::iterator_traits<RAIter>::value_type, |
|
426 typename boost::detail::iterator_traits<RAIter>::reference> PA; |
|
427 return PA(iter, n, id); |
|
428 } |
|
429 #endif |
|
430 template <class RAIter, class Value, class ID> |
|
431 inline safe_iterator_property_map<RAIter, ID, Value, Value&> |
|
432 make_safe_iterator_property_map(RAIter iter, std::size_t n, ID id, Value) { |
|
433 function_requires< RandomAccessIteratorConcept<RAIter> >(); |
|
434 typedef safe_iterator_property_map<RAIter, ID, Value, Value&> PMap; |
|
435 return PMap(iter, n, id); |
|
436 } |
|
437 |
|
438 //========================================================================= |
|
439 // An adaptor to turn a Unique Pair Associative Container like std::map or |
|
440 // std::hash_map into an Lvalue Property Map. |
|
441 |
|
442 template <typename UniquePairAssociativeContainer> |
|
443 class associative_property_map |
|
444 : public boost::put_get_helper< |
|
445 typename UniquePairAssociativeContainer::value_type::second_type&, |
|
446 associative_property_map<UniquePairAssociativeContainer> > |
|
447 { |
|
448 typedef UniquePairAssociativeContainer C; |
|
449 public: |
|
450 typedef typename C::key_type key_type; |
|
451 typedef typename C::value_type::second_type value_type; |
|
452 typedef value_type& reference; |
|
453 typedef lvalue_property_map_tag category; |
|
454 associative_property_map() : m_c(0) { } |
|
455 associative_property_map(C& c) : m_c(&c) { } |
|
456 reference operator[](const key_type& k) const { |
|
457 return (*m_c)[k]; |
|
458 } |
|
459 private: |
|
460 C* m_c; |
|
461 }; |
|
462 |
|
463 template <class UniquePairAssociativeContainer> |
|
464 associative_property_map<UniquePairAssociativeContainer> |
|
465 make_assoc_property_map(UniquePairAssociativeContainer& c) |
|
466 { |
|
467 return associative_property_map<UniquePairAssociativeContainer>(c); |
|
468 } |
|
469 |
|
470 template <typename UniquePairAssociativeContainer> |
|
471 class const_associative_property_map |
|
472 : public boost::put_get_helper< |
|
473 const typename UniquePairAssociativeContainer::value_type::second_type&, |
|
474 const_associative_property_map<UniquePairAssociativeContainer> > |
|
475 { |
|
476 typedef UniquePairAssociativeContainer C; |
|
477 public: |
|
478 typedef typename C::key_type key_type; |
|
479 typedef typename C::value_type::second_type value_type; |
|
480 typedef const value_type& reference; |
|
481 typedef lvalue_property_map_tag category; |
|
482 const_associative_property_map() : m_c(0) { } |
|
483 const_associative_property_map(const C& c) : m_c(&c) { } |
|
484 reference operator[](const key_type& k) const { |
|
485 return m_c->find(k)->second; |
|
486 } |
|
487 private: |
|
488 C const* m_c; |
|
489 }; |
|
490 |
|
491 template <class UniquePairAssociativeContainer> |
|
492 const_associative_property_map<UniquePairAssociativeContainer> |
|
493 make_assoc_property_map(const UniquePairAssociativeContainer& c) |
|
494 { |
|
495 return const_associative_property_map<UniquePairAssociativeContainer>(c); |
|
496 } |
|
497 |
|
498 //========================================================================= |
|
499 // A property map that applies the identity function to integers |
|
500 struct identity_property_map |
|
501 : public boost::put_get_helper<std::size_t, |
|
502 identity_property_map> |
|
503 { |
|
504 typedef std::size_t key_type; |
|
505 typedef std::size_t value_type; |
|
506 typedef std::size_t reference; |
|
507 typedef boost::readable_property_map_tag category; |
|
508 |
|
509 inline value_type operator[](const key_type& v) const { return v; } |
|
510 }; |
|
511 |
|
512 //========================================================================= |
|
513 // A property map that does not do anything, for |
|
514 // when you have to supply a property map, but don't need it. |
|
515 namespace detail { |
|
516 struct dummy_pmap_reference { |
|
517 template <class T> |
|
518 dummy_pmap_reference& operator=(const T&) { return *this; } |
|
519 operator int() { return 0; } |
|
520 }; |
|
521 } |
|
522 class dummy_property_map |
|
523 : public boost::put_get_helper<detail::dummy_pmap_reference, |
|
524 dummy_property_map > |
|
525 { |
|
526 public: |
|
527 typedef void key_type; |
|
528 typedef int value_type; |
|
529 typedef detail::dummy_pmap_reference reference; |
|
530 typedef boost::read_write_property_map_tag category; |
|
531 inline dummy_property_map() : c(0) { } |
|
532 inline dummy_property_map(value_type cc) : c(cc) { } |
|
533 inline dummy_property_map(const dummy_property_map& x) |
|
534 : c(x.c) { } |
|
535 template <class Vertex> |
|
536 inline reference operator[](Vertex) const { return reference(); } |
|
537 protected: |
|
538 value_type c; |
|
539 }; |
|
540 |
|
541 |
|
542 } // namespace boost |
|
543 |
|
544 |
|
545 #endif /* BOOST_PROPERTY_MAP_HPP */ |
|
546 |