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_PROPERTY_HPP
7#define BOOST_PROPERTY_HPP
8
9#include <boost/mpl/bool.hpp>
10#include <boost/mpl/if.hpp>
11#include <boost/mpl/has_xxx.hpp>
12#include <boost/utility/enable_if.hpp>
13#include <boost/type_traits.hpp>
14#include <boost/static_assert.hpp>
15
16namespace boost
17{
18
19struct no_property
20{
21};
22
23template < class Tag, class T, class Base = no_property > struct property
24{
25 typedef Base next_type;
26 typedef Tag tag_type;
27 typedef T value_type;
28 property(const T& v = T()) : m_value(v) {}
29 property(const T& v, const Base& b) : m_value(v), m_base(b) {}
30 // copy constructor and assignment operator will be generated by compiler
31
32 T m_value;
33 Base m_base;
34};
35
36// Kinds of properties
37namespace graph_introspect_detail
38{
39 BOOST_MPL_HAS_XXX_TRAIT_DEF(kind)
40 template < typename T, bool Cond > struct get_kind
41 {
42 typedef void type;
43 };
44 template < typename T > struct get_kind< T, true >
45 {
46 typedef typename T::kind type;
47 };
48}
49
50// Having a default is to make this trait work for any type, not just valid
51// properties, to work around VC++ <= 10 bugs related to SFINAE in
52// compressed_sparse_row_graph's get functions and similar
53template < class PropertyTag >
54struct property_kind
55: graph_introspect_detail::get_kind< PropertyTag,
56 graph_introspect_detail::has_kind< PropertyTag >::value >
57{
58};
59
60// Some standard properties defined independently of Boost.Graph:
61enum vertex_all_t
62{
63 vertex_all
64};
65enum edge_all_t
66{
67 edge_all
68};
69enum graph_all_t
70{
71 graph_all
72};
73enum vertex_bundle_t
74{
75 vertex_bundle
76};
77enum edge_bundle_t
78{
79 edge_bundle
80};
81enum graph_bundle_t
82{
83 graph_bundle
84};
85
86// Code to look up one property in a property list:
87template < typename PList, typename PropName, typename Enable = void >
88struct lookup_one_property_internal
89{
90 BOOST_STATIC_CONSTANT(bool, found = false);
91 typedef void type;
92};
93
94// Special-case properties (vertex_all, edge_all, graph_all)
95#define BGL_ALL_PROP(tag) \
96 template < typename T > struct lookup_one_property_internal< T, tag > \
97 { \
98 BOOST_STATIC_CONSTANT(bool, found = true); \
99 typedef T type; \
100 static T& lookup(T& x, tag) { return x; } \
101 static const T& lookup(const T& x, tag) { return x; } \
102 }; \
103 template < typename Tag, typename T, typename Base > \
104 struct lookup_one_property_internal< property< Tag, T, Base >, tag > \
105 { /* Avoid ambiguity */ \
106 BOOST_STATIC_CONSTANT(bool, found = true); \
107 typedef property< Tag, T, Base > type; \
108 static type& lookup(type& x, tag) { return x; } \
109 static const type& lookup(const type& x, tag) { return x; } \
110 };
111
112BGL_ALL_PROP(vertex_all_t)
113BGL_ALL_PROP(edge_all_t)
114BGL_ALL_PROP(graph_all_t)
115#undef BGL_ALL_PROP
116
117// *_bundled; these need to be macros rather than inheritance to resolve
118// ambiguities
119#define BGL_DO_ONE_BUNDLE_TYPE(kind) \
120 template < typename T > \
121 struct lookup_one_property_internal< T, BOOST_JOIN(kind, _bundle_t) > \
122 { \
123 BOOST_STATIC_CONSTANT(bool, found = true); \
124 typedef T type; \
125 static T& lookup(T& x, BOOST_JOIN(kind, _bundle_t)) { return x; } \
126 static const T& lookup(const T& x, BOOST_JOIN(kind, _bundle_t)) \
127 { \
128 return x; \
129 } \
130 }; \
131 \
132 template < typename Tag, typename T, typename Base > \
133 struct lookup_one_property_internal< property< Tag, T, Base >, \
134 BOOST_JOIN(kind, _bundle_t) > \
135 : lookup_one_property_internal< Base, BOOST_JOIN(kind, _bundle_t) > \
136 { \
137 private: \
138 typedef lookup_one_property_internal< Base, \
139 BOOST_JOIN(kind, _bundle_t) > \
140 base_type; \
141 \
142 public: \
143 template < typename BundleTag > \
144 static typename lazy_enable_if_c< \
145 (base_type::found \
146 && (is_same< BundleTag, \
147 BOOST_JOIN(kind, _bundle_t) >::value)), \
148 add_reference< typename base_type::type > >::type \
149 lookup(property< Tag, T, Base >& p, BundleTag) \
150 { \
151 return base_type::lookup(p.m_base, BOOST_JOIN(kind, _bundle_t)()); \
152 } \
153 template < typename BundleTag > \
154 static typename lazy_enable_if_c< \
155 (base_type::found \
156 && (is_same< BundleTag, \
157 BOOST_JOIN(kind, _bundle_t) >::value)), \
158 add_reference< const typename base_type::type > >::type \
159 lookup(const property< Tag, T, Base >& p, BundleTag) \
160 { \
161 return base_type::lookup(p.m_base, BOOST_JOIN(kind, _bundle_t)()); \
162 } \
163 };
164
165BGL_DO_ONE_BUNDLE_TYPE(vertex)
166BGL_DO_ONE_BUNDLE_TYPE(edge)
167BGL_DO_ONE_BUNDLE_TYPE(graph)
168#undef BGL_DO_ONE_BUNDLE_TYPE
169
170// Normal old-style properties; second case also handles chaining of bundled
171// property accesses
172template < typename Tag, typename T, typename Base >
173struct lookup_one_property_internal< boost::property< Tag, T, Base >, Tag >
174{
175 BOOST_STATIC_CONSTANT(bool, found = true);
176 typedef property< Tag, T, Base > prop;
177 typedef T type;
178 template < typename U >
179 static typename enable_if< is_same< prop, U >, T& >::type lookup(
180 U& prop, const Tag&)
181 {
182 return prop.m_value;
183 }
184 template < typename U >
185 static typename enable_if< is_same< prop, U >, const T& >::type lookup(
186 const U& prop, const Tag&)
187 {
188 return prop.m_value;
189 }
190};
191
192template < typename Tag, typename T, typename Base, typename PropName >
193struct lookup_one_property_internal< boost::property< Tag, T, Base >, PropName >
194: lookup_one_property_internal< Base, PropName >
195{
196private:
197 typedef lookup_one_property_internal< Base, PropName > base_type;
198
199public:
200 template < typename PL >
201 static
202 typename lazy_enable_if< is_same< PL, boost::property< Tag, T, Base > >,
203 add_reference< typename base_type::type > >::type
204 lookup(PL& prop, const PropName& tag)
205 {
206 return base_type::lookup(prop.m_base, tag);
207 }
208 template < typename PL >
209 static
210 typename lazy_enable_if< is_same< PL, boost::property< Tag, T, Base > >,
211 add_reference< const typename base_type::type > >::type
212 lookup(const PL& prop, const PropName& tag)
213 {
214 return base_type::lookup(prop.m_base, tag);
215 }
216};
217
218// Pointer-to-member access to bundled properties
219#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
220template < typename T, typename TMaybeBase, typename R >
221struct lookup_one_property_internal< T, R TMaybeBase::*,
222 typename enable_if< is_base_of< TMaybeBase, T > >::type >
223{
224 BOOST_STATIC_CONSTANT(bool, found = true);
225 typedef R type;
226 static R& lookup(T& x, R TMaybeBase::*ptr) { return x.*ptr; }
227 static const R& lookup(const T& x, R TMaybeBase::*ptr) { return x.*ptr; }
228};
229#endif
230
231// Version of above handling const property lists properly
232template < typename T, typename Tag >
233struct lookup_one_property : lookup_one_property_internal< T, Tag >
234{
235};
236
237template < typename T, typename Tag > struct lookup_one_property< const T, Tag >
238{
239 BOOST_STATIC_CONSTANT(
240 bool, found = (lookup_one_property_internal< T, Tag >::found));
241 typedef const typename lookup_one_property_internal< T, Tag >::type type;
242 template < typename U >
243 static typename lazy_enable_if< is_same< T, U >,
244 add_reference< const typename lookup_one_property_internal< T,
245 Tag >::type > >::type
246 lookup(const U& p, Tag tag)
247 {
248 return lookup_one_property_internal< T, Tag >::lookup(p, tag);
249 }
250};
251
252// The BGL properties specialize property_kind and
253// property_num, and use enum's for the Property type (see
254// graph/properties.hpp), but the user may want to use a class
255// instead with a nested kind type and num. Also, we may want to
256// switch BGL back to using class types for properties at some point.
257
258template < class P > struct has_property : boost::mpl::true_
259{
260};
261template <> struct has_property< no_property > : boost::mpl::false_
262{
263};
264
265} // namespace boost
266
267#include <boost/pending/detail/property.hpp>
268
269namespace boost
270{
271
272template < class PropertyList, class Tag >
273struct property_value : lookup_one_property< PropertyList, Tag >
274{
275};
276
277template < class PropertyList, class Tag >
278inline typename lookup_one_property< PropertyList, Tag >::type&
279get_property_value(PropertyList& p, Tag tag)
280{
281 return lookup_one_property< PropertyList, Tag >::lookup(p, tag);
282}
283
284template < class PropertyList, class Tag >
285inline const typename lookup_one_property< PropertyList, Tag >::type&
286get_property_value(const PropertyList& p, Tag tag)
287{
288 return lookup_one_property< PropertyList, Tag >::lookup(p, tag);
289}
290
291namespace detail
292{
293
294 /** This trait returns true if T is no_property. */
295 template < typename T >
296 struct is_no_property : mpl::bool_< is_same< T, no_property >::value >
297 {
298 };
299
300 template < typename PList, typename Tag > class lookup_one_property_f;
301
302 template < typename PList, typename Tag, typename F >
303 struct lookup_one_property_f_result;
304
305 template < typename PList, typename Tag >
306 struct lookup_one_property_f_result< PList, Tag,
307 const lookup_one_property_f< PList, Tag >(PList) >
308 {
309 typedef typename lookup_one_property< PList, Tag >::type type;
310 };
311
312 template < typename PList, typename Tag >
313 struct lookup_one_property_f_result< PList, Tag,
314 const lookup_one_property_f< PList, Tag >(PList&) >
315 {
316 typedef typename lookup_one_property< PList, Tag >::type& type;
317 };
318
319 template < typename PList, typename Tag >
320 struct lookup_one_property_f_result< PList, Tag,
321 const lookup_one_property_f< PList, Tag >(const PList&) >
322 {
323 typedef const typename lookup_one_property< PList, Tag >::type& type;
324 };
325
326 template < typename PList, typename Tag > class lookup_one_property_f
327 {
328 Tag tag;
329
330 public:
331 lookup_one_property_f(Tag tag) : tag(tag) {}
332 template < typename F >
333 struct result : lookup_one_property_f_result< PList, Tag, F >
334 {
335 };
336
337 typename lookup_one_property_f_result< PList, Tag,
338 const lookup_one_property_f(PList&) >::type
339 operator()(PList& pl) const
340 {
341 return lookup_one_property< PList, Tag >::lookup(pl, tag);
342 }
343 };
344
345} // namespace detail
346
347namespace detail
348{
349 // Stuff for directed_graph and undirected_graph to skip over their first
350 // vertex_index and edge_index properties when providing vertex_all and
351 // edge_all; make sure you know the exact structure of your properties if
352 // you use there.
353 struct remove_first_property
354 {
355 template < typename F > struct result
356 {
357 typedef typename boost::function_traits< F >::arg1_type a1;
358 typedef typename boost::remove_reference< a1 >::type non_ref;
359 typedef typename non_ref::next_type nx;
360 typedef typename boost::mpl::if_< boost::is_const< non_ref >,
361 boost::add_const< nx >, nx >::type with_const;
362 typedef typename boost::add_reference< with_const >::type type;
363 };
364 template < typename Prop >
365 typename Prop::next_type& operator()(Prop& p) const
366 {
367 return p.m_base;
368 }
369 template < typename Prop >
370 const typename Prop::next_type& operator()(const Prop& p) const
371 {
372 return p.m_base;
373 }
374 };
375}
376
377} // namesapce boost
378
379#endif /* BOOST_PROPERTY_HPP */
380

source code of boost/libs/graph/include/boost/pending/property.hpp