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 DATA_MEMBERS_DWA2002328_HPP
6# define DATA_MEMBERS_DWA2002328_HPP
7
8# include <boost/python/detail/prefix.hpp>
9
10# include <boost/python/handle.hpp>
11
12# include <boost/python/return_value_policy.hpp>
13# include <boost/python/return_by_value.hpp>
14# include <boost/python/return_internal_reference.hpp>
15# include <boost/python/make_function.hpp>
16
17# include <boost/python/converter/builtin_converters.hpp>
18
19# include <boost/python/detail/indirect_traits.hpp>
20# include <boost/python/detail/not_specified.hpp>
21# include <boost/python/detail/value_arg.hpp>
22
23# include <boost/type_traits/add_const.hpp>
24# include <boost/type_traits/add_reference.hpp>
25# include <boost/type_traits/is_member_pointer.hpp>
26
27# if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
28# include <boost/type_traits/remove_cv.hpp>
29# endif
30
31# include <boost/mpl/eval_if.hpp>
32# include <boost/mpl/if.hpp>
33# include <boost/mpl/vector/vector10.hpp>
34
35# include <boost/detail/workaround.hpp>
36
37namespace boost { namespace python {
38
39//
40// This file defines the make_getter and make_setter function
41// families, which are responsible for turning pointers, references,
42// and pointers-to-data-members into callable Python objects which
43// can be used for attribute access on wrapped classes.
44//
45
46namespace detail
47{
48
49 // A small function object which handles the getting and setting of
50 // data members.
51 template <class Data, class Class>
52 struct member
53 {
54 public:
55 member(Data Class::*which) : m_which(which) {}
56
57 Data& operator()(Class& c) const
58 {
59 return c.*m_which;
60 }
61
62 void operator()(Class& c, typename value_arg<Data>::type d) const
63 {
64 c.*m_which = d;
65 }
66 private:
67 Data Class::*m_which;
68 };
69
70 // A small function object which handles the getting and setting of
71 // non-member objects.
72 template <class Data>
73 struct datum
74 {
75 public:
76 datum(Data *which) : m_which(which) {}
77
78 Data& operator()() const
79 {
80 return *m_which;
81 }
82
83 void operator()(typename value_arg<Data>::type d) const
84 {
85 *m_which = d;
86 }
87 private:
88 Data *m_which;
89 };
90
91 //
92 // Helper metafunction for determining the default CallPolicy to use
93 // for attribute access. If T is a [reference to a] class type X
94 // whose conversion to python would normally produce a new copy of X
95 // in a wrapped X class instance (as opposed to types such as
96 // std::string, which are converted to native Python types, and
97 // smart pointer types which produce a wrapped class instance of the
98 // pointee type), to-python conversions will attempt to produce an
99 // object which refers to the original C++ object, rather than a
100 // copy. See default_member_getter_policy for rationale.
101 //
102 template <class T>
103 struct default_getter_by_ref
104 : mpl::and_<
105 mpl::bool_<
106 to_python_value<
107 typename value_arg<T>::type
108 >::uses_registry
109 >
110 , indirect_traits::is_reference_to_class<
111 typename value_arg<T>::type
112 >
113 >
114 {
115 };
116
117 // Metafunction computing the default CallPolicy to use for reading
118 // data members
119 //
120 // If it's a regular class type (not an object manager or other
121 // type for which we have to_python specializations, use
122 // return_internal_reference so that we can do things like
123 // x.y.z = 1
124 // and get the right result.
125 template <class T>
126 struct default_member_getter_policy
127 : mpl::if_<
128 default_getter_by_ref<T>
129 , return_internal_reference<>
130 , return_value_policy<return_by_value>
131 >
132 {};
133
134 // Metafunction computing the default CallPolicy to use for reading
135 // non-member data.
136 template <class T>
137 struct default_datum_getter_policy
138 : mpl::if_<
139 default_getter_by_ref<T>
140 , return_value_policy<reference_existing_object>
141 , return_value_policy<return_by_value>
142 >
143 {};
144
145 //
146 // make_getter helper function family -- These helpers to
147 // boost::python::make_getter are used to dispatch behavior. The
148 // third argument is a workaround for a CWPro8 partial ordering bug
149 // with pointers to data members. It should be convertible to
150 // mpl::true_ iff the first argument is a pointer-to-member, and
151 // mpl::false_ otherwise. The fourth argument is for compilers
152 // which don't support partial ordering at all and should always be
153 // passed 0L.
154 //
155
156#if BOOST_WORKAROUND(__EDG_VERSION__, <= 238)
157 template <class D, class P>
158 inline object make_getter(D& d, P& p, mpl::false_, ...);
159#endif
160
161 // Handle non-member pointers with policies
162 template <class D, class Policies>
163 inline object make_getter(D* d, Policies const& policies, mpl::false_, int)
164 {
165 return python::make_function(
166 detail::datum<D>(d), policies, mpl::vector1<D&>()
167 );
168 }
169
170 // Handle non-member pointers without policies
171 template <class D>
172 inline object make_getter(D* d, not_specified, mpl::false_, long)
173 {
174 typedef typename default_datum_getter_policy<D>::type policies;
175 return detail::make_getter(d, policies(), mpl::false_(), 0);
176 }
177
178 // Handle pointers-to-members with policies
179 template <class C, class D, class Policies>
180 inline object make_getter(D C::*pm, Policies const& policies, mpl::true_, int)
181 {
182#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
183 typedef typename remove_cv<C>::type Class;
184#else
185 typedef C Class;
186#endif
187 return python::make_function(
188 detail::member<D,Class>(pm)
189 , policies
190 , mpl::vector2<D&,Class&>()
191 );
192 }
193
194 // Handle pointers-to-members without policies
195 template <class C, class D>
196 inline object make_getter(D C::*pm, not_specified, mpl::true_, long)
197 {
198 typedef typename default_member_getter_policy<D>::type policies;
199 return detail::make_getter(pm, policies(), mpl::true_(), 0);
200 }
201
202 // Handle references
203 template <class D, class P>
204 inline object make_getter(D& d, P& p, mpl::false_, ...)
205 {
206 // Just dispatch to the handler for pointer types.
207 return detail::make_getter(&d, p, mpl::false_(), 0L);
208 }
209
210 //
211 // make_setter helper function family -- These helpers to
212 // boost::python::make_setter are used to dispatch behavior. The
213 // third argument is for compilers which don't support partial
214 // ordering at all and should always be passed 0.
215 //
216
217
218 // Handle non-member pointers
219 template <class D, class Policies>
220 inline object make_setter(D* p, Policies const& policies, mpl::false_, int)
221 {
222 return python::make_function(
223 detail::datum<D>(p), policies, mpl::vector2<void,D const&>()
224 );
225 }
226
227 // Handle pointers-to-members
228 template <class C, class D, class Policies>
229 inline object make_setter(D C::*pm, Policies const& policies, mpl::true_, int)
230 {
231 return python::make_function(
232 detail::member<D,C>(pm)
233 , policies
234 , mpl::vector3<void, C&, D const&>()
235 );
236 }
237
238 // Handle references
239 template <class D, class Policies>
240 inline object make_setter(D& x, Policies const& policies, mpl::false_, ...)
241 {
242 return detail::make_setter(&x, policies, mpl::false_(), 0L);
243 }
244}
245
246//
247// make_getter function family -- build a callable object which
248// retrieves data through the first argument and is appropriate for
249// use as the `get' function in Python properties . The second,
250// policies argument, is optional. We need both D& and D const&
251// overloads in order be able to handle rvalues.
252//
253template <class D, class Policies>
254inline object make_getter(D& d, Policies const& policies)
255{
256 return detail::make_getter(d, policies, is_member_pointer<D>(), 0L);
257}
258
259template <class D, class Policies>
260inline object make_getter(D const& d, Policies const& policies)
261{
262 return detail::make_getter(d, policies, is_member_pointer<D>(), 0L);
263}
264
265template <class D>
266inline object make_getter(D& x)
267{
268 detail::not_specified policy
269 = detail::not_specified(); // suppress a SunPro warning
270 return detail::make_getter(x, policy, is_member_pointer<D>(), 0L);
271}
272
273# if !BOOST_WORKAROUND(__EDG_VERSION__, <= 238)
274template <class D>
275inline object make_getter(D const& d)
276{
277 detail::not_specified policy
278 = detail::not_specified(); // Suppress a SunPro warning
279 return detail::make_getter(d, policy, is_member_pointer<D>(), 0L);
280}
281# endif
282
283//
284// make_setter function family -- build a callable object which
285// writes data through the first argument and is appropriate for
286// use as the `set' function in Python properties . The second,
287// policies argument, is optional. We need both D& and D const&
288// overloads in order be able to handle rvalues.
289//
290template <class D, class Policies>
291inline object make_setter(D& x, Policies const& policies)
292{
293 return detail::make_setter(x, policies, is_member_pointer<D>(), 0);
294}
295
296template <class D, class Policies>
297inline object make_setter(D const& x, Policies const& policies)
298{
299 return detail::make_setter(x, policies, is_member_pointer<D>(), 0);
300}
301
302template <class D>
303inline object make_setter(D& x)
304{
305 return detail::make_setter(x, default_call_policies(), is_member_pointer<D>(), 0);
306}
307
308# if !BOOST_WORKAROUND(__EDG_VERSION__, <= 238)
309template <class D>
310inline object make_setter(D const& x)
311{
312 return detail::make_setter(x, default_call_policies(), is_member_pointer<D>(), 0);
313}
314# endif
315
316}} // namespace boost::python
317
318#endif // DATA_MEMBERS_DWA2002328_HPP
319

source code of boost/boost/python/data_members.hpp