1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/ossrv_pub/boost_apis/boost/python/data_members.hpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,316 @@
1.4 +// Copyright David Abrahams 2002.
1.5 +// Distributed under the Boost Software License, Version 1.0. (See
1.6 +// accompanying file LICENSE_1_0.txt or copy at
1.7 +// http://www.boost.org/LICENSE_1_0.txt)
1.8 +#ifndef DATA_MEMBERS_DWA2002328_HPP
1.9 +# define DATA_MEMBERS_DWA2002328_HPP
1.10 +
1.11 +# include <boost/python/detail/prefix.hpp>
1.12 +
1.13 +# include <boost/python/handle.hpp>
1.14 +
1.15 +# include <boost/python/return_value_policy.hpp>
1.16 +# include <boost/python/return_by_value.hpp>
1.17 +# include <boost/python/return_internal_reference.hpp>
1.18 +# include <boost/python/make_function.hpp>
1.19 +
1.20 +# include <boost/python/converter/builtin_converters.hpp>
1.21 +
1.22 +# include <boost/python/detail/indirect_traits.hpp>
1.23 +# include <boost/python/detail/not_specified.hpp>
1.24 +# include <boost/python/detail/value_arg.hpp>
1.25 +
1.26 +# include <boost/type_traits/add_const.hpp>
1.27 +# include <boost/type_traits/add_reference.hpp>
1.28 +# include <boost/type_traits/is_member_pointer.hpp>
1.29 +
1.30 +# if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
1.31 +# include <boost/type_traits/remove_cv.hpp>
1.32 +# endif
1.33 +
1.34 +# include <boost/mpl/eval_if.hpp>
1.35 +# include <boost/mpl/if.hpp>
1.36 +# include <boost/mpl/vector/vector10.hpp>
1.37 +
1.38 +# include <boost/detail/workaround.hpp>
1.39 +
1.40 +namespace boost { namespace python {
1.41 +
1.42 +//
1.43 +// This file defines the make_getter and make_setter function
1.44 +// families, which are responsible for turning pointers, references,
1.45 +// and pointers-to-data-members into callable Python objects which
1.46 +// can be used for attribute access on wrapped classes.
1.47 +//
1.48 +
1.49 +namespace detail
1.50 +{
1.51 +
1.52 + // A small function object which handles the getting and setting of
1.53 + // data members.
1.54 + template <class Data, class Class>
1.55 + struct member
1.56 + {
1.57 + public:
1.58 + member(Data Class::*which) : m_which(which) {}
1.59 +
1.60 + Data& operator()(Class& c) const
1.61 + {
1.62 + return c.*m_which;
1.63 + }
1.64 +
1.65 + void operator()(Class& c, typename value_arg<Data>::type d) const
1.66 + {
1.67 + c.*m_which = d;
1.68 + }
1.69 + private:
1.70 + Data Class::*m_which;
1.71 + };
1.72 +
1.73 + // A small function object which handles the getting and setting of
1.74 + // non-member objects.
1.75 + template <class Data>
1.76 + struct datum
1.77 + {
1.78 + public:
1.79 + datum(Data *which) : m_which(which) {}
1.80 +
1.81 + Data& operator()() const
1.82 + {
1.83 + return *m_which;
1.84 + }
1.85 +
1.86 + void operator()(typename value_arg<Data>::type d) const
1.87 + {
1.88 + *m_which = d;
1.89 + }
1.90 + private:
1.91 + Data *m_which;
1.92 + };
1.93 +
1.94 + //
1.95 + // Helper metafunction for determining the default CallPolicy to use
1.96 + // for attribute access. If T is a [reference to a] class type X
1.97 + // whose conversion to python would normally produce a new copy of X
1.98 + // in a wrapped X class instance (as opposed to types such as
1.99 + // std::string, which are converted to native Python types, and
1.100 + // smart pointer types which produce a wrapped class instance of the
1.101 + // pointee type), to-python conversions will attempt to produce an
1.102 + // object which refers to the original C++ object, rather than a
1.103 + // copy. See default_member_getter_policy for rationale.
1.104 + //
1.105 + template <class T>
1.106 + struct default_getter_by_ref
1.107 + : mpl::and_<
1.108 + mpl::bool_<
1.109 + to_python_value<
1.110 + typename value_arg<T>::type
1.111 + >::uses_registry
1.112 + >
1.113 + , indirect_traits::is_reference_to_class<
1.114 + typename value_arg<T>::type
1.115 + >
1.116 + >
1.117 + {
1.118 + };
1.119 +
1.120 + // Metafunction computing the default CallPolicy to use for reading
1.121 + // data members
1.122 + //
1.123 + // If it's a regular class type (not an object manager or other
1.124 + // type for which we have to_python specializations, use
1.125 + // return_internal_reference so that we can do things like
1.126 + // x.y.z = 1
1.127 + // and get the right result.
1.128 + template <class T>
1.129 + struct default_member_getter_policy
1.130 + : mpl::if_<
1.131 + default_getter_by_ref<T>
1.132 + , return_internal_reference<>
1.133 + , return_value_policy<return_by_value>
1.134 + >
1.135 + {};
1.136 +
1.137 + // Metafunction computing the default CallPolicy to use for reading
1.138 + // non-member data.
1.139 + template <class T>
1.140 + struct default_datum_getter_policy
1.141 + : mpl::if_<
1.142 + default_getter_by_ref<T>
1.143 + , return_value_policy<reference_existing_object>
1.144 + , return_value_policy<return_by_value>
1.145 + >
1.146 + {};
1.147 +
1.148 + //
1.149 + // make_getter helper function family -- These helpers to
1.150 + // boost::python::make_getter are used to dispatch behavior. The
1.151 + // third argument is a workaround for a CWPro8 partial ordering bug
1.152 + // with pointers to data members. It should be convertible to
1.153 + // mpl::true_ iff the first argument is a pointer-to-member, and
1.154 + // mpl::false_ otherwise. The fourth argument is for compilers
1.155 + // which don't support partial ordering at all and should always be
1.156 + // passed 0L.
1.157 + //
1.158 +
1.159 +#if BOOST_WORKAROUND(__EDG_VERSION__, <= 238)
1.160 + template <class D, class P>
1.161 + inline object make_getter(D& d, P& p, mpl::false_, ...);
1.162 +#endif
1.163 +
1.164 + // Handle non-member pointers with policies
1.165 + template <class D, class Policies>
1.166 + inline object make_getter(D* d, Policies const& policies, mpl::false_, int)
1.167 + {
1.168 + return python::make_function(
1.169 + detail::datum<D>(d), policies, mpl::vector1<D&>()
1.170 + );
1.171 + }
1.172 +
1.173 + // Handle non-member pointers without policies
1.174 + template <class D>
1.175 + inline object make_getter(D* d, not_specified, mpl::false_, long)
1.176 + {
1.177 + typedef typename default_datum_getter_policy<D>::type policies;
1.178 + return detail::make_getter(d, policies(), mpl::false_(), 0);
1.179 + }
1.180 +
1.181 + // Handle pointers-to-members with policies
1.182 + template <class C, class D, class Policies>
1.183 + inline object make_getter(D C::*pm, Policies const& policies, mpl::true_, int)
1.184 + {
1.185 +#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
1.186 + typedef typename remove_cv<C>::type Class;
1.187 +#else
1.188 + typedef C Class;
1.189 +#endif
1.190 + return python::make_function(
1.191 + detail::member<D,Class>(pm)
1.192 + , policies
1.193 + , mpl::vector2<D&,Class&>()
1.194 + );
1.195 + }
1.196 +
1.197 + // Handle pointers-to-members without policies
1.198 + template <class C, class D>
1.199 + inline object make_getter(D C::*pm, not_specified, mpl::true_, long)
1.200 + {
1.201 + typedef typename default_member_getter_policy<D>::type policies;
1.202 + return detail::make_getter(pm, policies(), mpl::true_(), 0);
1.203 + }
1.204 +
1.205 + // Handle references
1.206 + template <class D, class P>
1.207 + inline object make_getter(D& d, P& p, mpl::false_, ...)
1.208 + {
1.209 + // Just dispatch to the handler for pointer types.
1.210 + return detail::make_getter(&d, p, mpl::false_(), 0L);
1.211 + }
1.212 +
1.213 + //
1.214 + // make_setter helper function family -- These helpers to
1.215 + // boost::python::make_setter are used to dispatch behavior. The
1.216 + // third argument is for compilers which don't support partial
1.217 + // ordering at all and should always be passed 0.
1.218 + //
1.219 +
1.220 +
1.221 + // Handle non-member pointers
1.222 + template <class D, class Policies>
1.223 + inline object make_setter(D* p, Policies const& policies, mpl::false_, int)
1.224 + {
1.225 + return python::make_function(
1.226 + detail::datum<D>(p), policies, mpl::vector2<void,D const&>()
1.227 + );
1.228 + }
1.229 +
1.230 + // Handle pointers-to-members
1.231 + template <class C, class D, class Policies>
1.232 + inline object make_setter(D C::*pm, Policies const& policies, mpl::true_, int)
1.233 + {
1.234 + return python::make_function(
1.235 + detail::member<D,C>(pm)
1.236 + , policies
1.237 + , mpl::vector3<void, C&, D const&>()
1.238 + );
1.239 + }
1.240 +
1.241 + // Handle references
1.242 + template <class D, class Policies>
1.243 + inline object make_setter(D& x, Policies const& policies, mpl::false_, ...)
1.244 + {
1.245 + return detail::make_setter(&x, policies, mpl::false_(), 0L);
1.246 + }
1.247 +}
1.248 +
1.249 +//
1.250 +// make_getter function family -- build a callable object which
1.251 +// retrieves data through the first argument and is appropriate for
1.252 +// use as the `get' function in Python properties . The second,
1.253 +// policies argument, is optional. We need both D& and D const&
1.254 +// overloads in order be able to handle rvalues.
1.255 +//
1.256 +template <class D, class Policies>
1.257 +inline object make_getter(D& d, Policies const& policies)
1.258 +{
1.259 + return detail::make_getter(d, policies, is_member_pointer<D>(), 0L);
1.260 +}
1.261 +
1.262 +template <class D, class Policies>
1.263 +inline object make_getter(D const& d, Policies const& policies)
1.264 +{
1.265 + return detail::make_getter(d, policies, is_member_pointer<D>(), 0L);
1.266 +}
1.267 +
1.268 +template <class D>
1.269 +inline object make_getter(D& x)
1.270 +{
1.271 + detail::not_specified policy;
1.272 + return detail::make_getter(x, policy, is_member_pointer<D>(), 0L);
1.273 +}
1.274 +
1.275 +# if !BOOST_WORKAROUND(__EDG_VERSION__, <= 238) && !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
1.276 +template <class D>
1.277 +inline object make_getter(D const& d)
1.278 +{
1.279 + detail::not_specified policy;
1.280 + return detail::make_getter(d, policy, is_member_pointer<D>(), 0L);
1.281 +}
1.282 +# endif
1.283 +
1.284 +//
1.285 +// make_setter function family -- build a callable object which
1.286 +// writes data through the first argument and is appropriate for
1.287 +// use as the `set' function in Python properties . The second,
1.288 +// policies argument, is optional. We need both D& and D const&
1.289 +// overloads in order be able to handle rvalues.
1.290 +//
1.291 +template <class D, class Policies>
1.292 +inline object make_setter(D& x, Policies const& policies)
1.293 +{
1.294 + return detail::make_setter(x, policies, is_member_pointer<D>(), 0);
1.295 +}
1.296 +
1.297 +template <class D, class Policies>
1.298 +inline object make_setter(D const& x, Policies const& policies)
1.299 +{
1.300 + return detail::make_setter(x, policies, is_member_pointer<D>(), 0);
1.301 +}
1.302 +
1.303 +template <class D>
1.304 +inline object make_setter(D& x)
1.305 +{
1.306 + return detail::make_setter(x, default_call_policies(), is_member_pointer<D>(), 0);
1.307 +}
1.308 +
1.309 +# if !(BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || BOOST_WORKAROUND(__EDG_VERSION__, <= 238))
1.310 +template <class D>
1.311 +inline object make_setter(D const& x)
1.312 +{
1.313 + return detail::make_setter(x, default_call_policies(), is_member_pointer<D>(), 0);
1.314 +}
1.315 +# endif
1.316 +
1.317 +}} // namespace boost::python
1.318 +
1.319 +#endif // DATA_MEMBERS_DWA2002328_HPP