diff options
Diffstat (limited to 'boost/pending/property.hpp')
-rw-r--r-- | boost/pending/property.hpp | 240 |
1 files changed, 182 insertions, 58 deletions
diff --git a/boost/pending/property.hpp b/boost/pending/property.hpp index c9880458cb..93ebffbf3b 100644 --- a/boost/pending/property.hpp +++ b/boost/pending/property.hpp @@ -7,32 +7,156 @@ #define BOOST_PROPERTY_HPP #include <boost/mpl/bool.hpp> +#include <boost/mpl/if.hpp> +#include <boost/mpl/has_xxx.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/type_traits.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; - }; + struct no_property {}; template <class Tag, class T, class Base = no_property> - struct property : public Base { + struct property { 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) { } + property(const T& v = T()) : m_value(v) { } + property(const T& v, const Base& b) : m_value(v), m_base(b) { } // copy constructor and assignment operator will be generated by compiler T m_value; + Base m_base; + }; + + // Kinds of properties + namespace graph_introspect_detail { + BOOST_MPL_HAS_XXX_TRAIT_DEF(kind) + template <typename T, bool Cond> struct get_kind {typedef void type;}; + template <typename T> struct get_kind<T, true> {typedef typename T::kind type;}; + } + + // Having a default is to make this trait work for any type, not just valid + // properties, to work around VC++ <= 10 bugs related to SFINAE in + // compressed_sparse_row_graph's get functions and similar + template <class PropertyTag> + struct property_kind: + graph_introspect_detail::get_kind<PropertyTag, graph_introspect_detail::has_kind<PropertyTag>::value> + {}; + + // Some standard properties defined independently of Boost.Graph: + enum vertex_all_t {vertex_all}; + enum edge_all_t {edge_all}; + enum graph_all_t {graph_all}; + enum vertex_bundle_t {vertex_bundle}; + enum edge_bundle_t {edge_bundle}; + enum graph_bundle_t {graph_bundle}; + + // Code to look up one property in a property list: + template <typename PList, typename PropName> + struct lookup_one_property_internal {BOOST_STATIC_CONSTANT(bool, found = false);}; + + // Special-case properties (vertex_all, edge_all, graph_all) +#define BGL_ALL_PROP(tag) \ + template <typename T> \ + struct lookup_one_property_internal<T, tag> { \ + BOOST_STATIC_CONSTANT(bool, found = true); \ + typedef T type; \ + static T& lookup(T& x, tag) {return x;} \ + static const T& lookup(const T& x, tag) {return x;} \ + }; \ + template <typename Tag, typename T, typename Base> \ + struct lookup_one_property_internal<property<Tag, T, Base>, tag> { /* Avoid ambiguity */ \ + BOOST_STATIC_CONSTANT(bool, found = true); \ + typedef property<Tag, T, Base> type; \ + static type& lookup(type& x, tag) {return x;} \ + static const type& lookup(const type& x, tag) {return x;} \ + }; + + BGL_ALL_PROP(vertex_all_t) + BGL_ALL_PROP(edge_all_t) + BGL_ALL_PROP(graph_all_t) +#undef BGL_ALL_PROP + + // *_bundled; these need to be macros rather than inheritance to resolve ambiguities + #define BGL_DO_ONE_BUNDLE_TYPE(kind) \ + template <typename T> \ + struct lookup_one_property_internal<T, BOOST_JOIN(kind, _bundle_t)> { \ + BOOST_STATIC_CONSTANT(bool, found = true); \ + typedef T type; \ + static T& lookup(T& x, BOOST_JOIN(kind, _bundle_t)) {return x;} \ + static const T& lookup(const T& x, BOOST_JOIN(kind, _bundle_t)) {return x;} \ + }; \ + \ + template <typename Tag, typename T, typename Base> \ + struct lookup_one_property_internal<property<Tag, T, Base>, BOOST_JOIN(kind, _bundle_t)>: lookup_one_property_internal<Base, BOOST_JOIN(kind, _bundle_t)> { \ + private: \ + typedef lookup_one_property_internal<Base, BOOST_JOIN(kind, _bundle_t)> base_type; \ + public: \ + static typename base_type::type& lookup(property<Tag, T, Base>& p, BOOST_JOIN(kind, _bundle_t)) {return base_type::lookup(p.m_base, BOOST_JOIN(kind, _bundle_t)());} \ + static const typename base_type::type& lookup(const property<Tag, T, Base>& p, BOOST_JOIN(kind, _bundle_t)) {return base_type::lookup(p.m_base, BOOST_JOIN(kind, _bundle_t)());} \ + }; \ + + BGL_DO_ONE_BUNDLE_TYPE(vertex) + BGL_DO_ONE_BUNDLE_TYPE(edge) + BGL_DO_ONE_BUNDLE_TYPE(graph) +#undef BGL_DO_ONE_BUNDLE_TYPE + + // Normal old-style properties; second case also handles chaining of bundled property accesses + template <typename Tag, typename T, typename Base> + struct lookup_one_property_internal<boost::property<Tag, T, Base>, Tag> { + BOOST_STATIC_CONSTANT(bool, found = true); + typedef property<Tag, T, Base> prop; + typedef T type; + template <typename U> + static typename enable_if<is_same<prop, U>, T&>::type + lookup(U& prop, const Tag&) {return prop.m_value;} + template <typename U> + static typename enable_if<is_same<prop, U>, const T&>::type + lookup(const U& prop, const Tag&) {return prop.m_value;} + }; + + template <typename Tag, typename T, typename Base, typename PropName> + struct lookup_one_property_internal<boost::property<Tag, T, Base>, PropName>: lookup_one_property_internal<Base, PropName> { + private: + typedef lookup_one_property_internal<Base, PropName> base_type; + public: + template <typename PL> + static typename enable_if<is_same<PL, boost::property<Tag, T, Base> >, typename base_type::type&>::type + lookup(PL& prop, const PropName& tag) { + return base_type::lookup(prop.m_base, tag); + } + template <typename PL> + static typename enable_if<is_same<PL, boost::property<Tag, T, Base> >, const typename base_type::type&>::type + lookup(const PL& prop, const PropName& tag) { + return base_type::lookup(prop.m_base, tag); + } + }; + + // Pointer-to-member access to bundled properties +#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES + template <typename T, typename R> + struct lookup_one_property_internal<T, R T::*> { + BOOST_STATIC_CONSTANT(bool, found = true); + typedef R type; + static R& lookup(T& x, R T::*ptr) {return x.*ptr;} + static const R& lookup(const T& x, R T::*ptr) {return x.*ptr;} + }; +#endif + + // Version of above handling const property lists properly + template <typename T, typename Tag> + struct lookup_one_property: lookup_one_property_internal<T, Tag> {}; + + template <typename T, typename Tag> + struct lookup_one_property<const T, Tag> { + BOOST_STATIC_CONSTANT(bool, found = (lookup_one_property_internal<T, Tag>::found)); + typedef const typename lookup_one_property_internal<T, Tag>::type type; + template <typename U> + static typename enable_if<is_same<T, U>, const typename lookup_one_property_internal<T, Tag>::type&>::type + lookup(const U& p, Tag tag) { + return lookup_one_property_internal<T, Tag>::lookup(p, tag); + } }; // The BGL properties specialize property_kind and @@ -41,11 +165,6 @@ namespace boost { // 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 <> @@ -58,45 +177,18 @@ namespace boost { 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 - }; + struct property_value: lookup_one_property<PropertyList, Tag> {}; - template <class Tag2> - inline detail::error_property_not_found - get_property_value(const no_property&, Tag2) { - return detail::error_property_not_found(); + template <class PropertyList, class Tag> + inline typename lookup_one_property<PropertyList, Tag>::type& + get_property_value(PropertyList& p, Tag tag) { + return lookup_one_property<PropertyList, Tag>::lookup(p, tag); } - 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); + template <class PropertyList, class Tag> + inline const typename lookup_one_property<PropertyList, Tag>::type& + get_property_value(const PropertyList& p, Tag tag) { + return lookup_one_property<PropertyList, Tag>::lookup(p, tag); } namespace detail { @@ -107,7 +199,6 @@ namespace boost { : 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 @@ -159,7 +250,40 @@ namespace boost { typedef no_property retagged; }; //@} -#endif + + template <typename PList, typename Tag> + class lookup_one_property_f; + + template <typename PList, typename Tag, typename F> struct lookup_one_property_f_result; + + template <typename PList, typename Tag> + struct lookup_one_property_f_result<PList, Tag, const lookup_one_property_f<PList, Tag>(PList)> { + typedef typename lookup_one_property<PList, Tag>::type type; + }; + + template <typename PList, typename Tag> + struct lookup_one_property_f_result<PList, Tag, const lookup_one_property_f<PList, Tag>(PList&)> { + typedef typename lookup_one_property<PList, Tag>::type& type; + }; + + template <typename PList, typename Tag> + struct lookup_one_property_f_result<PList, Tag, const lookup_one_property_f<PList, Tag>(const PList&)> { + typedef const typename lookup_one_property<PList, Tag>::type& type; + }; + + template <typename PList, typename Tag> + class lookup_one_property_f { + Tag tag; + public: + lookup_one_property_f(Tag tag): tag(tag) {} + template <typename F> struct result: lookup_one_property_f_result<PList, Tag, F> {}; + + typename lookup_one_property_f_result<PList, Tag, const lookup_one_property_f(PList&)>::type + operator()(PList& pl) const { + return lookup_one_property<PList, Tag>::lookup(pl, tag); + } + }; + } // namespace detail } // namesapce boost |