summaryrefslogtreecommitdiff
path: root/boost/python/detail/unwind_type.hpp
blob: 9a997c9dbd3015e038b02c413aab869d8c7fefee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
// Copyright David Abrahams 2002.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef UNWIND_TYPE_DWA200222_HPP
# define UNWIND_TYPE_DWA200222_HPP

# include <boost/python/detail/cv_category.hpp>
# include <boost/python/detail/indirect_traits.hpp>
# include <boost/type_traits/object_traits.hpp>

namespace boost { namespace python { namespace detail {

#ifndef _MSC_VER //if forward declared, msvc6.5 does not recognize them as inline
// forward declaration, required (at least) by Tru64 cxx V6.5-042
template <class Generator, class U>
inline typename Generator::result_type
unwind_type(U const& p, Generator* = 0);

// forward declaration, required (at least) by Tru64 cxx V6.5-042
template <class Generator, class U>
inline typename Generator::result_type
unwind_type(boost::type<U>*p = 0, Generator* = 0);
#endif

template <class Generator, class U>
inline typename Generator::result_type
unwind_type_cv(U* p, cv_unqualified, Generator* = 0)
{
    return Generator::execute(p);
}

template <class Generator, class U>
inline typename Generator::result_type
unwind_type_cv(U const* p, const_, Generator* = 0)
{
    return unwind_type(const_cast<U*>(p), (Generator*)0);
}

template <class Generator, class U>
inline typename Generator::result_type
unwind_type_cv(U volatile* p, volatile_, Generator* = 0)
{
    return unwind_type(const_cast<U*>(p), (Generator*)0);
}

template <class Generator, class U>
inline typename Generator::result_type
unwind_type_cv(U const volatile* p, const_volatile_, Generator* = 0)
{
    return unwind_type(const_cast<U*>(p), (Generator*)0);
}

template <class Generator, class U>
inline typename Generator::result_type
unwind_ptr_type(U* p, Generator* = 0)
{
    typedef typename cv_category<U>::type tag;
    return unwind_type_cv<Generator>(p, tag());
}

template <bool is_ptr>
struct unwind_helper
{
    template <class Generator, class U>
    static typename Generator::result_type
    execute(U p, Generator* = 0)
    {
        return unwind_ptr_type(p, (Generator*)0);
    }
};

template <>
struct unwind_helper<false>
{
    template <class Generator, class U>
    static typename Generator::result_type
    execute(U& p, Generator* = 0)
    {
        return unwind_ptr_type(&p, (Generator*)0);
    }
};

template <class Generator, class U>
inline typename Generator::result_type
#ifndef _MSC_VER
unwind_type(U const& p, Generator*)
#else
unwind_type(U const& p, Generator* = 0)
#endif
{
    return unwind_helper<is_pointer<U>::value>::execute(p, (Generator*)0);
}

enum { direct_ = 0, pointer_ = 1, reference_ = 2, reference_to_pointer_ = 3 };
template <int indirection> struct unwind_helper2;

template <>
struct unwind_helper2<direct_>
{
    template <class Generator, class U>
    static typename Generator::result_type
    execute(U(*)(), Generator* = 0)
    {
        return unwind_ptr_type((U*)0, (Generator*)0);
    }
};

template <>
struct unwind_helper2<pointer_>
{
    template <class Generator, class U>
    static typename Generator::result_type
    execute(U*(*)(), Generator* = 0)
    {
        return unwind_ptr_type((U*)0, (Generator*)0);
    }
};

template <>
struct unwind_helper2<reference_>
{
    template <class Generator, class U>
    static typename Generator::result_type
    execute(U&(*)(), Generator* = 0)
    {
        return unwind_ptr_type((U*)0, (Generator*)0);
    }
};

template <>
struct unwind_helper2<reference_to_pointer_>
{
    template <class Generator, class U>
    static typename Generator::result_type
    execute(U&(*)(), Generator* = 0)
    {
        return unwind_ptr_type(U(0), (Generator*)0);
    }
};

// Call this one with both template parameters explicitly specified
// and no function arguments:
//
//      return unwind_type<my_generator,T>();
//
// Doesn't work if T is an array type; we could handle that case, but
// why bother?
template <class Generator, class U>
inline typename Generator::result_type
#ifndef _MSC_VER
unwind_type(boost::type<U>*, Generator*)
#else
unwind_type(boost::type<U>*p =0, Generator* =0)
#endif
{
    BOOST_STATIC_CONSTANT(int, indirection
        = (boost::is_pointer<U>::value ? pointer_ : 0)
                             + (indirect_traits::is_reference_to_pointer<U>::value
                             ? reference_to_pointer_
                             : boost::is_reference<U>::value
                             ? reference_
                             : 0));

    return unwind_helper2<indirection>::execute((U(*)())0,(Generator*)0);
}

}}} // namespace boost::python::detail

#endif // UNWIND_TYPE_DWA200222_HPP