source: NonGTP/Boost/boost/python/data_members.hpp @ 857

Revision 857, 9.7 KB checked in by igarcia, 18 years ago (diff)
Line 
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    return detail::make_getter(x, policy, is_member_pointer<D>(), 0L);
270}
271
272#  if !BOOST_WORKAROUND(__EDG_VERSION__, <= 238) && !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
273template <class D>
274inline object make_getter(D const& d)
275{
276    detail::not_specified policy;
277    return detail::make_getter(d, policy, is_member_pointer<D>(), 0L);
278}
279#  endif
280
281//
282// make_setter function family -- build a callable object which
283// writes data through the first argument and is appropriate for
284// use as the `set' function in Python properties .  The second,
285// policies argument, is optional.  We need both D& and D const&
286// overloads in order be able to handle rvalues.
287//
288template <class D, class Policies>
289inline object make_setter(D& x, Policies const& policies)
290{
291    return detail::make_setter(x, policies, is_member_pointer<D>(), 0);
292}
293
294template <class D, class Policies>
295inline object make_setter(D const& x, Policies const& policies)
296{
297    return detail::make_setter(x, policies, is_member_pointer<D>(), 0);
298}
299
300template <class D>
301inline object make_setter(D& x)
302{
303    return detail::make_setter(x, default_call_policies(), is_member_pointer<D>(), 0);
304}
305
306# if !(BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || BOOST_WORKAROUND(__EDG_VERSION__, <= 238))
307template <class D>
308inline object make_setter(D const& x)
309{
310    return detail::make_setter(x, default_call_policies(), is_member_pointer<D>(), 0);
311}
312# endif
313
314}} // namespace boost::python
315
316#endif // DATA_MEMBERS_DWA2002328_HPP
Note: See TracBrowser for help on using the repository browser.