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