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