property.hpp 14 KB

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