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