property.hpp 11 KB

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