williamr@2
|
1 |
// (C) Copyright Jeremy Siek 2004
|
williamr@2
|
2 |
// Distributed under the Boost Software License, Version 1.0. (See
|
williamr@2
|
3 |
// accompanying file LICENSE_1_0.txt or copy at
|
williamr@2
|
4 |
// http://www.boost.org/LICENSE_1_0.txt)
|
williamr@2
|
5 |
|
williamr@4
|
6 |
#ifndef BOOST_DETAIL_PROPERTY_HPP
|
williamr@4
|
7 |
#define BOOST_DETAIL_PROPERTY_HPP
|
williamr@2
|
8 |
|
williamr@4
|
9 |
#include <utility> // for std::pair
|
williamr@4
|
10 |
#include <boost/type_traits/same_traits.hpp> // for is_same
|
williamr@2
|
11 |
|
williamr@2
|
12 |
namespace boost {
|
williamr@2
|
13 |
|
williamr@4
|
14 |
namespace detail {
|
williamr@2
|
15 |
|
williamr@4
|
16 |
template <class PropertyTag1, class PropertyTag2>
|
williamr@4
|
17 |
struct same_property {
|
williamr@4
|
18 |
enum { value = is_same<PropertyTag1,PropertyTag2>::value };
|
williamr@4
|
19 |
};
|
williamr@4
|
20 |
|
williamr@4
|
21 |
struct error_property_not_found { };
|
williamr@4
|
22 |
|
williamr@4
|
23 |
template <int TagMatched>
|
williamr@4
|
24 |
struct property_value_dispatch {
|
williamr@4
|
25 |
template <class PropertyTag, class T, class Tag>
|
williamr@4
|
26 |
inline static T& get_value(PropertyTag& p, T*, Tag) {
|
williamr@4
|
27 |
return p.m_value;
|
williamr@4
|
28 |
}
|
williamr@4
|
29 |
template <class PropertyTag, class T, class Tag>
|
williamr@4
|
30 |
inline static const T& const_get_value(const PropertyTag& p, T*, Tag) {
|
williamr@4
|
31 |
return p.m_value;
|
williamr@4
|
32 |
}
|
williamr@4
|
33 |
};
|
williamr@4
|
34 |
|
williamr@4
|
35 |
template <class PropertyList>
|
williamr@4
|
36 |
struct property_value_end {
|
williamr@4
|
37 |
template <class T> struct result { typedef T type; };
|
williamr@4
|
38 |
|
williamr@4
|
39 |
template <class T, class Tag>
|
williamr@4
|
40 |
inline static T& get_value(PropertyList& p, T* t, Tag tag) {
|
williamr@4
|
41 |
typedef typename PropertyList::next_type Next;
|
williamr@4
|
42 |
typedef typename Next::tag_type Next_tag;
|
williamr@4
|
43 |
enum { match = same_property<Next_tag,Tag>::value };
|
williamr@4
|
44 |
return property_value_dispatch<match>
|
williamr@4
|
45 |
::get_value(static_cast<Next&>(p), t, tag);
|
williamr@4
|
46 |
}
|
williamr@4
|
47 |
template <class T, class Tag>
|
williamr@4
|
48 |
inline static const T& const_get_value(const PropertyList& p, T* t, Tag tag) {
|
williamr@4
|
49 |
typedef typename PropertyList::next_type Next;
|
williamr@4
|
50 |
typedef typename Next::tag_type Next_tag;
|
williamr@4
|
51 |
enum { match = same_property<Next_tag,Tag>::value };
|
williamr@4
|
52 |
return property_value_dispatch<match>
|
williamr@4
|
53 |
::const_get_value(static_cast<const Next&>(p), t, tag);
|
williamr@4
|
54 |
}
|
williamr@4
|
55 |
};
|
williamr@4
|
56 |
template <>
|
williamr@4
|
57 |
struct property_value_end<no_property> {
|
williamr@4
|
58 |
template <class T> struct result {
|
williamr@4
|
59 |
typedef detail::error_property_not_found type;
|
williamr@4
|
60 |
};
|
williamr@4
|
61 |
|
williamr@4
|
62 |
// Stop the recursion and return error
|
williamr@4
|
63 |
template <class T, class Tag>
|
williamr@4
|
64 |
inline static detail::error_property_not_found&
|
williamr@4
|
65 |
get_value(no_property&, T*, Tag) {
|
williamr@4
|
66 |
static error_property_not_found s_prop_not_found;
|
williamr@4
|
67 |
return s_prop_not_found;
|
williamr@4
|
68 |
}
|
williamr@4
|
69 |
template <class T, class Tag>
|
williamr@4
|
70 |
inline static const detail::error_property_not_found&
|
williamr@4
|
71 |
const_get_value(const no_property&, T*, Tag) {
|
williamr@4
|
72 |
static error_property_not_found s_prop_not_found;
|
williamr@4
|
73 |
return s_prop_not_found;
|
williamr@4
|
74 |
}
|
williamr@4
|
75 |
};
|
williamr@4
|
76 |
|
williamr@4
|
77 |
template <>
|
williamr@4
|
78 |
struct property_value_dispatch<0> {
|
williamr@4
|
79 |
template <class PropertyList, class T, class Tag>
|
williamr@4
|
80 |
inline static typename property_value_end<PropertyList>::template result<T>::type&
|
williamr@4
|
81 |
get_value(PropertyList& p, T* t, Tag tag) {
|
williamr@4
|
82 |
return property_value_end<PropertyList>::get_value(p, t, tag);
|
williamr@4
|
83 |
}
|
williamr@4
|
84 |
template <class PropertyList, class T, class Tag>
|
williamr@4
|
85 |
inline static const typename property_value_end<PropertyList>::template result<T>::type&
|
williamr@4
|
86 |
const_get_value(const PropertyList& p, T* t, Tag tag) {
|
williamr@4
|
87 |
return property_value_end<PropertyList>::const_get_value(p, t, tag);
|
williamr@4
|
88 |
}
|
williamr@4
|
89 |
};
|
williamr@4
|
90 |
|
williamr@4
|
91 |
template <class PropertyList>
|
williamr@4
|
92 |
struct build_property_tag_value_alist
|
williamr@4
|
93 |
{
|
williamr@4
|
94 |
typedef typename PropertyList::next_type NextProperty;
|
williamr@4
|
95 |
typedef typename PropertyList::value_type Value;
|
williamr@4
|
96 |
typedef typename PropertyList::tag_type Tag;
|
williamr@4
|
97 |
typedef typename build_property_tag_value_alist<NextProperty>::type Next;
|
williamr@4
|
98 |
typedef std::pair< std::pair<Tag,Value>, Next> type;
|
williamr@4
|
99 |
};
|
williamr@4
|
100 |
template <>
|
williamr@4
|
101 |
struct build_property_tag_value_alist<no_property>
|
williamr@4
|
102 |
{
|
williamr@4
|
103 |
typedef no_property type;
|
williamr@4
|
104 |
};
|
williamr@4
|
105 |
|
williamr@4
|
106 |
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
williamr@4
|
107 |
template <class TagValueAList, class Tag>
|
williamr@4
|
108 |
struct extract_value {
|
williamr@4
|
109 |
typedef error_property_not_found type;
|
williamr@4
|
110 |
};
|
williamr@4
|
111 |
template <class Value, class Tag1, class Tag2, class Rest>
|
williamr@4
|
112 |
struct extract_value< std::pair<std::pair<Tag1,Value>,Rest>, Tag2> {
|
williamr@4
|
113 |
typedef typename extract_value<Rest,Tag2>::type type;
|
williamr@4
|
114 |
};
|
williamr@4
|
115 |
template <class Value, class Tag, class Rest>
|
williamr@4
|
116 |
struct extract_value< std::pair<std::pair<Tag,Value>,Rest>, Tag> {
|
williamr@4
|
117 |
typedef Value type;
|
williamr@4
|
118 |
};
|
williamr@2
|
119 |
#else
|
williamr@4
|
120 |
// VC++ workaround:
|
williamr@4
|
121 |
// The main idea here is to replace partial specialization with
|
williamr@4
|
122 |
// nested template member classes. Of course there is the
|
williamr@4
|
123 |
// further complication that the outer class of the nested
|
williamr@4
|
124 |
// template class cannot itself be a template class.
|
williamr@4
|
125 |
// Hence the need for the ev_selector. -JGS
|
williamr@2
|
126 |
|
williamr@4
|
127 |
struct recursive_extract;
|
williamr@4
|
128 |
struct end_extract;
|
williamr@2
|
129 |
|
williamr@4
|
130 |
template <class TagValueAList>
|
williamr@4
|
131 |
struct ev_selector { typedef recursive_extract type; };
|
williamr@4
|
132 |
template <>
|
williamr@4
|
133 |
struct ev_selector<no_property> { typedef end_extract type; };
|
williamr@2
|
134 |
|
williamr@4
|
135 |
struct recursive_extract {
|
williamr@4
|
136 |
template <class TagValueAList, class Tag1>
|
williamr@4
|
137 |
struct bind_ {
|
williamr@4
|
138 |
typedef typename TagValueAList::first_type AListFirst;
|
williamr@4
|
139 |
typedef typename AListFirst::first_type Tag2;
|
williamr@4
|
140 |
typedef typename AListFirst::second_type Value;
|
williamr@4
|
141 |
enum { match = same_property<Tag1,Tag2>::value };
|
williamr@4
|
142 |
typedef typename TagValueAList::second_type Next;
|
williamr@4
|
143 |
typedef typename ev_selector<Next>::type Extractor;
|
williamr@4
|
144 |
typedef typename boost::ct_if< match, Value,
|
williamr@4
|
145 |
typename Extractor::template bind_<Next,Tag1>::type
|
williamr@4
|
146 |
>::type type;
|
williamr@4
|
147 |
};
|
williamr@4
|
148 |
};
|
williamr@4
|
149 |
struct end_extract {
|
williamr@4
|
150 |
template <class AList, class Tag1>
|
williamr@4
|
151 |
struct bind_ {
|
williamr@4
|
152 |
typedef error_property_not_found type;
|
williamr@4
|
153 |
};
|
williamr@4
|
154 |
};
|
williamr@4
|
155 |
#endif //!defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
williamr@2
|
156 |
|
williamr@4
|
157 |
} // namespace detail
|
williamr@2
|
158 |
} // namespace boost
|
williamr@2
|
159 |
|
williamr@4
|
160 |
#endif // BOOST_DETAIL_PROPERTY_HPP
|