source: NonGTP/Boost/boost/pending/detail/property.hpp @ 857

Revision 857, 5.8 KB checked in by igarcia, 18 years ago (diff)
Line 
1//  (C) Copyright Jeremy Siek 2004
2//  Distributed under the Boost Software License, Version 1.0. (See
3//  accompanying file LICENSE_1_0.txt or copy at
4//  http://www.boost.org/LICENSE_1_0.txt)
5
6#ifndef BOOST_DETAIL_PROPERTY_HPP
7#define BOOST_DETAIL_PROPERTY_HPP
8
9#include <utility> // for std::pair
10#include <boost/type_traits/same_traits.hpp> // for is_same
11
12namespace boost {
13
14  namespace detail {
15
16    template <class PropertyTag1, class PropertyTag2>
17    struct same_property {
18      enum { value = is_same<PropertyTag1,PropertyTag2>::value };
19    };
20
21    struct error_property_not_found { };
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    };
119#else
120    // VC++ workaround:
121    // The main idea here is to replace partial specialization with
122    // nested template member classes. Of course there is the
123    // further complication that the outer class of the nested
124    // template class cannot itself be a template class.
125    // Hence the need for the ev_selector. -JGS
126
127    struct recursive_extract;
128    struct end_extract;
129
130    template <class TagValueAList>
131    struct ev_selector { typedef recursive_extract type; };
132    template <>
133    struct ev_selector<no_property> { typedef end_extract type; };
134
135    struct recursive_extract {
136      template <class TagValueAList, class Tag1>
137      struct bind_ {
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
156
157  } // namespace detail
158} // namespace boost
159
160#endif // BOOST_DETAIL_PROPERTY_HPP
Note: See TracBrowser for help on using the repository browser.