Chris@16: // (C) Copyright Jeremy Siek 1999-2001. Chris@16: // Copyright (C) 2006 Trustees of Indiana University Chris@16: // Authors: Douglas Gregor and Jeremy Siek Chris@16: Chris@16: // Distributed under the Boost Software License, Version 1.0. (See Chris@16: // accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: // See http://www.boost.org/libs/property_map for documentation. Chris@16: Chris@16: #ifndef BOOST_PROPERTY_MAP_HPP Chris@16: #define BOOST_PROPERTY_MAP_HPP Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@101: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { Chris@16: Chris@16: //========================================================================= Chris@16: // property_traits class Chris@16: Chris@16: BOOST_MPL_HAS_XXX_TRAIT_DEF(key_type) Chris@16: BOOST_MPL_HAS_XXX_TRAIT_DEF(value_type) Chris@16: BOOST_MPL_HAS_XXX_TRAIT_DEF(reference) Chris@16: BOOST_MPL_HAS_XXX_TRAIT_DEF(category) Chris@16: Chris@16: template Chris@16: struct is_property_map : Chris@16: boost::mpl::and_< Chris@16: has_key_type, Chris@16: has_value_type, Chris@16: has_reference, Chris@16: has_category Chris@16: > Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct default_property_traits { Chris@16: typedef typename PA::key_type key_type; Chris@16: typedef typename PA::value_type value_type; Chris@16: typedef typename PA::reference reference; Chris@16: typedef typename PA::category category; Chris@16: }; Chris@16: Chris@16: struct null_property_traits {}; Chris@16: Chris@16: template Chris@16: struct property_traits : Chris@16: boost::mpl::if_, Chris@16: default_property_traits, Chris@16: null_property_traits>::type Chris@16: {}; Chris@16: Chris@16: #if 0 Chris@16: template Chris@16: struct property_traits { Chris@16: typedef typename PA::key_type key_type; Chris@16: typedef typename PA::value_type value_type; Chris@16: typedef typename PA::reference reference; Chris@16: typedef typename PA::category category; Chris@16: }; Chris@16: #endif Chris@16: Chris@16: //========================================================================= Chris@16: // property_traits category tags Chris@16: Chris@16: namespace detail { Chris@16: enum ePropertyMapID { READABLE_PA, WRITABLE_PA, Chris@16: READ_WRITE_PA, LVALUE_PA, OP_BRACKET_PA, Chris@16: RAND_ACCESS_ITER_PA, LAST_PA }; Chris@16: } Chris@16: struct readable_property_map_tag { enum { id = detail::READABLE_PA }; }; Chris@16: struct writable_property_map_tag { enum { id = detail::WRITABLE_PA }; }; Chris@16: struct read_write_property_map_tag : Chris@16: public readable_property_map_tag, Chris@16: public writable_property_map_tag Chris@16: { enum { id = detail::READ_WRITE_PA }; }; Chris@16: Chris@16: struct lvalue_property_map_tag : public read_write_property_map_tag Chris@16: { enum { id = detail::LVALUE_PA }; }; Chris@16: Chris@16: //========================================================================= Chris@16: // property_traits specialization for pointers Chris@16: Chris@16: template Chris@16: struct property_traits { Chris@16: // BOOST_STATIC_ASSERT(boost::is_same::value && !"Using pointers as property maps is deprecated"); Chris@16: typedef T value_type; Chris@16: typedef value_type& reference; Chris@16: typedef std::ptrdiff_t key_type; Chris@16: typedef lvalue_property_map_tag category; Chris@16: }; Chris@16: template Chris@16: struct property_traits { Chris@16: // BOOST_STATIC_ASSERT(boost::is_same::value && !"Using pointers as property maps is deprecated"); Chris@16: typedef T value_type; Chris@16: typedef const value_type& reference; Chris@16: typedef std::ptrdiff_t key_type; Chris@16: typedef lvalue_property_map_tag category; Chris@16: }; Chris@16: Chris@16: #if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) Chris@16: // MSVC doesn't have Koenig lookup, so the user has to Chris@16: // do boost::get() anyways, and the using clause Chris@16: // doesn't really work for MSVC. Chris@16: } // namespace boost Chris@16: #endif Chris@16: Chris@16: // These need to go in global namespace because Koenig Chris@16: // lookup does not apply to T*. Chris@16: Chris@16: // V must be convertible to T Chris@16: template Chris@16: inline void put(T* pa, std::ptrdiff_t k, const V& val) { pa[k] = val; } Chris@16: Chris@16: template Chris@16: inline const T& get(const T* pa, std::ptrdiff_t k) { return pa[k]; } Chris@16: Chris@16: #if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) Chris@16: namespace boost { Chris@16: using ::put; Chris@16: using ::get; Chris@16: #endif Chris@16: Chris@16: //========================================================================= Chris@16: // concept checks for property maps Chris@16: Chris@16: template Chris@16: struct ReadablePropertyMapConcept Chris@16: { Chris@16: typedef typename property_traits::key_type key_type; Chris@16: typedef typename property_traits::reference reference; Chris@16: typedef typename property_traits::category Category; Chris@16: typedef boost::readable_property_map_tag ReadableTag; Chris@16: void constraints() { Chris@16: function_requires< ConvertibleConcept >(); Chris@16: Chris@16: val = get(pmap, k); Chris@16: } Chris@16: PMap pmap; Chris@16: Key k; Chris@16: typename property_traits::value_type val; Chris@16: }; Chris@16: template Chris@16: struct readable_property_map_archetype { Chris@16: typedef KeyArchetype key_type; Chris@16: typedef ValueArchetype value_type; Chris@16: typedef convertible_to_archetype reference; Chris@16: typedef readable_property_map_tag category; Chris@16: }; Chris@16: template Chris@16: const typename readable_property_map_archetype::reference& Chris@16: get(const readable_property_map_archetype&, Chris@16: const typename readable_property_map_archetype::key_type&) Chris@16: { Chris@16: typedef typename readable_property_map_archetype::reference R; Chris@16: return static_object::get(); Chris@16: } Chris@16: Chris@16: Chris@16: template Chris@16: struct WritablePropertyMapConcept Chris@16: { Chris@16: typedef typename property_traits::key_type key_type; Chris@16: typedef typename property_traits::category Category; Chris@16: typedef boost::writable_property_map_tag WritableTag; Chris@16: void constraints() { Chris@16: function_requires< ConvertibleConcept >(); Chris@16: put(pmap, k, val); Chris@16: } Chris@16: PMap pmap; Chris@16: Key k; Chris@16: typename property_traits::value_type val; Chris@16: }; Chris@16: template Chris@16: struct writable_property_map_archetype { Chris@16: typedef KeyArchetype key_type; Chris@16: typedef ValueArchetype value_type; Chris@16: typedef void reference; Chris@16: typedef writable_property_map_tag category; Chris@16: }; Chris@16: template Chris@16: void put(const writable_property_map_archetype&, Chris@16: const typename writable_property_map_archetype::key_type&, Chris@16: const typename writable_property_map_archetype::value_type&) { } Chris@16: Chris@16: Chris@16: template Chris@16: struct ReadWritePropertyMapConcept Chris@16: { Chris@16: typedef typename property_traits::category Category; Chris@16: typedef boost::read_write_property_map_tag ReadWriteTag; Chris@16: void constraints() { Chris@16: function_requires< ReadablePropertyMapConcept >(); Chris@16: function_requires< WritablePropertyMapConcept >(); Chris@16: function_requires< ConvertibleConcept >(); Chris@16: } Chris@16: }; Chris@16: template Chris@16: struct read_write_property_map_archetype Chris@16: : public readable_property_map_archetype, Chris@16: public writable_property_map_archetype Chris@16: { Chris@16: typedef KeyArchetype key_type; Chris@16: typedef ValueArchetype value_type; Chris@16: typedef convertible_to_archetype reference; Chris@16: typedef read_write_property_map_tag category; Chris@16: }; Chris@16: Chris@16: Chris@16: template Chris@16: struct LvaluePropertyMapConcept Chris@16: { Chris@16: typedef typename property_traits::category Category; Chris@16: typedef boost::lvalue_property_map_tag LvalueTag; Chris@16: typedef typename property_traits::reference reference; Chris@16: Chris@16: void constraints() { Chris@16: function_requires< ReadablePropertyMapConcept >(); Chris@16: function_requires< ConvertibleConcept >(); Chris@16: Chris@16: typedef typename property_traits::value_type value_type; Chris@16: BOOST_MPL_ASSERT((boost::mpl::or_< Chris@16: boost::is_same, Chris@16: boost::is_same >)); Chris@16: Chris@16: reference ref = pmap[k]; Chris@16: ignore_unused_variable_warning(ref); Chris@16: } Chris@16: PMap pmap; Chris@16: Key k; Chris@16: }; Chris@16: template Chris@16: struct lvalue_property_map_archetype Chris@16: : public readable_property_map_archetype Chris@16: { Chris@16: typedef KeyArchetype key_type; Chris@16: typedef ValueArchetype value_type; Chris@16: typedef const ValueArchetype& reference; Chris@16: typedef lvalue_property_map_tag category; Chris@16: const value_type& operator[](const key_type&) const { Chris@16: return static_object::get(); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct Mutable_LvaluePropertyMapConcept Chris@16: { Chris@16: typedef typename property_traits::category Category; Chris@16: typedef boost::lvalue_property_map_tag LvalueTag; Chris@16: typedef typename property_traits::reference reference; Chris@16: void constraints() { Chris@16: boost::function_requires< ReadWritePropertyMapConcept >(); Chris@16: boost::function_requires >(); Chris@16: Chris@16: typedef typename property_traits::value_type value_type; Chris@16: BOOST_MPL_ASSERT((boost::is_same)); Chris@16: Chris@16: reference ref = pmap[k]; Chris@16: ignore_unused_variable_warning(ref); Chris@16: } Chris@16: PMap pmap; Chris@16: Key k; Chris@16: }; Chris@16: template Chris@16: struct mutable_lvalue_property_map_archetype Chris@16: : public readable_property_map_archetype, Chris@16: public writable_property_map_archetype Chris@16: { Chris@16: typedef KeyArchetype key_type; Chris@16: typedef ValueArchetype value_type; Chris@16: typedef ValueArchetype& reference; Chris@16: typedef lvalue_property_map_tag category; Chris@16: value_type& operator[](const key_type&) const { Chris@16: return static_object::get(); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct typed_identity_property_map; Chris@16: Chris@16: // A helper class for constructing a property map Chris@16: // from a class that implements operator[] Chris@16: Chris@16: template Chris@16: struct put_get_helper { }; Chris@16: Chris@16: template Chris@16: inline Reference Chris@16: get(const put_get_helper& pa, const K& k) Chris@16: { Chris@16: Reference v = static_cast(pa)[k]; Chris@16: return v; Chris@16: } Chris@16: template Chris@16: inline void Chris@16: put(const put_get_helper& pa, K k, const V& v) Chris@16: { Chris@16: static_cast(pa)[k] = v; Chris@16: } Chris@16: Chris@16: //========================================================================= Chris@16: // Adapter to turn a RandomAccessIterator into a property map Chris@16: Chris@16: template ::value_type Chris@16: , class R = typename std::iterator_traits::reference Chris@16: #endif Chris@16: > Chris@16: class iterator_property_map Chris@16: : public boost::put_get_helper< R, Chris@16: iterator_property_map > Chris@16: { Chris@16: public: Chris@16: typedef typename property_traits::key_type key_type; Chris@16: typedef T value_type; Chris@16: typedef R reference; Chris@16: typedef boost::lvalue_property_map_tag category; Chris@16: Chris@16: inline iterator_property_map( Chris@16: RandomAccessIterator cc = RandomAccessIterator(), Chris@16: const IndexMap& _id = IndexMap() ) Chris@16: : iter(cc), index(_id) { } Chris@16: inline R operator[](key_type v) const { return *(iter + get(index, v)) ; } Chris@16: protected: Chris@16: RandomAccessIterator iter; Chris@16: IndexMap index; Chris@16: }; Chris@16: Chris@16: #if !defined BOOST_NO_STD_ITERATOR_TRAITS Chris@16: template Chris@16: inline iterator_property_map< Chris@16: RAIter, ID, Chris@16: typename std::iterator_traits::value_type, Chris@16: typename std::iterator_traits::reference> Chris@16: make_iterator_property_map(RAIter iter, ID id) { Chris@16: function_requires< RandomAccessIteratorConcept >(); Chris@16: typedef iterator_property_map< Chris@16: RAIter, ID, Chris@16: typename std::iterator_traits::value_type, Chris@16: typename std::iterator_traits::reference> PA; Chris@16: return PA(iter, id); Chris@16: } Chris@16: #endif Chris@16: template Chris@16: inline iterator_property_map Chris@16: make_iterator_property_map(RAIter iter, ID id, Value) { Chris@16: function_requires< RandomAccessIteratorConcept >(); Chris@16: typedef iterator_property_map PMap; Chris@16: return PMap(iter, id); Chris@16: } Chris@16: Chris@16: template ::value_type Chris@16: , class R = typename std::iterator_traits::reference Chris@16: #endif Chris@16: > Chris@16: class safe_iterator_property_map Chris@16: : public boost::put_get_helper< R, Chris@16: safe_iterator_property_map > Chris@16: { Chris@16: public: Chris@16: typedef typename property_traits::key_type key_type; Chris@16: typedef T value_type; Chris@16: typedef R reference; Chris@16: typedef boost::lvalue_property_map_tag category; Chris@16: Chris@16: inline safe_iterator_property_map( Chris@16: RandomAccessIterator first, Chris@16: std::size_t n_ = 0, Chris@16: const IndexMap& _id = IndexMap() ) Chris@16: : iter(first), n(n_), index(_id) { } Chris@16: inline safe_iterator_property_map() { } Chris@16: inline R operator[](key_type v) const { Chris@16: BOOST_ASSERT(get(index, v) < n); Chris@16: return *(iter + get(index, v)) ; Chris@16: } Chris@16: typename property_traits::value_type size() const { return n; } Chris@16: protected: Chris@16: RandomAccessIterator iter; Chris@16: typename property_traits::value_type n; Chris@16: IndexMap index; Chris@16: }; Chris@16: Chris@16: template Chris@16: inline safe_iterator_property_map< Chris@16: RAIter, ID, Chris@16: typename boost::detail::iterator_traits::value_type, Chris@16: typename boost::detail::iterator_traits::reference> Chris@16: make_safe_iterator_property_map(RAIter iter, std::size_t n, ID id) { Chris@16: function_requires< RandomAccessIteratorConcept >(); Chris@16: typedef safe_iterator_property_map< Chris@16: RAIter, ID, Chris@16: typename boost::detail::iterator_traits::value_type, Chris@16: typename boost::detail::iterator_traits::reference> PA; Chris@16: return PA(iter, n, id); Chris@16: } Chris@16: template Chris@16: inline safe_iterator_property_map Chris@16: make_safe_iterator_property_map(RAIter iter, std::size_t n, ID id, Value) { Chris@16: function_requires< RandomAccessIteratorConcept >(); Chris@16: typedef safe_iterator_property_map PMap; Chris@16: return PMap(iter, n, id); Chris@16: } Chris@16: Chris@16: //========================================================================= Chris@16: // An adaptor to turn a Unique Pair Associative Container like std::map or Chris@16: // std::hash_map into an Lvalue Property Map. Chris@16: Chris@16: template Chris@16: class associative_property_map Chris@16: : public boost::put_get_helper< Chris@16: typename UniquePairAssociativeContainer::value_type::second_type&, Chris@16: associative_property_map > Chris@16: { Chris@16: typedef UniquePairAssociativeContainer C; Chris@16: public: Chris@16: typedef typename C::key_type key_type; Chris@16: typedef typename C::value_type::second_type value_type; Chris@16: typedef value_type& reference; Chris@16: typedef lvalue_property_map_tag category; Chris@16: associative_property_map() : m_c(0) { } Chris@16: associative_property_map(C& c) : m_c(&c) { } Chris@16: reference operator[](const key_type& k) const { Chris@16: return (*m_c)[k]; Chris@16: } Chris@16: private: Chris@16: C* m_c; Chris@16: }; Chris@16: Chris@16: template Chris@16: associative_property_map Chris@16: make_assoc_property_map(UniquePairAssociativeContainer& c) Chris@16: { Chris@16: return associative_property_map(c); Chris@16: } Chris@16: Chris@16: template Chris@16: class const_associative_property_map Chris@16: : public boost::put_get_helper< Chris@16: const typename UniquePairAssociativeContainer::value_type::second_type&, Chris@16: const_associative_property_map > Chris@16: { Chris@16: typedef UniquePairAssociativeContainer C; Chris@16: public: Chris@16: typedef typename C::key_type key_type; Chris@16: typedef typename C::value_type::second_type value_type; Chris@16: typedef const value_type& reference; Chris@16: typedef lvalue_property_map_tag category; Chris@16: const_associative_property_map() : m_c(0) { } Chris@16: const_associative_property_map(const C& c) : m_c(&c) { } Chris@16: reference operator[](const key_type& k) const { Chris@16: return m_c->find(k)->second; Chris@16: } Chris@16: private: Chris@16: C const* m_c; Chris@16: }; Chris@16: Chris@16: template Chris@16: const_associative_property_map Chris@16: make_assoc_property_map(const UniquePairAssociativeContainer& c) Chris@16: { Chris@16: return const_associative_property_map(c); Chris@16: } Chris@16: Chris@16: //========================================================================= Chris@16: // A property map that always returns the same object by value. Chris@16: // Chris@101: template Chris@16: class static_property_map : Chris@16: public Chris@16: boost::put_get_helper > Chris@16: { Chris@16: ValueType value; Chris@16: public: Chris@101: typedef KeyType key_type; Chris@16: typedef ValueType value_type; Chris@16: typedef ValueType reference; Chris@16: typedef readable_property_map_tag category; Chris@16: static_property_map(ValueType v) : value(v) {} Chris@16: Chris@16: template Chris@16: inline reference operator[](T) const { return value; } Chris@16: }; Chris@16: Chris@101: template Chris@101: static_property_map Chris@101: make_static_property_map(const ValueType& v) { Chris@101: return static_property_map(v); Chris@101: } Chris@101: Chris@16: //========================================================================= Chris@16: // A property map that always returns a reference to the same object. Chris@16: // Chris@16: template Chris@16: class ref_property_map : Chris@16: public Chris@16: boost::put_get_helper > Chris@16: { Chris@16: ValueType* value; Chris@16: public: Chris@16: typedef KeyType key_type; Chris@16: typedef ValueType value_type; Chris@16: typedef ValueType& reference; Chris@16: typedef lvalue_property_map_tag category; Chris@16: ref_property_map(ValueType& v) : value(&v) {} Chris@16: ValueType& operator[](key_type const&) const { return *value; } Chris@16: }; Chris@16: Chris@16: //========================================================================= Chris@16: // A generalized identity property map Chris@16: template Chris@16: struct typed_identity_property_map Chris@16: : public boost::put_get_helper > Chris@16: { Chris@16: typedef T key_type; Chris@16: typedef T value_type; Chris@16: typedef T reference; Chris@16: typedef boost::readable_property_map_tag category; Chris@16: Chris@16: inline value_type operator[](const key_type& v) const { return v; } Chris@16: }; Chris@16: Chris@16: //========================================================================= Chris@16: // A property map that applies the identity function to integers Chris@16: typedef typed_identity_property_map identity_property_map; Chris@16: Chris@16: //========================================================================= Chris@16: // A property map that does not do anything, for Chris@16: // when you have to supply a property map, but don't need it. Chris@16: namespace detail { Chris@16: struct dummy_pmap_reference { Chris@16: template Chris@16: dummy_pmap_reference& operator=(const T&) { return *this; } Chris@16: operator int() { return 0; } Chris@16: }; Chris@16: } Chris@16: class dummy_property_map Chris@16: : public boost::put_get_helper Chris@16: { Chris@16: public: Chris@16: typedef void key_type; Chris@16: typedef int value_type; Chris@16: typedef detail::dummy_pmap_reference reference; Chris@16: typedef boost::read_write_property_map_tag category; Chris@16: inline dummy_property_map() : c(0) { } Chris@16: inline dummy_property_map(value_type cc) : c(cc) { } Chris@16: inline dummy_property_map(const dummy_property_map& x) Chris@16: : c(x.c) { } Chris@16: template Chris@16: inline reference operator[](Vertex) const { return reference(); } Chris@16: protected: Chris@16: value_type c; Chris@16: }; Chris@16: Chris@16: // Convert a Readable property map into a function object Chris@16: template Chris@16: class property_map_function { Chris@16: PropMap pm; Chris@16: typedef typename property_traits::key_type param_type; Chris@16: public: Chris@16: explicit property_map_function(const PropMap& pm): pm(pm) {} Chris@16: typedef typename property_traits::value_type result_type; Chris@16: result_type operator()(const param_type& k) const {return get(pm, k);} Chris@16: }; Chris@16: Chris@16: template Chris@16: property_map_function Chris@16: make_property_map_function(const PropMap& pm) { Chris@16: return property_map_function(pm); Chris@16: } Chris@16: Chris@16: } // namespace boost Chris@16: Chris@16: #ifdef BOOST_GRAPH_USE_MPI Chris@101: #include Chris@101: #endif Chris@16: Chris@16: #include Chris@16: Chris@16: #endif /* BOOST_PROPERTY_MAP_HPP */ Chris@16: