epoc32/include/stdapis/boost/pending/detail/property.hpp
branchSymbian3
changeset 4 837f303aceeb
parent 3 e1b950c65cb4
--- a/epoc32/include/stdapis/boost/pending/detail/property.hpp	Wed Mar 31 12:27:01 2010 +0100
+++ b/epoc32/include/stdapis/boost/pending/detail/property.hpp	Wed Mar 31 12:33:34 2010 +0100
@@ -3,130 +3,158 @@
 //  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/pending/ct_if.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
+#ifndef BOOST_DETAIL_PROPERTY_HPP
+#define BOOST_DETAIL_PROPERTY_HPP
 
-    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_STATIC_CONSTANT(bool, value = true);
-    typedef true_type type;
-  };
-  template <>
-  struct has_property<no_property> { 
-    BOOST_STATIC_CONSTANT(bool, value = false); 
-    typedef false_type type; 
-  };
-
-} // namespace boost
-
-#include <boost/pending/detail/property.hpp>
+#include <utility> // for std::pair
+#include <boost/type_traits/same_traits.hpp> // for is_same
 
 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  
-  };
+  namespace detail {
+
+    template <class PropertyTag1, class PropertyTag2>
+    struct same_property {
+      enum { value = is_same<PropertyTag1,PropertyTag2>::value };
+    };
+
+    struct error_property_not_found { };
+
+    template <int TagMatched>
+    struct property_value_dispatch {
+      template <class PropertyTag, class T, class Tag>
+      inline static T& get_value(PropertyTag& p, T*, Tag) {
+        return p.m_value; 
+      }
+      template <class PropertyTag, class T, class Tag>
+      inline static const T& const_get_value(const PropertyTag& p, T*, Tag) {
+        return p.m_value; 
+      }
+    };
+
+    template <class PropertyList>
+    struct property_value_end {
+      template <class T> struct result { typedef T type; };
+
+      template <class T, class Tag>
+      inline static T& get_value(PropertyList& p, T* t, Tag tag) {
+        typedef typename PropertyList::next_type Next;
+        typedef typename Next::tag_type Next_tag;
+        enum { match = same_property<Next_tag,Tag>::value };
+        return property_value_dispatch<match>
+          ::get_value(static_cast<Next&>(p), t, tag);
+      }
+      template <class T, class Tag>
+      inline static const T& const_get_value(const PropertyList& p, T* t, Tag tag) {
+        typedef typename PropertyList::next_type Next;
+        typedef typename Next::tag_type Next_tag;
+        enum { match = same_property<Next_tag,Tag>::value };
+        return property_value_dispatch<match>
+          ::const_get_value(static_cast<const Next&>(p), t, tag);
+      }
+    };
+    template <>
+    struct property_value_end<no_property> {
+      template <class T> struct result { 
+        typedef detail::error_property_not_found type; 
+      };
+
+      // Stop the recursion and return error
+      template <class T, class Tag>
+      inline static detail::error_property_not_found&
+      get_value(no_property&, T*, Tag) {
+        static error_property_not_found s_prop_not_found;
+        return s_prop_not_found;
+      }
+      template <class T, class Tag>
+      inline static const detail::error_property_not_found&
+      const_get_value(const no_property&, T*, Tag) {
+        static error_property_not_found s_prop_not_found;
+        return s_prop_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);
-  }
+    template <>
+    struct property_value_dispatch<0> {
+      template <class PropertyList, class T, class Tag>
+      inline static typename property_value_end<PropertyList>::template result<T>::type&
+      get_value(PropertyList& p, T* t, Tag tag) {
+        return property_value_end<PropertyList>::get_value(p, t, tag);
+      }
+      template <class PropertyList, class T, class Tag>
+      inline static const typename property_value_end<PropertyList>::template result<T>::type&
+      const_get_value(const PropertyList& p, T* t, Tag tag) {
+        return property_value_end<PropertyList>::const_get_value(p, t, tag);
+      }
+    };
+
+    template <class PropertyList>
+    struct build_property_tag_value_alist
+    {
+      typedef typename PropertyList::next_type NextProperty;
+      typedef typename PropertyList::value_type Value;
+      typedef typename PropertyList::tag_type Tag;
+      typedef typename build_property_tag_value_alist<NextProperty>::type Next;
+      typedef std::pair< std::pair<Tag,Value>, Next> type;
+    };
+    template <>
+    struct build_property_tag_value_alist<no_property>
+    {
+      typedef no_property type;
+    };
 
- namespace detail {
-#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
-   template<typename FinalTag, typename FinalType>
-   struct retag_property_list
-   {
-     typedef property<FinalTag, FinalType> type;
-     typedef FinalType retagged;
-   };
+#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+    template <class TagValueAList, class Tag>
+    struct extract_value {
+      typedef error_property_not_found type;
+    };
+    template <class Value, class Tag1, class Tag2, class Rest>
+    struct extract_value< std::pair<std::pair<Tag1,Value>,Rest>, Tag2> {
+      typedef typename extract_value<Rest,Tag2>::type type;
+    };
+    template <class Value, class Tag, class Rest>
+    struct extract_value< std::pair<std::pair<Tag,Value>,Rest>, Tag> {
+      typedef Value type;
+    };
+#else
+    // VC++ workaround:
+    // The main idea here is to replace partial specialization with
+    // nested template member classes. Of course there is the
+    // further complication that the outer class of the nested
+    // template class cannot itself be a template class.
+    // Hence the need for the ev_selector. -JGS
 
-   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;
+    struct recursive_extract;
+    struct end_extract;
 
-   public:
-     typedef property<Tag, T, typename next::type> type;
-     typedef typename next::retagged retagged;
-   };
+    template <class TagValueAList>
+    struct ev_selector { typedef recursive_extract type; };
+    template <>
+    struct ev_selector<no_property> { typedef end_extract type; };
 
-   template<typename FinalTag>
-   struct retag_property_list<FinalTag, no_property>
-   {
-     typedef no_property type;
-     typedef no_property retagged;
-   };
-#endif
-  }
-} // namesapce boost
+    struct recursive_extract {
+      template <class TagValueAList, class Tag1>
+      struct bind_ {
+        typedef typename TagValueAList::first_type AListFirst;
+        typedef typename AListFirst::first_type Tag2;
+        typedef typename AListFirst::second_type Value;
+        enum { match = same_property<Tag1,Tag2>::value };
+        typedef typename TagValueAList::second_type Next;
+        typedef typename ev_selector<Next>::type Extractor;
+        typedef typename boost::ct_if< match, Value, 
+          typename Extractor::template bind_<Next,Tag1>::type
+        >::type type;
+      };
+    };
+    struct end_extract {
+      template <class AList, class Tag1>
+      struct bind_ {
+        typedef error_property_not_found type;
+      };
+    };
+#endif //!defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 
-#endif /* BOOST_PROPERTY_HPP */
+  } // namespace detail 
+} // namespace boost
+
+#endif // BOOST_DETAIL_PROPERTY_HPP