property_map.hpp 20 KB

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