property.hpp 14 KB

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