Boost logo

Boost :

From: nksauter_at_[hidden]
Date: 2001-05-11 23:40:35


Now that Python 2.1 supports the notion of rich comparisons I
would like to implement support for these operators in the
Boost.Python library. My first attempt at doing this succeeded
only partially: I was able to define the Python 2.1 customization
functions (__gt__, __ge__, __lt__, __le__, __eq__, __ne__)
but this did not produce the expected result of overloading the
operators themselves, that is, a<b, etc. I am attaching the
relevant code in the hope that someone will be able to understand
what is missing.

Nick Sauter
Lawrence Berkeley Labs

To reproduce my test:

1. Make differences to boost/python/detail/extension_class.hpp:
619,624d618
< choose_op<(which & op_gt)>::template
args<Operand>::add(this);
< choose_op<(which & op_ge)>::template
args<Operand>::add(this);
< choose_op<(which & op_lt)>::template
args<Operand>::add(this);
< choose_op<(which & op_le)>::template
args<Operand>::add(this);
< choose_op<(which & op_eq)>::template
args<Operand>::add(this);
< choose_op<(which & op_ne)>::template
args<Operand>::add(this);
654,659d647
< choose_op<(which & op_gt)>::template
args<Left,Right>::add(this);
< choose_op<(which & op_ge)>::template
args<Left,Right>::add(this);
< choose_op<(which & op_lt)>::template
args<Left,Right>::add(this);
< choose_op<(which & op_le)>::template
args<Left,Right>::add(this);
< choose_op<(which & op_eq)>::template
args<Left,Right>::add(this);
< choose_op<(which & op_ne)>::template
args<Left,Right>::add(this);

2. Make differences to boost/python/operators.hpp:
68,74c68
< op_cmp = 0x100000,
< op_gt = 0x200000,
< op_ge = 0x400000,
< op_lt = 0x800000,
< op_le = 0x1000000,
< op_eq = 0x2000000,
< op_ne = 0x4000000

---
>     op_cmp = 0x100000
310,315d303
<   PY_DEFINE_BINARY_OPERATORS(gt, >);
<   PY_DEFINE_BINARY_OPERATORS(ge, >=);
<   PY_DEFINE_BINARY_OPERATORS(lt, <);
<   PY_DEFINE_BINARY_OPERATORS(le, <=);
<   PY_DEFINE_BINARY_OPERATORS(eq, ==);
<   PY_DEFINE_BINARY_OPERATORS(ne, !=);
3.  Now compile the following extension module, richcmpmodule.cpp:
#include <boost/python/cross_module.hpp>
#include <libs/python/example/dvect.h>
namespace {
#include <cctbx/basic/from_bpl_import.h>
#include <libs/python/example/dvect_conversions.cpp>
}//namespace
#define DVECT_BINARY_OPERATORS( oper ) \
vects::dvect operator##oper (const vects::dvect& a, const 
vects::dvect& b) {\
  if (a.size()!=b.size()){throw boost::python::argument_error();}     
  \
  vects::dvect result(a.size());                                      
      \
  vects::dvect::const_iterator a_it = a.begin();                      
      \
  vects::dvect::const_iterator b_it = b.begin();                      
      \
  vects::dvect::iterator r_it = result.begin();                       
      \
  for (int i=0; i<a.size(); i++) { r_it[i] = (a_it[i] ##oper
b_it[i]); 
}    \
  return result;                                                      
      \
}
DVECT_BINARY_OPERATORS( + )
DVECT_BINARY_OPERATORS( - )
DVECT_BINARY_OPERATORS( * )
DVECT_BINARY_OPERATORS( / )
DVECT_BINARY_OPERATORS( > )
DVECT_BINARY_OPERATORS( >= )
DVECT_BINARY_OPERATORS( < )
DVECT_BINARY_OPERATORS( <= )
DVECT_BINARY_OPERATORS( == )
DVECT_BINARY_OPERATORS( != )
#undef DVECT_BINARY_OPERATORS
BOOST_PYTHON_MODULE_INIT(richcmp)
{
  try
  {
    python::module_builder richcmp_module("richcmp");
    python::class_builder<vects::dvect> dvect_class(richcmp_module, 
"dvect");
    dvect_class.def(python::constructor<python::tuple>());
    dvect_class.def(&vects::dvect::as_tuple,"as_tuple");
#define all_operators (boost::python::op_mul | boost::python::op_add
| 
boost::python::op_div | boost::python::op_sub )
    dvect_class.def(boost::python::operators<all_operators>());
#define comp_operators (boost::python::op_gt | boost::python::op_ge  
|\
boost::python::op_lt | boost::python::op_le  | \
boost::python::op_eq | boost::python::op_ne)
    dvect_class.def(boost::python::operators<comp_operators>());
  }
  catch(...){python::handle_exception();}//Deal with the exception
for 
Python
}
4.  Test the module:
import richcmp
dv = richcmp.dvect((1,2,3,4,5))
print dv.as_tuple()
dv2 = richcmp.dvect((6,7,8,9,10))
print dv2.as_tuple()
print (dv+dv2).as_tuple()
print dv.__eq__(dv2).as_tuple()
print dv.__ne__(dv2).as_tuple()
print (dv == dv2) #result should be a dvect but comes out as an int

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk