williamr@2: // (C) Copyright Jeremy Siek 1999-2001. williamr@2: // Distributed under the Boost Software License, Version 1.0. (See williamr@2: // accompanying file LICENSE_1_0.txt or copy at williamr@2: // http://www.boost.org/LICENSE_1_0.txt) williamr@2: williamr@2: // See http://www.boost.org/libs/property_map for documentation. williamr@2: williamr@2: #ifndef BOOST_PROPERTY_MAP_HPP williamr@2: #define BOOST_PROPERTY_MAP_HPP williamr@2: williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: williamr@2: namespace boost { williamr@2: williamr@2: //========================================================================= williamr@2: // property_traits class williamr@2: williamr@2: template williamr@2: struct property_traits { williamr@2: typedef typename PA::key_type key_type; williamr@2: typedef typename PA::value_type value_type; williamr@2: typedef typename PA::reference reference; williamr@2: typedef typename PA::category category; williamr@2: }; williamr@2: williamr@2: //========================================================================= williamr@2: // property_traits category tags williamr@2: williamr@2: namespace detail { williamr@2: enum ePropertyMapID { READABLE_PA, WRITABLE_PA, williamr@2: READ_WRITE_PA, LVALUE_PA, OP_BRACKET_PA, williamr@2: RAND_ACCESS_ITER_PA, LAST_PA }; williamr@2: } williamr@2: struct readable_property_map_tag { enum { id = detail::READABLE_PA }; }; williamr@2: struct writable_property_map_tag { enum { id = detail::WRITABLE_PA }; }; williamr@2: struct read_write_property_map_tag : williamr@2: public readable_property_map_tag, williamr@2: public writable_property_map_tag williamr@2: { enum { id = detail::READ_WRITE_PA }; }; williamr@2: williamr@2: struct lvalue_property_map_tag : public read_write_property_map_tag williamr@2: { enum { id = detail::LVALUE_PA }; }; williamr@2: williamr@2: //========================================================================= williamr@2: // property_traits specialization for pointers williamr@2: williamr@2: #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION williamr@2: // The user will just have to create their own specializations for williamr@2: // other pointers types if the compiler does not have partial williamr@2: // specializations. Sorry! williamr@2: #define BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(TYPE) \ williamr@2: template <> \ williamr@2: struct property_traits { \ williamr@2: typedef TYPE value_type; \ williamr@2: typedef value_type& reference; \ williamr@2: typedef std::ptrdiff_t key_type; \ williamr@2: typedef lvalue_property_map_tag category; \ williamr@2: }; \ williamr@2: template <> \ williamr@2: struct property_traits { \ williamr@2: typedef TYPE value_type; \ williamr@2: typedef const value_type& reference; \ williamr@2: typedef std::ptrdiff_t key_type; \ williamr@2: typedef lvalue_property_map_tag category; \ williamr@2: } williamr@2: williamr@2: BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(long); williamr@2: BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(unsigned long); williamr@2: BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(int); williamr@2: BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(unsigned int); williamr@2: BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(short); williamr@2: BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(unsigned short); williamr@2: BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(char); williamr@2: BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(unsigned char); williamr@2: BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(signed char); williamr@2: BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(bool); williamr@2: BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(float); williamr@2: BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(double); williamr@2: BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(long double); williamr@2: williamr@2: // This may need to be turned off for some older compilers that don't have williamr@2: // wchar_t intrinsically. williamr@2: # ifndef BOOST_NO_INTRINSIC_WCHAR_T williamr@2: template <> williamr@2: struct property_traits { williamr@2: typedef wchar_t value_type; williamr@2: typedef value_type& reference; williamr@2: typedef std::ptrdiff_t key_type; williamr@2: typedef lvalue_property_map_tag category; williamr@2: }; williamr@2: template <> williamr@2: struct property_traits { williamr@2: typedef wchar_t value_type; williamr@2: typedef const value_type& reference; williamr@2: typedef std::ptrdiff_t key_type; williamr@2: typedef lvalue_property_map_tag category; williamr@2: }; williamr@2: # endif williamr@2: williamr@2: #else williamr@2: template williamr@2: struct property_traits { williamr@2: typedef T value_type; williamr@2: typedef value_type& reference; williamr@2: typedef std::ptrdiff_t key_type; williamr@2: typedef lvalue_property_map_tag category; williamr@2: }; williamr@2: template williamr@2: struct property_traits { williamr@2: typedef T value_type; williamr@2: typedef const value_type& reference; williamr@2: typedef std::ptrdiff_t key_type; williamr@2: typedef lvalue_property_map_tag category; williamr@2: }; williamr@2: #endif williamr@2: williamr@2: #if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) williamr@2: // MSVC doesn't have Koenig lookup, so the user has to williamr@2: // do boost::get() anyways, and the using clause williamr@2: // doesn't really work for MSVC. williamr@2: } // namespace boost williamr@2: #endif williamr@2: williamr@2: // These need to go in global namespace because Koenig williamr@2: // lookup does not apply to T*. williamr@2: williamr@2: // V must be convertible to T williamr@2: template williamr@2: inline void put(T* pa, std::ptrdiff_t k, const V& val) { pa[k] = val; } williamr@2: williamr@2: template williamr@2: inline const T& get(const T* pa, std::ptrdiff_t k) { return pa[k]; } williamr@2: williamr@2: #if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) williamr@2: namespace boost { williamr@2: using ::put; williamr@2: using ::get; williamr@2: #endif williamr@2: williamr@2: //========================================================================= williamr@2: // concept checks for property maps williamr@2: williamr@2: template williamr@2: struct ReadablePropertyMapConcept williamr@2: { williamr@2: typedef typename property_traits::key_type key_type; williamr@2: typedef typename property_traits::reference reference; williamr@2: typedef typename property_traits::category Category; williamr@2: typedef boost::readable_property_map_tag ReadableTag; williamr@2: void constraints() { williamr@2: function_requires< ConvertibleConcept >(); williamr@2: williamr@2: val = get(pmap, k); williamr@2: } williamr@2: PMap pmap; williamr@2: Key k; williamr@2: typename property_traits::value_type val; williamr@2: }; williamr@2: template williamr@2: struct readable_property_map_archetype { williamr@2: typedef KeyArchetype key_type; williamr@2: typedef ValueArchetype value_type; williamr@2: typedef convertible_to_archetype reference; williamr@2: typedef readable_property_map_tag category; williamr@2: }; williamr@2: template williamr@2: const typename readable_property_map_archetype::reference& williamr@2: get(const readable_property_map_archetype&, williamr@2: const typename readable_property_map_archetype::key_type&) williamr@2: { williamr@2: typedef typename readable_property_map_archetype::reference R; williamr@2: return static_object::get(); williamr@2: } williamr@2: williamr@2: williamr@2: template williamr@2: struct WritablePropertyMapConcept williamr@2: { williamr@2: typedef typename property_traits::key_type key_type; williamr@2: typedef typename property_traits::category Category; williamr@2: typedef boost::writable_property_map_tag WritableTag; williamr@2: void constraints() { williamr@2: function_requires< ConvertibleConcept >(); williamr@2: put(pmap, k, val); williamr@2: } williamr@2: PMap pmap; williamr@2: Key k; williamr@2: typename property_traits::value_type val; williamr@2: }; williamr@2: template williamr@2: struct writable_property_map_archetype { williamr@2: typedef KeyArchetype key_type; williamr@2: typedef ValueArchetype value_type; williamr@2: typedef void reference; williamr@2: typedef writable_property_map_tag category; williamr@2: }; williamr@2: template williamr@2: void put(const writable_property_map_archetype&, williamr@2: const typename writable_property_map_archetype::key_type&, williamr@2: const typename writable_property_map_archetype::value_type&) { } williamr@2: williamr@2: williamr@2: template williamr@2: struct ReadWritePropertyMapConcept williamr@2: { williamr@2: typedef typename property_traits::category Category; williamr@2: typedef boost::read_write_property_map_tag ReadWriteTag; williamr@2: void constraints() { williamr@2: function_requires< ReadablePropertyMapConcept >(); williamr@2: function_requires< WritablePropertyMapConcept >(); williamr@2: function_requires< ConvertibleConcept >(); williamr@2: } williamr@2: }; williamr@2: template williamr@2: struct read_write_property_map_archetype williamr@2: : public readable_property_map_archetype, williamr@2: public writable_property_map_archetype williamr@2: { williamr@2: typedef KeyArchetype key_type; williamr@2: typedef ValueArchetype value_type; williamr@2: typedef convertible_to_archetype reference; williamr@2: typedef read_write_property_map_tag category; williamr@2: }; williamr@2: williamr@2: williamr@2: template williamr@2: struct LvaluePropertyMapConcept williamr@2: { williamr@2: typedef typename property_traits::category Category; williamr@2: typedef boost::lvalue_property_map_tag LvalueTag; williamr@2: typedef typename property_traits::reference reference; williamr@2: williamr@2: void constraints() { williamr@2: function_requires< ReadablePropertyMapConcept >(); williamr@2: function_requires< ConvertibleConcept >(); williamr@2: williamr@2: typedef typename property_traits::value_type value_type; williamr@2: typedef typename require_same< williamr@2: const value_type&, reference>::type req; williamr@2: williamr@2: reference ref = pmap[k]; williamr@2: ignore_unused_variable_warning(ref); williamr@2: } williamr@2: PMap pmap; williamr@2: Key k; williamr@2: }; williamr@2: template williamr@2: struct lvalue_property_map_archetype williamr@2: : public readable_property_map_archetype williamr@2: { williamr@2: typedef KeyArchetype key_type; williamr@2: typedef ValueArchetype value_type; williamr@2: typedef const ValueArchetype& reference; williamr@2: typedef lvalue_property_map_tag category; williamr@2: const value_type& operator[](const key_type&) const { williamr@2: return static_object::get(); williamr@2: } williamr@2: }; williamr@2: williamr@2: template williamr@2: struct Mutable_LvaluePropertyMapConcept williamr@2: { williamr@2: typedef typename property_traits::category Category; williamr@2: typedef boost::lvalue_property_map_tag LvalueTag; williamr@2: typedef typename property_traits::reference reference; williamr@2: void constraints() { williamr@2: boost::function_requires< ReadWritePropertyMapConcept >(); williamr@2: boost::function_requires >(); williamr@2: williamr@2: typedef typename property_traits::value_type value_type; williamr@2: typedef typename require_same< williamr@2: value_type&, williamr@2: reference>::type req; williamr@2: williamr@2: reference ref = pmap[k]; williamr@2: ignore_unused_variable_warning(ref); williamr@2: } williamr@2: PMap pmap; williamr@2: Key k; williamr@2: }; williamr@2: template williamr@2: struct mutable_lvalue_property_map_archetype williamr@2: : public readable_property_map_archetype, williamr@2: public writable_property_map_archetype williamr@2: { williamr@2: typedef KeyArchetype key_type; williamr@2: typedef ValueArchetype value_type; williamr@2: typedef ValueArchetype& reference; williamr@2: typedef lvalue_property_map_tag category; williamr@2: value_type& operator[](const key_type&) const { williamr@2: return static_object::get(); williamr@2: } williamr@2: }; williamr@2: williamr@2: struct identity_property_map; williamr@2: williamr@2: // A helper class for constructing a property map williamr@2: // from a class that implements operator[] williamr@2: williamr@2: template williamr@2: struct put_get_helper { }; williamr@2: williamr@2: template williamr@2: inline Reference williamr@2: get(const put_get_helper& pa, const K& k) williamr@2: { williamr@2: Reference v = static_cast(pa)[k]; williamr@2: return v; williamr@2: } williamr@2: template williamr@2: inline void williamr@2: put(const put_get_helper& pa, K k, const V& v) williamr@2: { williamr@2: static_cast(pa)[k] = v; williamr@2: } williamr@2: williamr@2: //========================================================================= williamr@2: // Adapter to turn a RandomAccessIterator into a property map williamr@2: williamr@2: template ::value_type williamr@2: , class R = typename std::iterator_traits::reference williamr@2: #endif williamr@2: > williamr@2: class iterator_property_map williamr@2: : public boost::put_get_helper< R, williamr@2: iterator_property_map > williamr@2: { williamr@2: public: williamr@2: typedef typename property_traits::key_type key_type; williamr@2: typedef T value_type; williamr@2: typedef R reference; williamr@2: typedef boost::lvalue_property_map_tag category; williamr@2: williamr@2: inline iterator_property_map( williamr@2: RandomAccessIterator cc = RandomAccessIterator(), williamr@2: const IndexMap& _id = IndexMap() ) williamr@2: : iter(cc), index(_id) { } williamr@2: inline R operator[](key_type v) const { return *(iter + get(index, v)) ; } williamr@2: protected: williamr@2: RandomAccessIterator iter; williamr@2: IndexMap index; williamr@2: }; williamr@2: williamr@2: #if !defined BOOST_NO_STD_ITERATOR_TRAITS williamr@2: template williamr@2: inline iterator_property_map< williamr@2: RAIter, ID, williamr@2: typename std::iterator_traits::value_type, williamr@2: typename std::iterator_traits::reference> williamr@2: make_iterator_property_map(RAIter iter, ID id) { williamr@2: function_requires< RandomAccessIteratorConcept >(); williamr@2: typedef iterator_property_map< williamr@2: RAIter, ID, williamr@2: typename std::iterator_traits::value_type, williamr@2: typename std::iterator_traits::reference> PA; williamr@2: return PA(iter, id); williamr@2: } williamr@2: #endif williamr@2: template williamr@2: inline iterator_property_map williamr@2: make_iterator_property_map(RAIter iter, ID id, Value) { williamr@2: function_requires< RandomAccessIteratorConcept >(); williamr@2: typedef iterator_property_map PMap; williamr@2: return PMap(iter, id); williamr@2: } williamr@2: williamr@2: template ::value_type williamr@2: , class R = typename std::iterator_traits::reference williamr@2: #endif williamr@2: > williamr@2: class safe_iterator_property_map williamr@2: : public boost::put_get_helper< R, williamr@2: safe_iterator_property_map > williamr@2: { williamr@2: public: williamr@2: typedef typename property_traits::key_type key_type; williamr@2: typedef T value_type; williamr@2: typedef R reference; williamr@2: typedef boost::lvalue_property_map_tag category; williamr@2: williamr@2: inline safe_iterator_property_map( williamr@2: RandomAccessIterator first, williamr@2: std::size_t n_ = 0, williamr@2: const IndexMap& _id = IndexMap() ) williamr@2: : iter(first), n(n_), index(_id) { } williamr@2: inline safe_iterator_property_map() { } williamr@2: inline R operator[](key_type v) const { williamr@2: assert(get(index, v) < n); williamr@2: return *(iter + get(index, v)) ; williamr@2: } williamr@2: typename property_traits::value_type size() const { return n; } williamr@2: protected: williamr@2: RandomAccessIterator iter; williamr@2: typename property_traits::value_type n; williamr@2: IndexMap index; williamr@2: }; williamr@2: williamr@2: #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION williamr@2: template williamr@2: inline safe_iterator_property_map< williamr@2: RAIter, ID, williamr@2: typename boost::detail::iterator_traits::value_type, williamr@2: typename boost::detail::iterator_traits::reference> williamr@2: make_safe_iterator_property_map(RAIter iter, std::size_t n, ID id) { williamr@2: function_requires< RandomAccessIteratorConcept >(); williamr@2: typedef safe_iterator_property_map< williamr@2: RAIter, ID, williamr@2: typename boost::detail::iterator_traits::value_type, williamr@2: typename boost::detail::iterator_traits::reference> PA; williamr@2: return PA(iter, n, id); williamr@2: } williamr@2: #endif williamr@2: template williamr@2: inline safe_iterator_property_map williamr@2: make_safe_iterator_property_map(RAIter iter, std::size_t n, ID id, Value) { williamr@2: function_requires< RandomAccessIteratorConcept >(); williamr@2: typedef safe_iterator_property_map PMap; williamr@2: return PMap(iter, n, id); williamr@2: } williamr@2: williamr@2: //========================================================================= williamr@2: // An adaptor to turn a Unique Pair Associative Container like std::map or williamr@2: // std::hash_map into an Lvalue Property Map. williamr@2: williamr@2: template williamr@2: class associative_property_map williamr@2: : public boost::put_get_helper< williamr@2: typename UniquePairAssociativeContainer::value_type::second_type&, williamr@2: associative_property_map > williamr@2: { williamr@2: typedef UniquePairAssociativeContainer C; williamr@2: public: williamr@2: typedef typename C::key_type key_type; williamr@2: typedef typename C::value_type::second_type value_type; williamr@2: typedef value_type& reference; williamr@2: typedef lvalue_property_map_tag category; williamr@2: associative_property_map() : m_c(0) { } williamr@2: associative_property_map(C& c) : m_c(&c) { } williamr@2: reference operator[](const key_type& k) const { williamr@2: return (*m_c)[k]; williamr@2: } williamr@2: private: williamr@2: C* m_c; williamr@2: }; williamr@2: williamr@2: template williamr@2: associative_property_map williamr@2: make_assoc_property_map(UniquePairAssociativeContainer& c) williamr@2: { williamr@2: return associative_property_map(c); williamr@2: } williamr@2: williamr@2: template williamr@2: class const_associative_property_map williamr@2: : public boost::put_get_helper< williamr@2: const typename UniquePairAssociativeContainer::value_type::second_type&, williamr@2: const_associative_property_map > williamr@2: { williamr@2: typedef UniquePairAssociativeContainer C; williamr@2: public: williamr@2: typedef typename C::key_type key_type; williamr@2: typedef typename C::value_type::second_type value_type; williamr@2: typedef const value_type& reference; williamr@2: typedef lvalue_property_map_tag category; williamr@2: const_associative_property_map() : m_c(0) { } williamr@2: const_associative_property_map(const C& c) : m_c(&c) { } williamr@2: reference operator[](const key_type& k) const { williamr@2: return m_c->find(k)->second; williamr@2: } williamr@2: private: williamr@2: C const* m_c; williamr@2: }; williamr@2: williamr@2: template williamr@2: const_associative_property_map williamr@2: make_assoc_property_map(const UniquePairAssociativeContainer& c) williamr@2: { williamr@2: return const_associative_property_map(c); williamr@2: } williamr@2: williamr@2: //========================================================================= williamr@2: // A property map that applies the identity function to integers williamr@2: struct identity_property_map williamr@2: : public boost::put_get_helper williamr@2: { williamr@2: typedef std::size_t key_type; williamr@2: typedef std::size_t value_type; williamr@2: typedef std::size_t reference; williamr@2: typedef boost::readable_property_map_tag category; williamr@2: williamr@2: inline value_type operator[](const key_type& v) const { return v; } williamr@2: }; williamr@2: williamr@2: //========================================================================= williamr@2: // A property map that does not do anything, for williamr@2: // when you have to supply a property map, but don't need it. williamr@2: namespace detail { williamr@2: struct dummy_pmap_reference { williamr@2: template williamr@2: dummy_pmap_reference& operator=(const T&) { return *this; } williamr@2: operator int() { return 0; } williamr@2: }; williamr@2: } williamr@2: class dummy_property_map williamr@2: : public boost::put_get_helper williamr@2: { williamr@2: public: williamr@2: typedef void key_type; williamr@2: typedef int value_type; williamr@2: typedef detail::dummy_pmap_reference reference; williamr@2: typedef boost::read_write_property_map_tag category; williamr@2: inline dummy_property_map() : c(0) { } williamr@2: inline dummy_property_map(value_type cc) : c(cc) { } williamr@2: inline dummy_property_map(const dummy_property_map& x) williamr@2: : c(x.c) { } williamr@2: template williamr@2: inline reference operator[](Vertex) const { return reference(); } williamr@2: protected: williamr@2: value_type c; williamr@2: }; williamr@2: williamr@2: williamr@2: } // namespace boost williamr@2: williamr@2: williamr@2: #endif /* BOOST_PROPERTY_MAP_HPP */ williamr@2: