epoc32/include/stdapis/boost/pending/detail/property.hpp
branchSymbian3
changeset 4 837f303aceeb
parent 3 e1b950c65cb4
equal deleted inserted replaced
3:e1b950c65cb4 4:837f303aceeb
     1 //  (C) Copyright Jeremy Siek 2004 
     1 //  (C) Copyright Jeremy Siek 2004 
     2 //  Distributed under the Boost Software License, Version 1.0. (See
     2 //  Distributed under the Boost Software License, Version 1.0. (See
     3 //  accompanying file LICENSE_1_0.txt or copy at
     3 //  accompanying file LICENSE_1_0.txt or copy at
     4 //  http://www.boost.org/LICENSE_1_0.txt)
     4 //  http://www.boost.org/LICENSE_1_0.txt)
     5 
     5 
     6 #ifndef BOOST_PROPERTY_HPP
     6 #ifndef BOOST_DETAIL_PROPERTY_HPP
     7 #define BOOST_PROPERTY_HPP
     7 #define BOOST_DETAIL_PROPERTY_HPP
     8 
     8 
     9 #include <boost/pending/ct_if.hpp>
     9 #include <utility> // for std::pair
       
    10 #include <boost/type_traits/same_traits.hpp> // for is_same
    10 
    11 
    11 namespace boost {
    12 namespace boost {
    12 
    13 
    13   struct no_property { 
    14   namespace detail {
    14     typedef no_property tag_type;
       
    15     typedef no_property next_type;
       
    16     typedef no_property value_type;
       
    17     enum { num = 0 };
       
    18     typedef void kind;
       
    19   };
       
    20 
    15 
    21   template <class Tag, class T, class Base = no_property>
    16     template <class PropertyTag1, class PropertyTag2>
    22   struct property : public Base {
    17     struct same_property {
    23     typedef Base next_type;
    18       enum { value = is_same<PropertyTag1,PropertyTag2>::value };
    24     typedef Tag tag_type;
    19     };
    25     typedef T value_type;
    20 
    26 #if BOOST_WORKAROUND (__GNUC__, < 3)
    21     struct error_property_not_found { };
    27     property() { }
    22 
       
    23     template <int TagMatched>
       
    24     struct property_value_dispatch {
       
    25       template <class PropertyTag, class T, class Tag>
       
    26       inline static T& get_value(PropertyTag& p, T*, Tag) {
       
    27         return p.m_value; 
       
    28       }
       
    29       template <class PropertyTag, class T, class Tag>
       
    30       inline static const T& const_get_value(const PropertyTag& p, T*, Tag) {
       
    31         return p.m_value; 
       
    32       }
       
    33     };
       
    34 
       
    35     template <class PropertyList>
       
    36     struct property_value_end {
       
    37       template <class T> struct result { typedef T type; };
       
    38 
       
    39       template <class T, class Tag>
       
    40       inline static T& get_value(PropertyList& p, T* t, Tag tag) {
       
    41         typedef typename PropertyList::next_type Next;
       
    42         typedef typename Next::tag_type Next_tag;
       
    43         enum { match = same_property<Next_tag,Tag>::value };
       
    44         return property_value_dispatch<match>
       
    45           ::get_value(static_cast<Next&>(p), t, tag);
       
    46       }
       
    47       template <class T, class Tag>
       
    48       inline static const T& const_get_value(const PropertyList& p, T* t, Tag tag) {
       
    49         typedef typename PropertyList::next_type Next;
       
    50         typedef typename Next::tag_type Next_tag;
       
    51         enum { match = same_property<Next_tag,Tag>::value };
       
    52         return property_value_dispatch<match>
       
    53           ::const_get_value(static_cast<const Next&>(p), t, tag);
       
    54       }
       
    55     };
       
    56     template <>
       
    57     struct property_value_end<no_property> {
       
    58       template <class T> struct result { 
       
    59         typedef detail::error_property_not_found type; 
       
    60       };
       
    61 
       
    62       // Stop the recursion and return error
       
    63       template <class T, class Tag>
       
    64       inline static detail::error_property_not_found&
       
    65       get_value(no_property&, T*, Tag) {
       
    66         static error_property_not_found s_prop_not_found;
       
    67         return s_prop_not_found;
       
    68       }
       
    69       template <class T, class Tag>
       
    70       inline static const detail::error_property_not_found&
       
    71       const_get_value(const no_property&, T*, Tag) {
       
    72         static error_property_not_found s_prop_not_found;
       
    73         return s_prop_not_found;
       
    74       }
       
    75     };
       
    76 
       
    77     template <>
       
    78     struct property_value_dispatch<0> {
       
    79       template <class PropertyList, class T, class Tag>
       
    80       inline static typename property_value_end<PropertyList>::template result<T>::type&
       
    81       get_value(PropertyList& p, T* t, Tag tag) {
       
    82         return property_value_end<PropertyList>::get_value(p, t, tag);
       
    83       }
       
    84       template <class PropertyList, class T, class Tag>
       
    85       inline static const typename property_value_end<PropertyList>::template result<T>::type&
       
    86       const_get_value(const PropertyList& p, T* t, Tag tag) {
       
    87         return property_value_end<PropertyList>::const_get_value(p, t, tag);
       
    88       }
       
    89     };
       
    90 
       
    91     template <class PropertyList>
       
    92     struct build_property_tag_value_alist
       
    93     {
       
    94       typedef typename PropertyList::next_type NextProperty;
       
    95       typedef typename PropertyList::value_type Value;
       
    96       typedef typename PropertyList::tag_type Tag;
       
    97       typedef typename build_property_tag_value_alist<NextProperty>::type Next;
       
    98       typedef std::pair< std::pair<Tag,Value>, Next> type;
       
    99     };
       
   100     template <>
       
   101     struct build_property_tag_value_alist<no_property>
       
   102     {
       
   103       typedef no_property type;
       
   104     };
       
   105 
       
   106 #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
       
   107     template <class TagValueAList, class Tag>
       
   108     struct extract_value {
       
   109       typedef error_property_not_found type;
       
   110     };
       
   111     template <class Value, class Tag1, class Tag2, class Rest>
       
   112     struct extract_value< std::pair<std::pair<Tag1,Value>,Rest>, Tag2> {
       
   113       typedef typename extract_value<Rest,Tag2>::type type;
       
   114     };
       
   115     template <class Value, class Tag, class Rest>
       
   116     struct extract_value< std::pair<std::pair<Tag,Value>,Rest>, Tag> {
       
   117       typedef Value type;
       
   118     };
    28 #else
   119 #else
    29     property() : m_value() { }
   120     // VC++ workaround:
    30 #endif
   121     // The main idea here is to replace partial specialization with
    31     property(const T& v) : m_value(v) { }
   122     // nested template member classes. Of course there is the
    32     property(const T& v, const Base& b) : Base(b), m_value(v) { }
   123     // further complication that the outer class of the nested
    33     // copy constructor and assignment operator will be generated by compiler
   124     // template class cannot itself be a template class.
       
   125     // Hence the need for the ev_selector. -JGS
    34 
   126 
    35     T m_value;
   127     struct recursive_extract;
    36   };
   128     struct end_extract;
    37 
   129 
    38   // The BGL properties specialize property_kind and
   130     template <class TagValueAList>
    39   // property_num, and use enum's for the Property type (see
   131     struct ev_selector { typedef recursive_extract type; };
    40   // graph/properties.hpp), but the user may want to use a class
   132     template <>
    41   // instead with a nested kind type and num.  Also, we may want to
   133     struct ev_selector<no_property> { typedef end_extract type; };
    42   // switch BGL back to using class types for properties at some point.
       
    43 
   134 
    44   template <class PropertyTag>
   135     struct recursive_extract {
    45   struct property_kind {
   136       template <class TagValueAList, class Tag1>
    46     typedef typename PropertyTag::kind type;
   137       struct bind_ {
    47   };
   138         typedef typename TagValueAList::first_type AListFirst;
       
   139         typedef typename AListFirst::first_type Tag2;
       
   140         typedef typename AListFirst::second_type Value;
       
   141         enum { match = same_property<Tag1,Tag2>::value };
       
   142         typedef typename TagValueAList::second_type Next;
       
   143         typedef typename ev_selector<Next>::type Extractor;
       
   144         typedef typename boost::ct_if< match, Value, 
       
   145           typename Extractor::template bind_<Next,Tag1>::type
       
   146         >::type type;
       
   147       };
       
   148     };
       
   149     struct end_extract {
       
   150       template <class AList, class Tag1>
       
   151       struct bind_ {
       
   152         typedef error_property_not_found type;
       
   153       };
       
   154     };
       
   155 #endif //!defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
    48 
   156 
    49   template <class P>
   157   } // namespace detail 
    50   struct has_property { 
       
    51     BOOST_STATIC_CONSTANT(bool, value = true);
       
    52     typedef true_type type;
       
    53   };
       
    54   template <>
       
    55   struct has_property<no_property> { 
       
    56     BOOST_STATIC_CONSTANT(bool, value = false); 
       
    57     typedef false_type type; 
       
    58   };
       
    59 
       
    60 } // namespace boost
   158 } // namespace boost
    61 
   159 
    62 #include <boost/pending/detail/property.hpp>
   160 #endif // BOOST_DETAIL_PROPERTY_HPP
    63 
       
    64 namespace boost {
       
    65 
       
    66   template <class PropertyList, class Tag>
       
    67   struct property_value {
       
    68 #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
       
    69     typedef typename detail::build_property_tag_value_alist<PropertyList>::type AList;
       
    70     typedef typename detail::extract_value<AList,Tag>::type type;
       
    71 #else
       
    72     typedef typename detail::build_property_tag_value_alist<PropertyList>::type AList;
       
    73     typedef typename detail::ev_selector<AList>::type Extractor;
       
    74     typedef typename Extractor::template bind_<AList,Tag>::type type;
       
    75 #endif  
       
    76   };
       
    77 
       
    78   template <class Tag1, class Tag2, class T1, class Base>
       
    79   inline typename property_value<property<Tag1,T1,Base>, Tag2>::type& 
       
    80   get_property_value(property<Tag1,T1,Base>& p, Tag2 tag2) {
       
    81     BOOST_STATIC_CONSTANT(bool, 
       
    82                           match = (detail::same_property<Tag1,Tag2>::value));
       
    83     typedef property<Tag1,T1,Base> Prop;
       
    84     typedef typename property_value<Prop, Tag2>::type T2;
       
    85     T2* t2 = 0;
       
    86     typedef detail::property_value_dispatch<match> Dispatcher;
       
    87     return Dispatcher::get_value(p, t2, tag2);
       
    88   }
       
    89   template <class Tag1, class Tag2, class T1, class Base>
       
    90   inline
       
    91   const typename property_value<property<Tag1,T1,Base>, Tag2>::type& 
       
    92   get_property_value(const property<Tag1,T1,Base>& p, Tag2 tag2) {
       
    93     BOOST_STATIC_CONSTANT(bool, 
       
    94                           match = (detail::same_property<Tag1,Tag2>::value));
       
    95     typedef property<Tag1,T1,Base> Prop;
       
    96     typedef typename property_value<Prop, Tag2>::type T2;
       
    97     T2* t2 = 0;
       
    98     typedef detail::property_value_dispatch<match> Dispatcher;
       
    99     return Dispatcher::const_get_value(p, t2, tag2);
       
   100   }
       
   101 
       
   102  namespace detail {
       
   103 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
       
   104    template<typename FinalTag, typename FinalType>
       
   105    struct retag_property_list
       
   106    {
       
   107      typedef property<FinalTag, FinalType> type;
       
   108      typedef FinalType retagged;
       
   109    };
       
   110 
       
   111    template<typename FinalTag, typename Tag, typename T, typename Base>
       
   112    struct retag_property_list<FinalTag, property<Tag, T, Base> >
       
   113    {
       
   114    private:
       
   115      typedef retag_property_list<FinalTag, Base> next;
       
   116 
       
   117    public:
       
   118      typedef property<Tag, T, typename next::type> type;
       
   119      typedef typename next::retagged retagged;
       
   120    };
       
   121 
       
   122    template<typename FinalTag>
       
   123    struct retag_property_list<FinalTag, no_property>
       
   124    {
       
   125      typedef no_property type;
       
   126      typedef no_property retagged;
       
   127    };
       
   128 #endif
       
   129   }
       
   130 } // namesapce boost
       
   131 
       
   132 #endif /* BOOST_PROPERTY_HPP */