property.hpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  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. namespace boost {
  9. struct no_property {
  10. typedef no_property tag_type;
  11. typedef no_property next_type;
  12. typedef no_property value_type;
  13. enum { num = 0 };
  14. typedef void kind;
  15. };
  16. template <class Tag, class T, class Base = no_property>
  17. struct property : public Base {
  18. typedef Base next_type;
  19. typedef Tag tag_type;
  20. typedef T value_type;
  21. #if BOOST_WORKAROUND (__GNUC__, < 3)
  22. property() { }
  23. #else
  24. property() : m_value() { }
  25. #endif
  26. property(const T& v) : m_value(v) { }
  27. property(const T& v, const Base& b) : Base(b), m_value(v) { }
  28. // copy constructor and assignment operator will be generated by compiler
  29. T m_value;
  30. };
  31. // The BGL properties specialize property_kind and
  32. // property_num, and use enum's for the Property type (see
  33. // graph/properties.hpp), but the user may want to use a class
  34. // instead with a nested kind type and num. Also, we may want to
  35. // switch BGL back to using class types for properties at some point.
  36. template <class PropertyTag>
  37. struct property_kind {
  38. typedef typename PropertyTag::kind type;
  39. };
  40. template <class P>
  41. struct has_property : boost::mpl::true_ {};
  42. template <>
  43. struct has_property<no_property> : boost::mpl::false_ {};
  44. } // namespace boost
  45. #include <boost/pending/detail/property.hpp>
  46. namespace boost {
  47. template <class PropertyList, class Tag>
  48. struct property_value {
  49. #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
  50. typedef typename detail::build_property_tag_value_alist<PropertyList>::type AList;
  51. typedef typename detail::extract_value<AList,Tag>::type type;
  52. #else
  53. typedef typename detail::build_property_tag_value_alist<PropertyList>::type AList;
  54. typedef typename detail::ev_selector<AList>::type Extractor;
  55. typedef typename Extractor::template bind_<AList,Tag>::type type;
  56. #endif
  57. };
  58. template <class Tag2>
  59. inline detail::error_property_not_found
  60. get_property_value(const no_property& p, Tag2) {
  61. return detail::error_property_not_found();
  62. }
  63. template <class Tag1, class Tag2, class T1, class Base>
  64. inline typename property_value<property<Tag1,T1,Base>, Tag2>::type&
  65. get_property_value(property<Tag1,T1,Base>& p, Tag2 tag2) {
  66. BOOST_STATIC_CONSTANT(bool,
  67. match = (detail::same_property<Tag1,Tag2>::value));
  68. typedef property<Tag1,T1,Base> Prop;
  69. typedef typename property_value<Prop, Tag2>::type T2;
  70. T2* t2 = 0;
  71. typedef detail::property_value_dispatch<match> Dispatcher;
  72. return Dispatcher::get_value(p, t2, tag2);
  73. }
  74. template <class Tag1, class Tag2, class T1, class Base>
  75. inline
  76. const typename property_value<property<Tag1,T1,Base>, Tag2>::type&
  77. get_property_value(const property<Tag1,T1,Base>& p, Tag2 tag2) {
  78. BOOST_STATIC_CONSTANT(bool,
  79. match = (detail::same_property<Tag1,Tag2>::value));
  80. typedef property<Tag1,T1,Base> Prop;
  81. typedef typename property_value<Prop, Tag2>::type T2;
  82. T2* t2 = 0;
  83. typedef detail::property_value_dispatch<match> Dispatcher;
  84. return Dispatcher::const_get_value(p, t2, tag2);
  85. }
  86. namespace detail {
  87. /** This trait returns true if T is no_property. */
  88. template <typename T>
  89. struct is_no_property
  90. : mpl::bool_<is_same<T, no_property>::value>
  91. { };
  92. #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
  93. /** @internal @name Retag Property List
  94. * This metafunction is used internally to normalize a property if it is
  95. * actually modeling a property. Specifically this is used in Boost.Graph
  96. * to map user-provided classes into bundled properties.
  97. */
  98. //@{
  99. // One base case of the recursive form (see below). This matches any
  100. // retag request that does not include a property<...> or no_property as
  101. // the FinalType. This is used for generating bundles in Boost.Graph.
  102. template<typename FinalTag, typename FinalType>
  103. struct retag_property_list
  104. {
  105. typedef property<FinalTag, FinalType> type;
  106. typedef FinalType retagged;
  107. };
  108. // Recursively retag the nested property list.
  109. template<typename FinalTag, typename Tag, typename T, typename Base>
  110. struct retag_property_list<FinalTag, property<Tag, T, Base> >
  111. {
  112. private:
  113. typedef retag_property_list<FinalTag, Base> next;
  114. public:
  115. typedef property<Tag, T, typename next::type> type;
  116. typedef typename next::retagged retagged;
  117. };
  118. // This base case will correctly deduce the final property type if the
  119. // retagged property is given in property form. This should not hide
  120. // the base case below.
  121. // NOTE: This addresses a problem of layering bundled properties in the BGL
  122. // where multiple retaggings will fail to deduce the correct retagged
  123. // type.
  124. template<typename FinalTag, typename FinalType>
  125. struct retag_property_list<FinalTag, property<FinalTag, FinalType> >
  126. {
  127. public:
  128. typedef property<FinalTag, FinalType> type;
  129. typedef FinalType retagged;
  130. };
  131. // A final base case of the retag_propert_list, this will terminate a
  132. // properly structured list.
  133. template<typename FinalTag>
  134. struct retag_property_list<FinalTag, no_property>
  135. {
  136. typedef no_property type;
  137. typedef no_property retagged;
  138. };
  139. //@}
  140. #endif
  141. } // namespace detail
  142. } // namesapce boost
  143. #endif /* BOOST_PROPERTY_HPP */