Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-19 09:46:09

0001 // Copyright David Abrahams 2002.
0002 // Distributed under the Boost Software License, Version 1.0. (See
0003 // accompanying file LICENSE_1_0.txt or copy at
0004 // http://www.boost.org/LICENSE_1_0.txt)
0005 #ifndef DATA_MEMBERS_DWA2002328_HPP
0006 # define DATA_MEMBERS_DWA2002328_HPP
0007 
0008 # include <boost/python/detail/prefix.hpp>
0009 
0010 # include <boost/python/handle.hpp>
0011 
0012 # include <boost/python/return_value_policy.hpp>
0013 # include <boost/python/return_by_value.hpp>
0014 # include <boost/python/return_internal_reference.hpp>
0015 # include <boost/python/make_function.hpp>
0016 
0017 # include <boost/python/converter/builtin_converters.hpp>
0018 
0019 # include <boost/python/detail/indirect_traits.hpp>
0020 # include <boost/python/detail/not_specified.hpp>
0021 # include <boost/python/detail/value_arg.hpp>
0022 # include <boost/python/detail/type_traits.hpp>
0023 
0024 # include <boost/mpl/eval_if.hpp>
0025 # include <boost/mpl/if.hpp>
0026 # include <boost/mpl/vector/vector10.hpp>
0027 
0028 # include <boost/detail/workaround.hpp>
0029 
0030 namespace boost { namespace python { 
0031 
0032 //
0033 // This file defines the make_getter and make_setter function
0034 // families, which are responsible for turning pointers, references,
0035 // and pointers-to-data-members into callable Python objects which
0036 // can be used for attribute access on wrapped classes.
0037 //
0038 
0039 namespace detail
0040 {
0041 
0042   // A small function object which handles the getting and setting of
0043   // data members.
0044   template <class Data, class Class>
0045   struct member
0046   {
0047    public:      
0048       member(Data Class::*which) : m_which(which) {}
0049       
0050       Data& operator()(Class& c) const
0051       {
0052           return c.*m_which;
0053       }
0054 
0055       void operator()(Class& c, typename value_arg<Data>::type d) const
0056       {
0057           c.*m_which = d;
0058       }
0059    private:
0060       Data Class::*m_which;
0061   };
0062 
0063   // A small function object which handles the getting and setting of
0064   // non-member objects.
0065   template <class Data>
0066   struct datum
0067   {
0068    public:      
0069       datum(Data *which) : m_which(which) {}
0070       
0071       Data& operator()() const
0072       {
0073           return *m_which;
0074       }
0075 
0076       void operator()(typename value_arg<Data>::type d) const
0077       {
0078           *m_which = d;
0079       }
0080    private:
0081       Data *m_which;
0082   };
0083   
0084   //
0085   // Helper metafunction for determining the default CallPolicy to use
0086   // for attribute access.  If T is a [reference to a] class type X
0087   // whose conversion to python would normally produce a new copy of X
0088   // in a wrapped X class instance (as opposed to types such as
0089   // std::string, which are converted to native Python types, and
0090   // smart pointer types which produce a wrapped class instance of the
0091   // pointee type), to-python conversions will attempt to produce an
0092   // object which refers to the original C++ object, rather than a
0093   // copy.  See default_member_getter_policy for rationale.
0094   // 
0095   template <class T>
0096   struct default_getter_by_ref
0097       : mpl::and_<
0098           mpl::bool_<
0099               to_python_value<
0100                   typename value_arg<T>::type
0101               >::uses_registry
0102           >
0103         , indirect_traits::is_reference_to_class<
0104               typename value_arg<T>::type
0105           >
0106        >
0107   {
0108   };
0109 
0110   // Metafunction computing the default CallPolicy to use for reading
0111   // data members
0112   //
0113   // If it's a regular class type (not an object manager or other
0114   // type for which we have to_python specializations, use
0115   // return_internal_reference so that we can do things like
0116   //    x.y.z =  1
0117   // and get the right result.
0118   template <class T>
0119   struct default_member_getter_policy
0120     : mpl::if_<
0121           default_getter_by_ref<T>
0122         , return_internal_reference<>
0123         , return_value_policy<return_by_value>
0124       >
0125   {};
0126 
0127   // Metafunction computing the default CallPolicy to use for reading
0128   // non-member data.
0129   template <class T>
0130   struct default_datum_getter_policy
0131     : mpl::if_<
0132           default_getter_by_ref<T>
0133         , return_value_policy<reference_existing_object>
0134         , return_value_policy<return_by_value>
0135       >
0136   {};
0137 
0138   //
0139   // make_getter helper function family -- These helpers to
0140   // boost::python::make_getter are used to dispatch behavior.  The
0141   // third argument is a workaround for a CWPro8 partial ordering bug
0142   // with pointers to data members.  It should be convertible to
0143   // detail::true_ iff the first argument is a pointer-to-member, and
0144   // detail::false_ otherwise.  The fourth argument is for compilers
0145   // which don't support partial ordering at all and should always be
0146   // passed 0L.
0147 
0148 
0149 #if BOOST_WORKAROUND(__EDG_VERSION__, <= 238)
0150   template <class D, class P>
0151   inline object make_getter(D& d, P& p, detail::false_, ...);
0152 #endif
0153 
0154   // Handle non-member pointers with policies
0155   template <class D, class Policies>
0156   inline object make_getter(D* d, Policies const& policies, detail::false_, int)
0157   {
0158       return python::make_function(
0159           detail::datum<D>(d), policies, mpl::vector1<D&>()
0160       );
0161   }
0162   
0163   // Handle non-member pointers without policies
0164   template <class D>
0165   inline object make_getter(D* d, not_specified, detail::false_, long)
0166   {
0167       typedef typename default_datum_getter_policy<D>::type policies;
0168       return detail::make_getter(d, policies(), detail::false_(), 0);
0169   }
0170 
0171   // Handle pointers-to-members with policies
0172   template <class C, class D, class Policies>
0173   inline object make_getter(D C::*pm, Policies const& policies, detail::true_, int)
0174   {
0175 #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
0176       typedef typename detail::remove_cv<C>::type Class;
0177 #else
0178       typedef C Class;
0179 #endif 
0180       return python::make_function(
0181           detail::member<D,Class>(pm)
0182         , policies
0183         , mpl::vector2<D&,Class&>()
0184       );
0185   }
0186       
0187   // Handle pointers-to-members without policies
0188   template <class C, class D>
0189   inline object make_getter(D C::*pm, not_specified, detail::true_, long)
0190   {
0191       typedef typename default_member_getter_policy<D>::type policies;
0192       return detail::make_getter(pm, policies(), detail::true_(), 0);
0193   }
0194 
0195   // Handle references
0196   template <class D, class P>
0197   inline object make_getter(D& d, P& p, detail::false_, ...)
0198   {
0199       // Just dispatch to the handler for pointer types.
0200       return detail::make_getter(&d, p, detail::false_(), 0L);
0201   }
0202 
0203   //
0204   // make_setter helper function family -- These helpers to
0205   // boost::python::make_setter are used to dispatch behavior.  The
0206   // third argument is for compilers which don't support partial
0207   // ordering at all and should always be passed 0.
0208   //
0209 
0210   
0211   // Handle non-member pointers
0212   template <class D, class Policies>
0213   inline object make_setter(D* p, Policies const& policies, detail::false_, int)
0214   {
0215       return python::make_function(
0216           detail::datum<D>(p), policies, mpl::vector2<void,D const&>()
0217       );
0218   }
0219 
0220   // Handle pointers-to-members
0221   template <class C, class D, class Policies>
0222   inline object make_setter(D C::*pm, Policies const& policies, detail::true_, int)
0223   {
0224       return python::make_function(
0225           detail::member<D,C>(pm)
0226         , policies
0227         , mpl::vector3<void, C&, D const&>()
0228       );
0229   }
0230 
0231   // Handle references
0232   template <class D, class Policies>
0233   inline object make_setter(D& x, Policies const& policies, detail::false_, ...)
0234   {
0235       return detail::make_setter(&x, policies, detail::false_(), 0L);
0236   }
0237 }
0238 
0239 //
0240 // make_getter function family -- build a callable object which
0241 // retrieves data through the first argument and is appropriate for
0242 // use as the `get' function in Python properties .  The second,
0243 // policies argument, is optional.  We need both D& and D const&
0244 // overloads in order be able to handle rvalues.
0245 //
0246 template <class D, class Policies>
0247 inline object make_getter(D& d, Policies const& policies)
0248 {
0249     return detail::make_getter(d, policies, detail::is_member_pointer<D>(), 0L);
0250 }
0251 
0252 template <class D, class Policies>
0253 inline object make_getter(D const& d, Policies const& policies)
0254 {
0255     return detail::make_getter(d, policies, detail::is_member_pointer<D>(), 0L);
0256 }
0257 
0258 template <class D>
0259 inline object make_getter(D& x)
0260 {
0261     detail::not_specified policy
0262         = detail::not_specified(); // suppress a SunPro warning
0263     return detail::make_getter(x, policy, detail::is_member_pointer<D>(), 0L);
0264 }
0265 
0266 #  if !BOOST_WORKAROUND(__EDG_VERSION__, <= 238)
0267 template <class D>
0268 inline object make_getter(D const& d)
0269 {
0270     detail::not_specified policy
0271         = detail::not_specified(); // Suppress a SunPro warning
0272     return detail::make_getter(d, policy, detail::is_member_pointer<D>(), 0L);
0273 }
0274 #  endif
0275 
0276 //
0277 // make_setter function family -- build a callable object which
0278 // writes data through the first argument and is appropriate for
0279 // use as the `set' function in Python properties .  The second,
0280 // policies argument, is optional.  We need both D& and D const&
0281 // overloads in order be able to handle rvalues.
0282 //
0283 template <class D, class Policies>
0284 inline object make_setter(D& x, Policies const& policies)
0285 {
0286     return detail::make_setter(x, policies, detail::is_member_pointer<D>(), 0);
0287 }
0288 
0289 template <class D, class Policies>
0290 inline object make_setter(D const& x, Policies const& policies)
0291 {
0292     return detail::make_setter(x, policies, detail::is_member_pointer<D>(), 0);
0293 }
0294 
0295 template <class D>
0296 inline object make_setter(D& x)
0297 {
0298     return detail::make_setter(x, default_call_policies(), detail::is_member_pointer<D>(), 0);
0299 }
0300 
0301 # if !BOOST_WORKAROUND(__EDG_VERSION__, <= 238)
0302 template <class D>
0303 inline object make_setter(D const& x)
0304 {
0305     return detail::make_setter(x, default_call_policies(), detail::is_member_pointer<D>(), 0);
0306 }
0307 # endif
0308 
0309 }} // namespace boost::python
0310 
0311 #endif // DATA_MEMBERS_DWA2002328_HPP