// (C) Copyright Jeremy Siek 1999-2001. Permission to copy, use, modify, // sell and distribute this software is granted provided this // copyright notice appears in all copies. This software is provided // "as is" without express or implied warranty, and with no claim as // to its suitability for any purpose. #ifndef BOOST_PROPERTY_MAP_HPP #define BOOST_PROPERTY_MAP_HPP #include #include #include #include #include namespace boost { //========================================================================= // property_traits class template struct property_traits { typedef typename PA::key_type key_type; typedef typename PA::value_type value_type; typedef typename PA::reference reference; typedef typename PA::category category; }; //========================================================================= // property_traits category tags namespace detail { enum ePropertyMapID { READABLE_PA, WRITABLE_PA, READ_WRITE_PA, LVALUE_PA, OP_BRACKET_PA, RAND_ACCESS_ITER_PA, LAST_PA }; } struct readable_property_map_tag { enum { id = detail::READABLE_PA }; }; struct writable_property_map_tag { enum { id = detail::WRITABLE_PA }; }; struct read_write_property_map_tag : public readable_property_map_tag, public writable_property_map_tag { enum { id = detail::READ_WRITE_PA }; }; struct lvalue_property_map_tag : public read_write_property_map_tag { enum { id = detail::LVALUE_PA }; }; //========================================================================= // property_traits specialization for pointers #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION // The user will just have to create their own specializations for // other pointers types if the compiler does not have partial // specializations. Sorry! #define BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(TYPE) \ template <> \ struct property_traits { \ typedef TYPE value_type; \ typedef value_type& reference; \ typedef std::ptrdiff_t key_type; \ typedef lvalue_property_map_tag category; \ }; \ template <> \ struct property_traits { \ typedef TYPE value_type; \ typedef const value_type& reference; \ typedef std::ptrdiff_t key_type; \ typedef lvalue_property_map_tag category; \ } BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(long); BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(unsigned long); BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(int); BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(unsigned int); BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(short); BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(unsigned short); BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(char); BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(unsigned char); BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(signed char); BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(bool); BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(float); BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(double); BOOST_SPECIALIZE_PROPERTY_TRAITS_PTR(long double); // This may need to be turned off for some older compilers that don't have // wchar_t intrinsically. # ifndef BOOST_NO_INTRINSIC_WCHAR_T template <> struct property_traits { typedef wchar_t value_type; typedef value_type& reference; typedef std::ptrdiff_t key_type; typedef lvalue_property_map_tag category; }; template <> struct property_traits { typedef wchar_t value_type; typedef const value_type& reference; typedef std::ptrdiff_t key_type; typedef lvalue_property_map_tag category; }; # endif #else template struct property_traits { typedef T value_type; typedef value_type& reference; typedef std::ptrdiff_t key_type; typedef lvalue_property_map_tag category; }; template struct property_traits { typedef T value_type; typedef const value_type& reference; typedef std::ptrdiff_t key_type; typedef lvalue_property_map_tag category; }; #endif #ifndef BOOST_MSVC // MSVC doesn't have Koenig lookup, so the user has to // do boost::get() anyways, and the using clause // doesn't really work for MSVC. } // namespace boost #endif // These need to go in global namespace because Koenig // lookup does not apply to T*. // V must be convertible to T template inline void put(T* pa, std::ptrdiff_t k, const V& val) { pa[k] = val; } template inline const T& get(const T* pa, std::ptrdiff_t k) { return pa[k]; } #ifndef BOOST_MSVC namespace boost { using ::put; using ::get; #endif //========================================================================= // concept checks for property maps template struct ReadablePropertyMapConcept { typedef typename property_traits::key_type key_type; typedef typename property_traits::reference reference; typedef typename property_traits::category Category; typedef boost::readable_property_map_tag ReadableTag; void constraints() { function_requires< ConvertibleConcept >(); val = get(pmap, k); } PMap pmap; Key k; typename property_traits::value_type val; }; template struct readable_property_map_archetype { typedef KeyArchetype key_type; typedef ValueArchetype value_type; typedef convertible_to_archetype reference; typedef readable_property_map_tag category; }; template const typename readable_property_map_archetype::reference& get(const readable_property_map_archetype&, const K&) { typedef typename readable_property_map_archetype::reference R; return static_object::get(); } template struct WritablePropertyMapConcept { typedef typename property_traits::key_type key_type; typedef typename property_traits::category Category; typedef boost::writable_property_map_tag WritableTag; void constraints() { function_requires< ConvertibleConcept >(); put(pmap, k, val); } PMap pmap; Key k; typename property_traits::value_type val; }; template struct writable_property_map_archetype { typedef KeyArchetype key_type; typedef ValueArchetype value_type; typedef void reference; typedef writable_property_map_tag category; }; template void put(const writable_property_map_archetype&, const K&, const V&) { } template struct ReadWritePropertyMapConcept { typedef typename property_traits::category Category; typedef boost::read_write_property_map_tag ReadWriteTag; void constraints() { function_requires< ReadablePropertyMapConcept >(); function_requires< WritablePropertyMapConcept >(); function_requires< ConvertibleConcept >(); } }; template struct read_write_property_map_archetype : public readable_property_map_archetype, public writable_property_map_archetype { typedef KeyArchetype key_type; typedef ValueArchetype value_type; typedef convertible_to_archetype reference; typedef read_write_property_map_tag category; }; template struct LvaluePropertyMapConcept { typedef typename property_traits::category Category; typedef boost::lvalue_property_map_tag LvalueTag; typedef typename property_traits::reference reference; void constraints() { function_requires< ReadablePropertyMapConcept >(); function_requires< ConvertibleConcept >(); typedef typename require_same< const typename property_traits::value_type&, reference>::type req; reference ref = pmap[k]; ignore_unused_variable_warning(ref); } PMap pmap; Key k; }; template struct lvalue_property_map_archetype : public readable_property_map_archetype { typedef KeyArchetype key_type; typedef ValueArchetype value_type; typedef const ValueArchetype& reference; typedef lvalue_property_map_tag category; const value_type& operator[](const key_type&) const { return static_object::get(); } }; template struct Mutable_LvaluePropertyMapConcept { typedef typename property_traits::category Category; typedef boost::lvalue_property_map_tag LvalueTag; typedef typename property_traits::reference reference; void constraints() { boost::function_requires< ReadWritePropertyMapConcept >(); boost::function_requires >(); typedef typename require_same< typename property_traits::value_type&, reference>::type req; reference ref = pmap[k]; ignore_unused_variable_warning(ref); } PMap pmap; Key k; }; template struct mutable_lvalue_property_map_archetype : public readable_property_map_archetype, public writable_property_map_archetype { typedef KeyArchetype key_type; typedef ValueArchetype value_type; typedef ValueArchetype& reference; typedef lvalue_property_map_tag category; value_type& operator[](const key_type&) const { return static_object::get(); } }; struct identity_property_map; // A helper class for constructing a property map // from a class that implements operator[] template struct put_get_helper { }; template inline Reference get(const put_get_helper& pa, const K& k) { Reference v = static_cast(pa)[k]; return v; } template inline void put(put_get_helper& pa, K k, const V& v) { static_cast(pa)[k] = v; } //========================================================================= // Adapter to turn a RandomAccessIterator into a property map template ::value_type , class R = typename std::iterator_traits::reference #endif > class iterator_property_map : public boost::put_get_helper< R, iterator_property_map > { public: typedef void key_type; typedef T value_type; typedef R reference; typedef boost::lvalue_property_map_tag category; inline iterator_property_map( RandomAccessIterator cc, const IndexMap& _id ) : iter(cc), index(_id) { } inline iterator_property_map( RandomAccessIterator cc = RandomAccessIterator() ) : iter(cc), _id(IndexMap()), index(_id), { } template inline R operator[](Key v) const { return *(iter + get(index, v)) ; } protected: RandomAccessIterator iter; IndexMap index; }; #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template inline iterator_property_map< RAIter, ID, typename std::iterator_traits::value_type, typename std::iterator_traits::reference> make_iterator_property_map(RAIter iter, ID id) { function_requires< RandomAccessIteratorConcept >(); typedef iterator_property_map< RAIter, ID, typename std::iterator_traits::value_type, typename std::iterator_traits::reference> PA; return PA(iter, id); } #endif template inline iterator_property_map make_iterator_property_map(RAIter iter, ID id, Value) { function_requires< RandomAccessIteratorConcept >(); typedef iterator_property_map PMap; return PMap(iter, id); } //========================================================================= // An adaptor to turn a Unique Pair Associative Container like std::map or // std::hash_map into an Lvalue Property Map. template class associative_property_map : public boost::put_get_helper< typename UniquePairAssociativeContainer::value_type::second_type&, associative_property_map > { typedef UniquePairAssociativeContainer C; public: typedef typename C::key_type key_type; typedef typename C::value_type::second_type value_type; typedef value_type& reference; typedef lvalue_property_map_tag category; associative_property_map(C& c) : m_c(c) { } reference operator[](const key_type& k) const { return m_c[k]; } private: C& m_c; }; template associative_property_map make_assoc_property_map(UniquePairAssociativeContainer& c) { return associative_property_map(c); } template class const_associative_property_map : public boost::put_get_helper< const typename UniquePairAssociativeContainer::value_type::second_type&, const_associative_property_map > { typedef UniquePairAssociativeContainer C; public: typedef typename C::key_type key_type; typedef typename C::value_type::second_type value_type; typedef const value_type& reference; typedef lvalue_property_map_tag category; const_associative_property_map(const C& c) : m_c(c) { } reference operator[](const key_type& k) const { return m_c[k]; } private: C& m_c; }; template const_associative_property_map make_assoc_property_map(const UniquePairAssociativeContainer& c) { return const_associative_property_map(c); } //========================================================================= // A property map that applies the identity function struct identity_property_map : public boost::put_get_helper { typedef void key_type; typedef std::size_t value_type; // ? -JGS typedef std::size_t reference; typedef boost::readable_property_map_tag category; template inline Vertex operator[](const Vertex& v) const { return v; } }; //========================================================================= // A property map that does not do anything, for // when you have to supply a property map, but don't need it. class dummy_property_map : public boost::put_get_helper< const int&, dummy_property_map > { public: typedef void key_type; typedef int value_type; struct reference { template reference& operator=(const T&) { return *this; } }; typedef boost::lvalue_property_map_tag category; inline dummy_property_map() : c(0) { } inline dummy_property_map(value_type cc) : c(cc) { } inline dummy_property_map(const dummy_property_map& x) : c(x.c) { } template inline reference operator[](Vertex) const { return reference(); } protected: value_type c; }; } // namespace boost #endif /* BOOST_PROPERTY_MAP_HPP */