os/ossrv/ossrv_pub/boost_apis/boost/python/operators.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 OPERATORS_DWA2002530_HPP
sl@0
     6
# define OPERATORS_DWA2002530_HPP
sl@0
     7
sl@0
     8
# include <boost/python/detail/prefix.hpp>
sl@0
     9
sl@0
    10
# include <boost/python/def_visitor.hpp>
sl@0
    11
# include <boost/python/converter/arg_to_python.hpp>
sl@0
    12
# include <boost/python/detail/operator_id.hpp>
sl@0
    13
# include <boost/python/detail/not_specified.hpp>
sl@0
    14
# include <boost/python/back_reference.hpp>
sl@0
    15
# include <boost/mpl/if.hpp>
sl@0
    16
# include <boost/mpl/eval_if.hpp>
sl@0
    17
# include <boost/python/self.hpp>
sl@0
    18
# include <boost/python/other.hpp>
sl@0
    19
# include <boost/lexical_cast.hpp>
sl@0
    20
# include <boost/python/refcount.hpp>
sl@0
    21
# include <boost/python/detail/unwrap_wrapper.hpp>
sl@0
    22
# include <string>
sl@0
    23
# include <complex>
sl@0
    24
sl@0
    25
namespace boost { namespace python { 
sl@0
    26
sl@0
    27
namespace detail
sl@0
    28
{
sl@0
    29
  // This is essentially the old v1 to_python(). It will be eliminated
sl@0
    30
  // once the public interface for to_python is settled on.
sl@0
    31
  template <class T>
sl@0
    32
  PyObject* convert_result(T const& x)
sl@0
    33
  {
sl@0
    34
      return converter::arg_to_python<T>(x).release();
sl@0
    35
  }
sl@0
    36
sl@0
    37
  // Operator implementation template declarations. The nested apply
sl@0
    38
  // declaration here keeps MSVC6 happy.
sl@0
    39
  template <operator_id> struct operator_l
sl@0
    40
  {
sl@0
    41
      template <class L, class R> struct apply;
sl@0
    42
  };
sl@0
    43
  
sl@0
    44
  template <operator_id> struct operator_r
sl@0
    45
  {
sl@0
    46
      template <class L, class R> struct apply;
sl@0
    47
  };
sl@0
    48
sl@0
    49
  template <operator_id> struct operator_1
sl@0
    50
  {
sl@0
    51
      template <class T> struct apply;
sl@0
    52
  };
sl@0
    53
sl@0
    54
  // MSVC6 doesn't want us to do this sort of inheritance on a nested
sl@0
    55
  // class template, so we use this layer of indirection to avoid
sl@0
    56
  // ::template<...> on the nested apply functions below
sl@0
    57
  template <operator_id id, class L, class R>
sl@0
    58
  struct operator_l_inner
sl@0
    59
      : operator_l<id>::template apply<L,R>
sl@0
    60
  {};
sl@0
    61
      
sl@0
    62
  template <operator_id id, class L, class R>
sl@0
    63
  struct operator_r_inner
sl@0
    64
      : operator_r<id>::template apply<L,R>
sl@0
    65
  {};
sl@0
    66
sl@0
    67
  template <operator_id id, class T>
sl@0
    68
  struct operator_1_inner
sl@0
    69
      : operator_1<id>::template apply<T>
sl@0
    70
  {};
sl@0
    71
      
sl@0
    72
  // Define three different binary_op templates which take care of
sl@0
    73
  // these cases:
sl@0
    74
  //    self op self
sl@0
    75
  //    self op R
sl@0
    76
  //    L op self
sl@0
    77
  // 
sl@0
    78
  // The inner apply metafunction is used to adjust the operator to
sl@0
    79
  // the class type being defined. Inheritance of the outer class is
sl@0
    80
  // simply used to provide convenient access to the operation's
sl@0
    81
  // name().
sl@0
    82
sl@0
    83
  // self op self
sl@0
    84
  template <operator_id id>
sl@0
    85
  struct binary_op : operator_l<id>
sl@0
    86
  {
sl@0
    87
      template <class T>
sl@0
    88
      struct apply : operator_l_inner<id,T,T>
sl@0
    89
      {
sl@0
    90
      };
sl@0
    91
  };
sl@0
    92
sl@0
    93
  // self op R
sl@0
    94
  template <operator_id id, class R>
sl@0
    95
  struct binary_op_l : operator_l<id>
sl@0
    96
  {
sl@0
    97
      template <class T>
sl@0
    98
      struct apply : operator_l_inner<id,T,R>
sl@0
    99
      {
sl@0
   100
      };
sl@0
   101
  };
sl@0
   102
sl@0
   103
  // L op self
sl@0
   104
  template <operator_id id, class L>
sl@0
   105
  struct binary_op_r : operator_r<id>
sl@0
   106
  {
sl@0
   107
      template <class T>
sl@0
   108
      struct apply : operator_r_inner<id,L,T>
sl@0
   109
      {
sl@0
   110
      };
sl@0
   111
  };
sl@0
   112
sl@0
   113
  template <operator_id id>
sl@0
   114
  struct unary_op : operator_1<id>
sl@0
   115
  {
sl@0
   116
      template <class T>
sl@0
   117
      struct apply : operator_1_inner<id,T>
sl@0
   118
      {
sl@0
   119
      };
sl@0
   120
  };
sl@0
   121
sl@0
   122
  // This type is what actually gets returned from operators used on
sl@0
   123
  // self_t
sl@0
   124
  template <operator_id id, class L = not_specified, class R = not_specified>
sl@0
   125
  struct operator_
sl@0
   126
    : def_visitor<operator_<id,L,R> >
sl@0
   127
  {
sl@0
   128
   private:
sl@0
   129
      template <class ClassT>
sl@0
   130
      void visit(ClassT& cl) const
sl@0
   131
      {
sl@0
   132
          typedef typename mpl::eval_if<
sl@0
   133
              is_same<L,self_t>
sl@0
   134
            , mpl::if_<
sl@0
   135
                  is_same<R,self_t>
sl@0
   136
                , binary_op<id>
sl@0
   137
                , binary_op_l<
sl@0
   138
                      id
sl@0
   139
                    , BOOST_DEDUCED_TYPENAME unwrap_other<R>::type
sl@0
   140
                  >
sl@0
   141
              >
sl@0
   142
            , mpl::if_<
sl@0
   143
                  is_same<L,not_specified>
sl@0
   144
                , unary_op<id>
sl@0
   145
                , binary_op_r<
sl@0
   146
                      id
sl@0
   147
                    , BOOST_DEDUCED_TYPENAME unwrap_other<L>::type
sl@0
   148
                  >
sl@0
   149
              >
sl@0
   150
          >::type generator;
sl@0
   151
      
sl@0
   152
          cl.def(
sl@0
   153
              generator::name()
sl@0
   154
            , &generator::template apply<
sl@0
   155
                 BOOST_DEDUCED_TYPENAME ClassT::wrapped_type
sl@0
   156
              >::execute
sl@0
   157
          );
sl@0
   158
      }
sl@0
   159
    
sl@0
   160
      friend class python::def_visitor_access;
sl@0
   161
  };
sl@0
   162
}
sl@0
   163
sl@0
   164
# define BOOST_PYTHON_BINARY_OPERATION(id, rid, expr)       \
sl@0
   165
namespace detail                                            \
sl@0
   166
{                                                           \
sl@0
   167
  template <>                                               \
sl@0
   168
  struct operator_l<op_##id>                                \
sl@0
   169
  {                                                         \
sl@0
   170
      template <class L, class R>                           \
sl@0
   171
      struct apply                                          \
sl@0
   172
      {                                                     \
sl@0
   173
          typedef typename unwrap_wrapper_<L>::type lhs;    \
sl@0
   174
          typedef typename unwrap_wrapper_<R>::type rhs;    \
sl@0
   175
          static PyObject* execute(lhs& l, rhs const& r)    \
sl@0
   176
          {                                                 \
sl@0
   177
              return detail::convert_result(expr);          \
sl@0
   178
          }                                                 \
sl@0
   179
      };                                                    \
sl@0
   180
      static char const* name() { return "__" #id "__"; }   \
sl@0
   181
  };                                                        \
sl@0
   182
                                                            \
sl@0
   183
  template <>                                               \
sl@0
   184
  struct operator_r<op_##id>                                \
sl@0
   185
  {                                                         \
sl@0
   186
      template <class L, class R>                           \
sl@0
   187
      struct apply                                          \
sl@0
   188
      {                                                     \
sl@0
   189
          typedef typename unwrap_wrapper_<L>::type lhs;    \
sl@0
   190
          typedef typename unwrap_wrapper_<R>::type rhs;    \
sl@0
   191
          static PyObject* execute(rhs& r, lhs const& l)    \
sl@0
   192
          {                                                 \
sl@0
   193
              return detail::convert_result(expr);          \
sl@0
   194
          }                                                 \
sl@0
   195
      };                                                    \
sl@0
   196
      static char const* name() { return "__" #rid "__"; }  \
sl@0
   197
  };                                                        \
sl@0
   198
} 
sl@0
   199
sl@0
   200
# define BOOST_PYTHON_BINARY_OPERATOR(id, rid, op)      \
sl@0
   201
BOOST_PYTHON_BINARY_OPERATION(id, rid, l op r)          \
sl@0
   202
namespace self_ns                                       \
sl@0
   203
{                                                       \
sl@0
   204
  template <class L, class R>                           \
sl@0
   205
  inline detail::operator_<detail::op_##id,L,R>         \
sl@0
   206
  operator op(L const&, R const&)                       \
sl@0
   207
  {                                                     \
sl@0
   208
      return detail::operator_<detail::op_##id,L,R>();  \
sl@0
   209
  }                                                     \
sl@0
   210
}
sl@0
   211
  
sl@0
   212
BOOST_PYTHON_BINARY_OPERATOR(add, radd, +)
sl@0
   213
BOOST_PYTHON_BINARY_OPERATOR(sub, rsub, -)
sl@0
   214
BOOST_PYTHON_BINARY_OPERATOR(mul, rmul, *)
sl@0
   215
BOOST_PYTHON_BINARY_OPERATOR(div, rdiv, /)
sl@0
   216
BOOST_PYTHON_BINARY_OPERATOR(mod, rmod, %)
sl@0
   217
BOOST_PYTHON_BINARY_OPERATOR(lshift, rlshift, <<)
sl@0
   218
BOOST_PYTHON_BINARY_OPERATOR(rshift, rrshift, >>)
sl@0
   219
BOOST_PYTHON_BINARY_OPERATOR(and, rand, &)
sl@0
   220
BOOST_PYTHON_BINARY_OPERATOR(xor, rxor, ^)
sl@0
   221
BOOST_PYTHON_BINARY_OPERATOR(or, ror, |)
sl@0
   222
BOOST_PYTHON_BINARY_OPERATOR(gt, lt, >)
sl@0
   223
BOOST_PYTHON_BINARY_OPERATOR(ge, le, >=)
sl@0
   224
BOOST_PYTHON_BINARY_OPERATOR(lt, gt, <)
sl@0
   225
BOOST_PYTHON_BINARY_OPERATOR(le, ge, <=)
sl@0
   226
BOOST_PYTHON_BINARY_OPERATOR(eq, eq, ==)
sl@0
   227
BOOST_PYTHON_BINARY_OPERATOR(ne, ne, !=)
sl@0
   228
# undef BOOST_PYTHON_BINARY_OPERATOR
sl@0
   229
    
sl@0
   230
// pow isn't an operator in C++; handle it specially.
sl@0
   231
BOOST_PYTHON_BINARY_OPERATION(pow, rpow, pow(l,r))
sl@0
   232
# undef BOOST_PYTHON_BINARY_OPERATION
sl@0
   233
    
sl@0
   234
namespace self_ns
sl@0
   235
{
sl@0
   236
# ifndef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
sl@0
   237
  template <class L, class R>
sl@0
   238
  inline detail::operator_<detail::op_pow,L,R>
sl@0
   239
  pow(L const&, R const&)
sl@0
   240
  {
sl@0
   241
      return detail::operator_<detail::op_pow,L,R>();
sl@0
   242
  }
sl@0
   243
# else
sl@0
   244
  // When there's no argument-dependent lookup, we need these
sl@0
   245
  // overloads to handle the case when everything is imported into the
sl@0
   246
  // global namespace. Note that the plain overload below does /not/
sl@0
   247
  // take const& arguments. This is needed by MSVC6 at least, or it
sl@0
   248
  // complains of ambiguities, since there's no partial ordering.
sl@0
   249
  inline detail::operator_<detail::op_pow,self_t,self_t>
sl@0
   250
  pow(self_t, self_t)
sl@0
   251
  {
sl@0
   252
      return detail::operator_<detail::op_pow,self_t,self_t>();
sl@0
   253
  }
sl@0
   254
  template <class R>
sl@0
   255
  inline detail::operator_<detail::op_pow,self_t,R>
sl@0
   256
  pow(self_t const&, R const&)
sl@0
   257
  {
sl@0
   258
      return detail::operator_<detail::op_pow,self_t,R>();
sl@0
   259
  }
sl@0
   260
  template <class L>
sl@0
   261
  inline detail::operator_<detail::op_pow,L,self_t>
sl@0
   262
  pow(L const&, self_t const&)
sl@0
   263
  {
sl@0
   264
      return detail::operator_<detail::op_pow,L,self_t>();
sl@0
   265
  }
sl@0
   266
# endif 
sl@0
   267
}
sl@0
   268
sl@0
   269
sl@0
   270
# define BOOST_PYTHON_INPLACE_OPERATOR(id, op)                  \
sl@0
   271
namespace detail                                                \
sl@0
   272
{                                                               \
sl@0
   273
  template <>                                                   \
sl@0
   274
  struct operator_l<op_##id>                                    \
sl@0
   275
  {                                                             \
sl@0
   276
      template <class L, class R>                               \
sl@0
   277
      struct apply                                              \
sl@0
   278
      {                                                         \
sl@0
   279
          typedef typename unwrap_wrapper_<L>::type lhs;        \
sl@0
   280
          typedef typename unwrap_wrapper_<R>::type rhs;        \
sl@0
   281
          static PyObject*                                      \
sl@0
   282
          execute(back_reference<lhs&> l, rhs const& r)         \
sl@0
   283
          {                                                     \
sl@0
   284
              l.get() op r;                                     \
sl@0
   285
              return python::incref(l.source().ptr());          \
sl@0
   286
          }                                                     \
sl@0
   287
      };                                                        \
sl@0
   288
      static char const* name() { return "__" #id "__"; }       \
sl@0
   289
  };                                                            \
sl@0
   290
}                                                               \
sl@0
   291
namespace self_ns                                               \
sl@0
   292
{                                                               \
sl@0
   293
  template <class R>                                            \
sl@0
   294
  inline detail::operator_<detail::op_##id,self_t,R>            \
sl@0
   295
  operator op(self_t const&, R const&)                          \
sl@0
   296
  {                                                             \
sl@0
   297
      return detail::operator_<detail::op_##id,self_t,R>();     \
sl@0
   298
  }                                                             \
sl@0
   299
}
sl@0
   300
sl@0
   301
BOOST_PYTHON_INPLACE_OPERATOR(iadd,+=)
sl@0
   302
BOOST_PYTHON_INPLACE_OPERATOR(isub,-=)
sl@0
   303
BOOST_PYTHON_INPLACE_OPERATOR(imul,*=)
sl@0
   304
BOOST_PYTHON_INPLACE_OPERATOR(idiv,/=)
sl@0
   305
BOOST_PYTHON_INPLACE_OPERATOR(imod,%=)
sl@0
   306
BOOST_PYTHON_INPLACE_OPERATOR(ilshift,<<=)
sl@0
   307
BOOST_PYTHON_INPLACE_OPERATOR(irshift,>>=)
sl@0
   308
BOOST_PYTHON_INPLACE_OPERATOR(iand,&=)
sl@0
   309
BOOST_PYTHON_INPLACE_OPERATOR(ixor,^=)
sl@0
   310
BOOST_PYTHON_INPLACE_OPERATOR(ior,|=)
sl@0
   311
    
sl@0
   312
# define BOOST_PYTHON_UNARY_OPERATOR(id, op, func_name)         \
sl@0
   313
namespace detail                                                \
sl@0
   314
{                                                               \
sl@0
   315
  template <>                                                   \
sl@0
   316
  struct operator_1<op_##id>                                    \
sl@0
   317
  {                                                             \
sl@0
   318
      template <class T>                                        \
sl@0
   319
      struct apply                                              \
sl@0
   320
      {                                                         \
sl@0
   321
          typedef typename unwrap_wrapper_<T>::type self_t;     \
sl@0
   322
          static PyObject* execute(self_t& x)                   \
sl@0
   323
          {                                                     \
sl@0
   324
              return detail::convert_result(op(x));             \
sl@0
   325
          }                                                     \
sl@0
   326
      };                                                        \
sl@0
   327
      static char const* name() { return "__" #id "__"; }       \
sl@0
   328
  };                                                            \
sl@0
   329
}                                                               \
sl@0
   330
namespace self_ns                                               \
sl@0
   331
{                                                               \
sl@0
   332
  inline detail::operator_<detail::op_##id>                     \
sl@0
   333
  func_name(self_t const&)                                      \
sl@0
   334
  {                                                             \
sl@0
   335
      return detail::operator_<detail::op_##id>();              \
sl@0
   336
  }                                                             \
sl@0
   337
}
sl@0
   338
# undef BOOST_PYTHON_INPLACE_OPERATOR
sl@0
   339
sl@0
   340
BOOST_PYTHON_UNARY_OPERATOR(neg, -, operator-)
sl@0
   341
BOOST_PYTHON_UNARY_OPERATOR(pos, +, operator+)
sl@0
   342
BOOST_PYTHON_UNARY_OPERATOR(abs, abs, abs)
sl@0
   343
BOOST_PYTHON_UNARY_OPERATOR(invert, ~, operator~)
sl@0
   344
BOOST_PYTHON_UNARY_OPERATOR(nonzero, !!, operator!)
sl@0
   345
BOOST_PYTHON_UNARY_OPERATOR(int, long, int_)
sl@0
   346
BOOST_PYTHON_UNARY_OPERATOR(long, PyLong_FromLong, long_)
sl@0
   347
BOOST_PYTHON_UNARY_OPERATOR(float, double, float_)
sl@0
   348
BOOST_PYTHON_UNARY_OPERATOR(complex, std::complex<double>, complex_)
sl@0
   349
BOOST_PYTHON_UNARY_OPERATOR(str, lexical_cast<std::string>, str)
sl@0
   350
# undef BOOST_PYTHON_UNARY_OPERATOR
sl@0
   351
sl@0
   352
}} // namespace boost::python
sl@0
   353
sl@0
   354
# ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
sl@0
   355
using boost::python::self_ns::abs;
sl@0
   356
using boost::python::self_ns::int_;
sl@0
   357
using boost::python::self_ns::long_;
sl@0
   358
using boost::python::self_ns::float_;
sl@0
   359
using boost::python::self_ns::complex_;
sl@0
   360
using boost::python::self_ns::str;
sl@0
   361
using boost::python::self_ns::pow;
sl@0
   362
# endif
sl@0
   363
sl@0
   364
#endif // OPERATORS_DWA2002530_HPP