forward.hpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. // Copyright David Abrahams 2001.
  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 FORWARD_DWA20011215_HPP
  6. # define FORWARD_DWA20011215_HPP
  7. # include <boost/mpl/if.hpp>
  8. # include <boost/type_traits/is_scalar.hpp>
  9. # include <boost/type_traits/add_const.hpp>
  10. # include <boost/type_traits/add_reference.hpp>
  11. # include <boost/ref.hpp>
  12. # include <boost/python/detail/value_arg.hpp>
  13. # include <boost/python/detail/copy_ctor_mutates_rhs.hpp>
  14. # if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
  15. # include <boost/type_traits/is_enum.hpp>
  16. # include <boost/mpl/and.hpp>
  17. # include <boost/mpl/not.hpp>
  18. # else
  19. # include <boost/mpl/or.hpp>
  20. # endif
  21. namespace boost { namespace python { namespace objects {
  22. // Very much like boost::reference_wrapper<T>, except that in this
  23. // case T can be a reference already without causing a
  24. // reference-to-reference error.
  25. template <class T>
  26. struct reference_to_value
  27. {
  28. typedef typename add_reference<typename add_const<T>::type>::type reference;
  29. reference_to_value(reference x) : m_value(x) {}
  30. reference get() const { return m_value; }
  31. private:
  32. reference m_value;
  33. };
  34. // A little metaprogram which selects the type to pass through an
  35. // intermediate forwarding function when the destination argument type
  36. // is T.
  37. template <class T>
  38. struct forward
  39. : mpl::if_<
  40. # if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
  41. // vc6 chokes on unforwarding enums nested in classes
  42. mpl::and_<
  43. is_scalar<T>
  44. , mpl::not_<
  45. is_enum<T>
  46. >
  47. >
  48. # else
  49. mpl::or_<python::detail::copy_ctor_mutates_rhs<T>, is_scalar<T> >
  50. # endif
  51. , T
  52. , reference_to_value<T>
  53. >
  54. {
  55. };
  56. # ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
  57. template<typename T>
  58. struct unforward
  59. {
  60. typedef typename unwrap_reference<T>::type& type;
  61. };
  62. template<typename T>
  63. struct unforward<reference_to_value<T> >
  64. {
  65. typedef T type;
  66. };
  67. template <typename T>
  68. struct unforward_cref
  69. : python::detail::value_arg<
  70. typename unwrap_reference<T>::type
  71. >
  72. {
  73. };
  74. template<typename T>
  75. struct unforward_cref<reference_to_value<T> >
  76. : add_reference<typename add_const<T>::type>
  77. {
  78. };
  79. # else // no partial specialization
  80. namespace detail
  81. {
  82. typedef char (&yes_reference_to_value_t)[1];
  83. typedef char (&no_reference_to_value_t)[2];
  84. no_reference_to_value_t is_reference_to_value_test(...);
  85. template<typename T>
  86. yes_reference_to_value_t is_reference_to_value_test(boost::type< reference_to_value<T> >);
  87. template<bool wrapped>
  88. struct unforwarder
  89. {
  90. template <class T>
  91. struct apply
  92. {
  93. typedef typename unwrap_reference<T>::type& type;
  94. };
  95. };
  96. template<>
  97. struct unforwarder<true>
  98. {
  99. template <class T>
  100. struct apply
  101. {
  102. typedef typename T::reference type;
  103. };
  104. };
  105. template<bool wrapped = false>
  106. struct cref_unforwarder
  107. {
  108. template <class T>
  109. struct apply
  110. : python::detail::value_arg<
  111. typename unwrap_reference<T>::type
  112. >
  113. {
  114. };
  115. };
  116. template<>
  117. struct cref_unforwarder<true>
  118. {
  119. template <class T>
  120. struct apply
  121. : python::detail::value_arg<
  122. typename T::reference
  123. >
  124. {
  125. };
  126. };
  127. template<typename T>
  128. struct is_reference_to_value
  129. {
  130. BOOST_STATIC_CONSTANT(
  131. bool, value = (
  132. sizeof(is_reference_to_value_test(boost::type<T>()))
  133. == sizeof(yes_reference_to_value_t)));
  134. typedef mpl::bool_<value> type;
  135. };
  136. }
  137. template <typename T>
  138. struct unforward
  139. : public detail::unforwarder<
  140. detail::is_reference_to_value<T>::value
  141. >::template apply<T>
  142. {};
  143. template <typename T>
  144. struct unforward_cref
  145. : public detail::cref_unforwarder<
  146. detail::is_reference_to_value<T>::value
  147. >::template apply<T>
  148. {};
  149. # endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
  150. template <class T>
  151. typename reference_to_value<T>::reference
  152. do_unforward(reference_to_value<T> const& x, int)
  153. {
  154. return x.get();
  155. }
  156. template <class T>
  157. typename reference_wrapper<T>::type&
  158. do_unforward(reference_wrapper<T> const& x, int)
  159. {
  160. return x.get();
  161. }
  162. template <class T>
  163. T const& do_unforward(T const& x, ...)
  164. {
  165. return x;
  166. }
  167. }}} // namespace boost::python::objects
  168. #endif // FORWARD_DWA20011215_HPP