Chris@16
|
1 // (C) Copyright Jeremy Siek 2004
|
Chris@16
|
2 // Distributed under the Boost Software License, Version 1.0. (See
|
Chris@16
|
3 // accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
4 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
5
|
Chris@16
|
6 #ifndef BOOST_PROPERTY_HPP
|
Chris@16
|
7 #define BOOST_PROPERTY_HPP
|
Chris@16
|
8
|
Chris@16
|
9 #include <boost/mpl/bool.hpp>
|
Chris@16
|
10 #include <boost/mpl/if.hpp>
|
Chris@16
|
11 #include <boost/mpl/has_xxx.hpp>
|
Chris@16
|
12 #include <boost/utility/enable_if.hpp>
|
Chris@16
|
13 #include <boost/type_traits.hpp>
|
Chris@16
|
14 #include <boost/static_assert.hpp>
|
Chris@16
|
15
|
Chris@16
|
16 namespace boost {
|
Chris@16
|
17
|
Chris@16
|
18 struct no_property {};
|
Chris@16
|
19
|
Chris@16
|
20 template <class Tag, class T, class Base = no_property>
|
Chris@16
|
21 struct property {
|
Chris@16
|
22 typedef Base next_type;
|
Chris@16
|
23 typedef Tag tag_type;
|
Chris@16
|
24 typedef T value_type;
|
Chris@16
|
25 property(const T& v = T()) : m_value(v) { }
|
Chris@16
|
26 property(const T& v, const Base& b) : m_value(v), m_base(b) { }
|
Chris@16
|
27 // copy constructor and assignment operator will be generated by compiler
|
Chris@16
|
28
|
Chris@16
|
29 T m_value;
|
Chris@16
|
30 Base m_base;
|
Chris@16
|
31 };
|
Chris@16
|
32
|
Chris@16
|
33 // Kinds of properties
|
Chris@16
|
34 namespace graph_introspect_detail {
|
Chris@16
|
35 BOOST_MPL_HAS_XXX_TRAIT_DEF(kind)
|
Chris@16
|
36 template <typename T, bool Cond> struct get_kind {typedef void type;};
|
Chris@16
|
37 template <typename T> struct get_kind<T, true> {typedef typename T::kind type;};
|
Chris@16
|
38 }
|
Chris@16
|
39
|
Chris@16
|
40 // Having a default is to make this trait work for any type, not just valid
|
Chris@16
|
41 // properties, to work around VC++ <= 10 bugs related to SFINAE in
|
Chris@16
|
42 // compressed_sparse_row_graph's get functions and similar
|
Chris@16
|
43 template <class PropertyTag>
|
Chris@16
|
44 struct property_kind:
|
Chris@16
|
45 graph_introspect_detail::get_kind<PropertyTag, graph_introspect_detail::has_kind<PropertyTag>::value>
|
Chris@16
|
46 {};
|
Chris@16
|
47
|
Chris@16
|
48 // Some standard properties defined independently of Boost.Graph:
|
Chris@16
|
49 enum vertex_all_t {vertex_all};
|
Chris@16
|
50 enum edge_all_t {edge_all};
|
Chris@16
|
51 enum graph_all_t {graph_all};
|
Chris@16
|
52 enum vertex_bundle_t {vertex_bundle};
|
Chris@16
|
53 enum edge_bundle_t {edge_bundle};
|
Chris@16
|
54 enum graph_bundle_t {graph_bundle};
|
Chris@16
|
55
|
Chris@16
|
56 // Code to look up one property in a property list:
|
Chris@16
|
57 template <typename PList, typename PropName, typename Enable = void>
|
Chris@16
|
58 struct lookup_one_property_internal {BOOST_STATIC_CONSTANT(bool, found = false); typedef void type;};
|
Chris@16
|
59
|
Chris@16
|
60 // Special-case properties (vertex_all, edge_all, graph_all)
|
Chris@16
|
61 #define BGL_ALL_PROP(tag) \
|
Chris@16
|
62 template <typename T> \
|
Chris@16
|
63 struct lookup_one_property_internal<T, tag> { \
|
Chris@16
|
64 BOOST_STATIC_CONSTANT(bool, found = true); \
|
Chris@16
|
65 typedef T type; \
|
Chris@16
|
66 static T& lookup(T& x, tag) {return x;} \
|
Chris@16
|
67 static const T& lookup(const T& x, tag) {return x;} \
|
Chris@16
|
68 }; \
|
Chris@16
|
69 template <typename Tag, typename T, typename Base> \
|
Chris@16
|
70 struct lookup_one_property_internal<property<Tag, T, Base>, tag> { /* Avoid ambiguity */ \
|
Chris@16
|
71 BOOST_STATIC_CONSTANT(bool, found = true); \
|
Chris@16
|
72 typedef property<Tag, T, Base> type; \
|
Chris@16
|
73 static type& lookup(type& x, tag) {return x;} \
|
Chris@16
|
74 static const type& lookup(const type& x, tag) {return x;} \
|
Chris@16
|
75 };
|
Chris@16
|
76
|
Chris@16
|
77 BGL_ALL_PROP(vertex_all_t)
|
Chris@16
|
78 BGL_ALL_PROP(edge_all_t)
|
Chris@16
|
79 BGL_ALL_PROP(graph_all_t)
|
Chris@16
|
80 #undef BGL_ALL_PROP
|
Chris@16
|
81
|
Chris@16
|
82 // *_bundled; these need to be macros rather than inheritance to resolve ambiguities
|
Chris@16
|
83 #define BGL_DO_ONE_BUNDLE_TYPE(kind) \
|
Chris@16
|
84 template <typename T> \
|
Chris@16
|
85 struct lookup_one_property_internal<T, BOOST_JOIN(kind, _bundle_t)> { \
|
Chris@16
|
86 BOOST_STATIC_CONSTANT(bool, found = true); \
|
Chris@16
|
87 typedef T type; \
|
Chris@16
|
88 static T& lookup(T& x, BOOST_JOIN(kind, _bundle_t)) {return x;} \
|
Chris@16
|
89 static const T& lookup(const T& x, BOOST_JOIN(kind, _bundle_t)) {return x;} \
|
Chris@16
|
90 }; \
|
Chris@16
|
91 \
|
Chris@16
|
92 template <typename Tag, typename T, typename Base> \
|
Chris@16
|
93 struct lookup_one_property_internal<property<Tag, T, Base>, BOOST_JOIN(kind, _bundle_t)>: lookup_one_property_internal<Base, BOOST_JOIN(kind, _bundle_t)> { \
|
Chris@16
|
94 private: \
|
Chris@16
|
95 typedef lookup_one_property_internal<Base, BOOST_JOIN(kind, _bundle_t)> base_type; \
|
Chris@16
|
96 public: \
|
Chris@16
|
97 template <typename BundleTag> \
|
Chris@16
|
98 static typename lazy_enable_if_c<(base_type::found && (is_same<BundleTag, BOOST_JOIN(kind, _bundle_t)>::value)), \
|
Chris@16
|
99 add_reference<typename base_type::type> >::type \
|
Chris@16
|
100 lookup(property<Tag, T, Base>& p, BundleTag) {return base_type::lookup(p.m_base, BOOST_JOIN(kind, _bundle_t)());} \
|
Chris@16
|
101 template <typename BundleTag> \
|
Chris@16
|
102 static typename lazy_enable_if_c<(base_type::found && (is_same<BundleTag, BOOST_JOIN(kind, _bundle_t)>::value)), \
|
Chris@16
|
103 add_reference<const typename base_type::type> >::type \
|
Chris@16
|
104 lookup(const property<Tag, T, Base>& p, BundleTag) {return base_type::lookup(p.m_base, BOOST_JOIN(kind, _bundle_t)());} \
|
Chris@16
|
105 }; \
|
Chris@16
|
106
|
Chris@16
|
107 BGL_DO_ONE_BUNDLE_TYPE(vertex)
|
Chris@16
|
108 BGL_DO_ONE_BUNDLE_TYPE(edge)
|
Chris@16
|
109 BGL_DO_ONE_BUNDLE_TYPE(graph)
|
Chris@16
|
110 #undef BGL_DO_ONE_BUNDLE_TYPE
|
Chris@16
|
111
|
Chris@16
|
112 // Normal old-style properties; second case also handles chaining of bundled property accesses
|
Chris@16
|
113 template <typename Tag, typename T, typename Base>
|
Chris@16
|
114 struct lookup_one_property_internal<boost::property<Tag, T, Base>, Tag> {
|
Chris@16
|
115 BOOST_STATIC_CONSTANT(bool, found = true);
|
Chris@16
|
116 typedef property<Tag, T, Base> prop;
|
Chris@16
|
117 typedef T type;
|
Chris@16
|
118 template <typename U>
|
Chris@16
|
119 static typename enable_if<is_same<prop, U>, T&>::type
|
Chris@16
|
120 lookup(U& prop, const Tag&) {return prop.m_value;}
|
Chris@16
|
121 template <typename U>
|
Chris@16
|
122 static typename enable_if<is_same<prop, U>, const T&>::type
|
Chris@16
|
123 lookup(const U& prop, const Tag&) {return prop.m_value;}
|
Chris@16
|
124 };
|
Chris@16
|
125
|
Chris@16
|
126 template <typename Tag, typename T, typename Base, typename PropName>
|
Chris@16
|
127 struct lookup_one_property_internal<boost::property<Tag, T, Base>, PropName>: lookup_one_property_internal<Base, PropName> {
|
Chris@16
|
128 private:
|
Chris@16
|
129 typedef lookup_one_property_internal<Base, PropName> base_type;
|
Chris@16
|
130 public:
|
Chris@16
|
131 template <typename PL>
|
Chris@16
|
132 static typename lazy_enable_if<is_same<PL, boost::property<Tag, T, Base> >,
|
Chris@16
|
133 add_reference<typename base_type::type> >::type
|
Chris@16
|
134 lookup(PL& prop, const PropName& tag) {
|
Chris@16
|
135 return base_type::lookup(prop.m_base, tag);
|
Chris@16
|
136 }
|
Chris@16
|
137 template <typename PL>
|
Chris@16
|
138 static typename lazy_enable_if<is_same<PL, boost::property<Tag, T, Base> >,
|
Chris@16
|
139 add_reference<const typename base_type::type> >::type
|
Chris@16
|
140 lookup(const PL& prop, const PropName& tag) {
|
Chris@16
|
141 return base_type::lookup(prop.m_base, tag);
|
Chris@16
|
142 }
|
Chris@16
|
143 };
|
Chris@16
|
144
|
Chris@16
|
145 // Pointer-to-member access to bundled properties
|
Chris@16
|
146 #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
|
Chris@16
|
147 template <typename T, typename TMaybeBase, typename R>
|
Chris@16
|
148 struct lookup_one_property_internal<T, R TMaybeBase::*, typename enable_if<is_base_of<TMaybeBase, T> >::type> {
|
Chris@16
|
149 BOOST_STATIC_CONSTANT(bool, found = true);
|
Chris@16
|
150 typedef R type;
|
Chris@16
|
151 static R& lookup(T& x, R TMaybeBase::*ptr) {return x.*ptr;}
|
Chris@16
|
152 static const R& lookup(const T& x, R TMaybeBase::*ptr) {return x.*ptr;}
|
Chris@16
|
153 };
|
Chris@16
|
154 #endif
|
Chris@16
|
155
|
Chris@16
|
156 // Version of above handling const property lists properly
|
Chris@16
|
157 template <typename T, typename Tag>
|
Chris@16
|
158 struct lookup_one_property: lookup_one_property_internal<T, Tag> {};
|
Chris@16
|
159
|
Chris@16
|
160 template <typename T, typename Tag>
|
Chris@16
|
161 struct lookup_one_property<const T, Tag> {
|
Chris@16
|
162 BOOST_STATIC_CONSTANT(bool, found = (lookup_one_property_internal<T, Tag>::found));
|
Chris@16
|
163 typedef const typename lookup_one_property_internal<T, Tag>::type type;
|
Chris@16
|
164 template <typename U>
|
Chris@16
|
165 static typename lazy_enable_if<is_same<T, U>,
|
Chris@16
|
166 add_reference<const typename lookup_one_property_internal<T, Tag>::type> >::type
|
Chris@16
|
167 lookup(const U& p, Tag tag) {
|
Chris@16
|
168 return lookup_one_property_internal<T, Tag>::lookup(p, tag);
|
Chris@16
|
169 }
|
Chris@16
|
170 };
|
Chris@16
|
171
|
Chris@16
|
172 // The BGL properties specialize property_kind and
|
Chris@16
|
173 // property_num, and use enum's for the Property type (see
|
Chris@16
|
174 // graph/properties.hpp), but the user may want to use a class
|
Chris@16
|
175 // instead with a nested kind type and num. Also, we may want to
|
Chris@16
|
176 // switch BGL back to using class types for properties at some point.
|
Chris@16
|
177
|
Chris@16
|
178 template <class P>
|
Chris@16
|
179 struct has_property : boost::mpl::true_ {};
|
Chris@16
|
180 template <>
|
Chris@16
|
181 struct has_property<no_property> : boost::mpl::false_ {};
|
Chris@16
|
182
|
Chris@16
|
183 } // namespace boost
|
Chris@16
|
184
|
Chris@16
|
185 #include <boost/pending/detail/property.hpp>
|
Chris@16
|
186
|
Chris@16
|
187 namespace boost {
|
Chris@16
|
188
|
Chris@16
|
189 template <class PropertyList, class Tag>
|
Chris@16
|
190 struct property_value: lookup_one_property<PropertyList, Tag> {};
|
Chris@16
|
191
|
Chris@16
|
192 template <class PropertyList, class Tag>
|
Chris@16
|
193 inline typename lookup_one_property<PropertyList, Tag>::type&
|
Chris@16
|
194 get_property_value(PropertyList& p, Tag tag) {
|
Chris@16
|
195 return lookup_one_property<PropertyList, Tag>::lookup(p, tag);
|
Chris@16
|
196 }
|
Chris@16
|
197
|
Chris@16
|
198 template <class PropertyList, class Tag>
|
Chris@16
|
199 inline const typename lookup_one_property<PropertyList, Tag>::type&
|
Chris@16
|
200 get_property_value(const PropertyList& p, Tag tag) {
|
Chris@16
|
201 return lookup_one_property<PropertyList, Tag>::lookup(p, tag);
|
Chris@16
|
202 }
|
Chris@16
|
203
|
Chris@16
|
204 namespace detail {
|
Chris@16
|
205
|
Chris@16
|
206 /** This trait returns true if T is no_property. */
|
Chris@16
|
207 template <typename T>
|
Chris@16
|
208 struct is_no_property
|
Chris@16
|
209 : mpl::bool_<is_same<T, no_property>::value>
|
Chris@16
|
210 { };
|
Chris@16
|
211
|
Chris@16
|
212 template <typename PList, typename Tag>
|
Chris@16
|
213 class lookup_one_property_f;
|
Chris@16
|
214
|
Chris@16
|
215 template <typename PList, typename Tag, typename F> struct lookup_one_property_f_result;
|
Chris@16
|
216
|
Chris@16
|
217 template <typename PList, typename Tag>
|
Chris@16
|
218 struct lookup_one_property_f_result<PList, Tag, const lookup_one_property_f<PList, Tag>(PList)> {
|
Chris@16
|
219 typedef typename lookup_one_property<PList, Tag>::type type;
|
Chris@16
|
220 };
|
Chris@16
|
221
|
Chris@16
|
222 template <typename PList, typename Tag>
|
Chris@16
|
223 struct lookup_one_property_f_result<PList, Tag, const lookup_one_property_f<PList, Tag>(PList&)> {
|
Chris@16
|
224 typedef typename lookup_one_property<PList, Tag>::type& type;
|
Chris@16
|
225 };
|
Chris@16
|
226
|
Chris@16
|
227 template <typename PList, typename Tag>
|
Chris@16
|
228 struct lookup_one_property_f_result<PList, Tag, const lookup_one_property_f<PList, Tag>(const PList&)> {
|
Chris@16
|
229 typedef const typename lookup_one_property<PList, Tag>::type& type;
|
Chris@16
|
230 };
|
Chris@16
|
231
|
Chris@16
|
232 template <typename PList, typename Tag>
|
Chris@16
|
233 class lookup_one_property_f {
|
Chris@16
|
234 Tag tag;
|
Chris@16
|
235 public:
|
Chris@16
|
236 lookup_one_property_f(Tag tag): tag(tag) {}
|
Chris@16
|
237 template <typename F> struct result: lookup_one_property_f_result<PList, Tag, F> {};
|
Chris@16
|
238
|
Chris@16
|
239 typename lookup_one_property_f_result<PList, Tag, const lookup_one_property_f(PList&)>::type
|
Chris@16
|
240 operator()(PList& pl) const {
|
Chris@16
|
241 return lookup_one_property<PList, Tag>::lookup(pl, tag);
|
Chris@16
|
242 }
|
Chris@16
|
243 };
|
Chris@16
|
244
|
Chris@16
|
245 } // namespace detail
|
Chris@16
|
246
|
Chris@16
|
247 namespace detail {
|
Chris@16
|
248 // Stuff for directed_graph and undirected_graph to skip over their first
|
Chris@16
|
249 // vertex_index and edge_index properties when providing vertex_all and
|
Chris@16
|
250 // edge_all; make sure you know the exact structure of your properties if you
|
Chris@16
|
251 // use there.
|
Chris@16
|
252 struct remove_first_property {
|
Chris@16
|
253 template <typename F>
|
Chris@16
|
254 struct result {
|
Chris@16
|
255 typedef typename boost::function_traits<F>::arg1_type a1;
|
Chris@16
|
256 typedef typename boost::remove_reference<a1>::type non_ref;
|
Chris@16
|
257 typedef typename non_ref::next_type nx;
|
Chris@16
|
258 typedef typename boost::mpl::if_<boost::is_const<non_ref>, boost::add_const<nx>, nx>::type with_const;
|
Chris@16
|
259 typedef typename boost::add_reference<with_const>::type type;
|
Chris@16
|
260 };
|
Chris@16
|
261 template <typename Prop>
|
Chris@16
|
262 typename Prop::next_type& operator()(Prop& p) const {return p.m_base;}
|
Chris@16
|
263 template <typename Prop>
|
Chris@16
|
264 const typename Prop::next_type& operator()(const Prop& p) const {return p.m_base;}
|
Chris@16
|
265 };
|
Chris@16
|
266 }
|
Chris@16
|
267
|
Chris@16
|
268 } // namesapce boost
|
Chris@16
|
269
|
Chris@16
|
270 #endif /* BOOST_PROPERTY_HPP */
|