123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- // (C) Copyright Jeremy Siek 2004
- // Distributed under the Boost Software License, Version 1.0. (See
- // accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- #ifndef BOOST_PROPERTY_HPP
- #define BOOST_PROPERTY_HPP
- #include <boost/mpl/bool.hpp>
- namespace boost {
- struct no_property {
- typedef no_property tag_type;
- typedef no_property next_type;
- typedef no_property value_type;
- enum { num = 0 };
- typedef void kind;
- };
- template <class Tag, class T, class Base = no_property>
- struct property : public Base {
- typedef Base next_type;
- typedef Tag tag_type;
- typedef T value_type;
- #if BOOST_WORKAROUND (__GNUC__, < 3)
- property() { }
- #else
- property() : m_value() { }
- #endif
- property(const T& v) : m_value(v) { }
- property(const T& v, const Base& b) : Base(b), m_value(v) { }
- // copy constructor and assignment operator will be generated by compiler
- T m_value;
- };
- // The BGL properties specialize property_kind and
- // property_num, and use enum's for the Property type (see
- // graph/properties.hpp), but the user may want to use a class
- // instead with a nested kind type and num. Also, we may want to
- // switch BGL back to using class types for properties at some point.
- template <class PropertyTag>
- struct property_kind {
- typedef typename PropertyTag::kind type;
- };
- template <class P>
- struct has_property : boost::mpl::true_ {};
- template <>
- struct has_property<no_property> : boost::mpl::false_ {};
- } // namespace boost
- #include <boost/pending/detail/property.hpp>
- namespace boost {
- template <class PropertyList, class Tag>
- struct property_value {
- #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
- typedef typename detail::build_property_tag_value_alist<PropertyList>::type AList;
- typedef typename detail::extract_value<AList,Tag>::type type;
- #else
- typedef typename detail::build_property_tag_value_alist<PropertyList>::type AList;
- typedef typename detail::ev_selector<AList>::type Extractor;
- typedef typename Extractor::template bind_<AList,Tag>::type type;
- #endif
- };
- template <class Tag2>
- inline detail::error_property_not_found
- get_property_value(const no_property& p, Tag2) {
- return detail::error_property_not_found();
- }
- template <class Tag1, class Tag2, class T1, class Base>
- inline typename property_value<property<Tag1,T1,Base>, Tag2>::type&
- get_property_value(property<Tag1,T1,Base>& p, Tag2 tag2) {
- BOOST_STATIC_CONSTANT(bool,
- match = (detail::same_property<Tag1,Tag2>::value));
- typedef property<Tag1,T1,Base> Prop;
- typedef typename property_value<Prop, Tag2>::type T2;
- T2* t2 = 0;
- typedef detail::property_value_dispatch<match> Dispatcher;
- return Dispatcher::get_value(p, t2, tag2);
- }
- template <class Tag1, class Tag2, class T1, class Base>
- inline
- const typename property_value<property<Tag1,T1,Base>, Tag2>::type&
- get_property_value(const property<Tag1,T1,Base>& p, Tag2 tag2) {
- BOOST_STATIC_CONSTANT(bool,
- match = (detail::same_property<Tag1,Tag2>::value));
- typedef property<Tag1,T1,Base> Prop;
- typedef typename property_value<Prop, Tag2>::type T2;
- T2* t2 = 0;
- typedef detail::property_value_dispatch<match> Dispatcher;
- return Dispatcher::const_get_value(p, t2, tag2);
- }
- namespace detail {
- /** This trait returns true if T is no_property. */
- template <typename T>
- struct is_no_property
- : mpl::bool_<is_same<T, no_property>::value>
- { };
- #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
- /** @internal @name Retag Property List
- * This metafunction is used internally to normalize a property if it is
- * actually modeling a property. Specifically this is used in Boost.Graph
- * to map user-provided classes into bundled properties.
- */
- //@{
- // One base case of the recursive form (see below). This matches any
- // retag request that does not include a property<...> or no_property as
- // the FinalType. This is used for generating bundles in Boost.Graph.
- template<typename FinalTag, typename FinalType>
- struct retag_property_list
- {
- typedef property<FinalTag, FinalType> type;
- typedef FinalType retagged;
- };
- // Recursively retag the nested property list.
- template<typename FinalTag, typename Tag, typename T, typename Base>
- struct retag_property_list<FinalTag, property<Tag, T, Base> >
- {
- private:
- typedef retag_property_list<FinalTag, Base> next;
- public:
- typedef property<Tag, T, typename next::type> type;
- typedef typename next::retagged retagged;
- };
- // This base case will correctly deduce the final property type if the
- // retagged property is given in property form. This should not hide
- // the base case below.
- // NOTE: This addresses a problem of layering bundled properties in the BGL
- // where multiple retaggings will fail to deduce the correct retagged
- // type.
- template<typename FinalTag, typename FinalType>
- struct retag_property_list<FinalTag, property<FinalTag, FinalType> >
- {
- public:
- typedef property<FinalTag, FinalType> type;
- typedef FinalType retagged;
- };
- // A final base case of the retag_propert_list, this will terminate a
- // properly structured list.
- template<typename FinalTag>
- struct retag_property_list<FinalTag, no_property>
- {
- typedef no_property type;
- typedef no_property retagged;
- };
- //@}
- #endif
- } // namespace detail
- } // namesapce boost
- #endif /* BOOST_PROPERTY_HPP */
|