unwind_type.hpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. // Copyright David Abrahams 2002.
  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 UNWIND_TYPE_DWA200222_HPP
  6. # define UNWIND_TYPE_DWA200222_HPP
  7. # include <boost/python/detail/cv_category.hpp>
  8. # include <boost/python/detail/indirect_traits.hpp>
  9. # include <boost/python/detail/type_traits.hpp>
  10. namespace boost { namespace python { namespace detail {
  11. #if (!defined(_MSC_VER) || _MSC_VER >= 1915)
  12. // If forward declared, msvc6.5 does not recognize them as inline.
  13. // However, as of msvc14.15 (_MSC_VER 1915/Visual Studio 15.8.0) name lookup is now consistent with other compilers.
  14. // forward declaration, required (at least) by Tru64 cxx V6.5-042 and msvc14.15
  15. template <class Generator, class U>
  16. inline typename Generator::result_type
  17. unwind_type(U const& p, Generator* = 0);
  18. // forward declaration, required (at least) by Tru64 cxx V6.5-042 and msvc14.15
  19. template <class Generator, class U>
  20. inline typename Generator::result_type
  21. unwind_type(boost::type<U>*p = 0, Generator* = 0);
  22. #endif
  23. template <class Generator, class U>
  24. inline typename Generator::result_type
  25. unwind_type_cv(U* p, cv_unqualified, Generator* = 0)
  26. {
  27. return Generator::execute(p);
  28. }
  29. template <class Generator, class U>
  30. inline typename Generator::result_type
  31. unwind_type_cv(U const* p, const_, Generator* = 0)
  32. {
  33. return unwind_type(const_cast<U*>(p), (Generator*)0);
  34. }
  35. template <class Generator, class U>
  36. inline typename Generator::result_type
  37. unwind_type_cv(U volatile* p, volatile_, Generator* = 0)
  38. {
  39. return unwind_type(const_cast<U*>(p), (Generator*)0);
  40. }
  41. template <class Generator, class U>
  42. inline typename Generator::result_type
  43. unwind_type_cv(U const volatile* p, const_volatile_, Generator* = 0)
  44. {
  45. return unwind_type(const_cast<U*>(p), (Generator*)0);
  46. }
  47. template <class Generator, class U>
  48. inline typename Generator::result_type
  49. unwind_ptr_type(U* p, Generator* = 0)
  50. {
  51. typedef typename cv_category<U>::type tag;
  52. return unwind_type_cv<Generator>(p, tag());
  53. }
  54. template <bool is_ptr>
  55. struct unwind_helper
  56. {
  57. template <class Generator, class U>
  58. static typename Generator::result_type
  59. execute(U p, Generator* = 0)
  60. {
  61. return unwind_ptr_type(p, (Generator*)0);
  62. }
  63. };
  64. template <>
  65. struct unwind_helper<false>
  66. {
  67. template <class Generator, class U>
  68. static typename Generator::result_type
  69. execute(U& p, Generator* = 0)
  70. {
  71. return unwind_ptr_type(&p, (Generator*)0);
  72. }
  73. };
  74. template <class Generator, class U>
  75. inline typename Generator::result_type
  76. #if (!defined(_MSC_VER) || _MSC_VER >= 1915)
  77. unwind_type(U const& p, Generator*)
  78. #else
  79. unwind_type(U const& p, Generator* = 0)
  80. #endif
  81. {
  82. return unwind_helper<is_pointer<U>::value>::execute(p, (Generator*)0);
  83. }
  84. enum { direct_ = 0, pointer_ = 1, reference_ = 2, reference_to_pointer_ = 3 };
  85. template <int indirection> struct unwind_helper2;
  86. template <>
  87. struct unwind_helper2<direct_>
  88. {
  89. template <class Generator, class U>
  90. static typename Generator::result_type
  91. execute(U(*)(), Generator* = 0)
  92. {
  93. return unwind_ptr_type((U*)0, (Generator*)0);
  94. }
  95. };
  96. template <>
  97. struct unwind_helper2<pointer_>
  98. {
  99. template <class Generator, class U>
  100. static typename Generator::result_type
  101. execute(U*(*)(), Generator* = 0)
  102. {
  103. return unwind_ptr_type((U*)0, (Generator*)0);
  104. }
  105. };
  106. template <>
  107. struct unwind_helper2<reference_>
  108. {
  109. template <class Generator, class U>
  110. static typename Generator::result_type
  111. execute(U&(*)(), Generator* = 0)
  112. {
  113. return unwind_ptr_type((U*)0, (Generator*)0);
  114. }
  115. };
  116. template <>
  117. struct unwind_helper2<reference_to_pointer_>
  118. {
  119. template <class Generator, class U>
  120. static typename Generator::result_type
  121. execute(U&(*)(), Generator* = 0)
  122. {
  123. return unwind_ptr_type(U(0), (Generator*)0);
  124. }
  125. };
  126. // Call this one with both template parameters explicitly specified
  127. // and no function arguments:
  128. //
  129. // return unwind_type<my_generator,T>();
  130. //
  131. // Doesn't work if T is an array type; we could handle that case, but
  132. // why bother?
  133. template <class Generator, class U>
  134. inline typename Generator::result_type
  135. #if (!defined(_MSC_VER) || _MSC_VER >= 1915)
  136. unwind_type(boost::type<U>*, Generator*)
  137. #else
  138. unwind_type(boost::type<U>*p =0, Generator* =0)
  139. #endif
  140. {
  141. BOOST_STATIC_CONSTANT(int, indirection
  142. = (is_pointer<U>::value ? pointer_ : 0)
  143. + (indirect_traits::is_reference_to_pointer<U>::value
  144. ? reference_to_pointer_
  145. : is_lvalue_reference<U>::value
  146. ? reference_
  147. : 0));
  148. return unwind_helper2<indirection>::execute((U(*)())0,(Generator*)0);
  149. }
  150. }}} // namespace boost::python::detail
  151. #endif // UNWIND_TYPE_DWA200222_HPP