diff --git a/extclass.h b/extclass.h index 5deb5210..840293f3 100644 --- a/extclass.h +++ b/extclass.h @@ -63,6 +63,8 @@ namespace detail { }; typedef BaseClassInfo DerivedClassInfo; + + struct add_operator_base; } class ExtensionClassBase : public Class @@ -86,6 +88,7 @@ class ExtensionClassBase : public Class virtual std::vector const& derived_classes() const = 0; protected: + friend struct detail::add_operator_base; void add_method(PyPtr method, const char* name); void add_method(Function* method, const char* name); @@ -367,15 +370,35 @@ enum operator_id namespace detail { + struct auto_operand {}; - struct auto_operand {}; + template + struct operand_select + { + template + struct wrapped + { + typedef Specified type; + }; + }; - template - struct define_operator; + template <> + struct operand_select + { + template + struct wrapped + { + typedef const WrappedType& type; + }; + }; + template struct define_operator; + template struct choose_op; + template struct choose_rop; + template struct choose_unary_op; } -template +template struct operators {}; template @@ -386,21 +409,19 @@ struct right_operand {}; namespace detail { + template + struct DefineConversion + { + static void * upcast_ptr(void * v) + { + return static_cast(static_cast(v)); + } - template - struct DefineConversion - { - static void * upcast_ptr(void * v) - { - return static_cast(static_cast(v)); - } - - static void * downcast_ptr(void * v) - { - return dynamic_cast(static_cast(v)); - } - }; - + static void * downcast_ptr(void * v) + { + return dynamic_cast(static_cast(v)); + } + }; } enum WithoutDowncast { without_downcast }; @@ -436,7 +457,7 @@ class ExtensionClass // define constructors template - void def(Constructor) + inline void def(Constructor) // The following incantation builds a Signature1, Signature2,... object. It // should _all_ get optimized away. { add_constructor( @@ -448,297 +469,46 @@ class ExtensionClass Signature0())))))); } - // export homogeneous operators (type of both lhs and rhs is 'operator') // usage: foo_class.def(py::operators<(py::op_add | py::op_sub), Foo>()); - template - void def(operators) - { - register_coerce(); - - if(which & py::op_add) - add_method(new typename detail::define_operator<(which & py::op_add)>:: - operator_function(), - detail::define_operator<(which & py::op_add)>::name()); - - if(which & py::op_sub) - add_method(new typename detail::define_operator<(which & py::op_sub)>:: - operator_function(), - detail::define_operator<(which & py::op_sub)>::name()); - - if(which & py::op_mul) - add_method(new typename detail::define_operator<(which & py::op_mul)>:: - operator_function(), - detail::define_operator<(which & py::op_mul)>::name()); - - if(which & py::op_div) - add_method(new typename detail::define_operator<(which & py::op_div)>:: - operator_function(), - detail::define_operator<(which & py::op_div)>::name()); - - if(which & py::op_mod) - add_method(new typename detail::define_operator<(which & py::op_mod)>:: - operator_function(), - detail::define_operator<(which & py::op_mod)>::name()); - - if(which & py::op_divmod) - add_method(new typename detail::define_operator<(which & py::op_divmod)>:: - operator_function(), - detail::define_operator<(which & py::op_divmod)>::name()); - - if(which & py::op_pow) - add_method(new typename detail::define_operator<(which & py::op_pow)>:: - operator_function(), - detail::define_operator<(which & py::op_pow)>::name()); - - if(which & py::op_lshift) - add_method(new typename detail::define_operator<(which & py::op_lshift)>:: - operator_function(), - detail::define_operator<(which & py::op_lshift)>::name()); - - if(which & py::op_rshift) - add_method(new typename detail::define_operator<(which & py::op_rshift)>:: - operator_function(), - detail::define_operator<(which & py::op_rshift)>::name()); - - if(which & py::op_and) - add_method(new typename detail::define_operator<(which & py::op_and)>:: - operator_function(), - detail::define_operator<(which & py::op_and)>::name()); - - if(which & py::op_xor) - add_method(new typename detail::define_operator<(which & py::op_xor)>:: - operator_function(), - detail::define_operator<(which & py::op_xor)>::name()); - - if(which & py::op_or) - add_method(new typename detail::define_operator<(which & py::op_or)>:: - operator_function(), - detail::define_operator<(which & py::op_or)>::name()); - - if(which & py::op_neg) - add_method(new typename detail::define_operator<(which & py::op_neg)>:: - operator_function(), - detail::define_operator<(which & py::op_neg)>::name()); - - if(which & py::op_pos) - add_method(new typename detail::define_operator<(which & py::op_pos)>:: - operator_function(), - detail::define_operator<(which & py::op_pos)>::name()); - - if(which & py::op_abs) - add_method(new typename detail::define_operator<(which & py::op_abs)>:: - operator_function(), - detail::define_operator<(which & py::op_abs)>::name()); - - if(which & py::op_invert) - add_method(new typename detail::define_operator<(which & py::op_invert)>:: - operator_function(), - detail::define_operator<(which & py::op_invert)>::name()); - - if(which & py::op_int) - add_method(new typename detail::define_operator<(which & py::op_int)>:: - operator_function(), - detail::define_operator<(which & py::op_int)>::name()); - - if(which & py::op_long) - add_method(new typename detail::define_operator<(which & py::op_long)>:: - operator_function(), - detail::define_operator<(which & py::op_long)>::name()); - - if(which & py::op_float) - add_method(new typename detail::define_operator<(which & py::op_float)>:: - operator_function(), - detail::define_operator<(which & py::op_float)>::name()); - - if(which & py::op_cmp) - add_method(new typename detail::define_operator<(which & py::op_cmp)>:: - operator_function(), - detail::define_operator<(which & py::op_cmp)>::name()); - - if(which & py::op_str) - add_method(new typename detail::define_operator<(which & py::op_str)>:: - operator_function(), - detail::define_operator<(which & py::op_str)>::name()); - - } - + // export homogeneous operators (type of both lhs and rhs is 'T const &') // usage: foo_class.def(py::operators<(py::op_add | py::op_sub)>()); - template - void def(operators) + template + inline void def(operators) { - def(operators()); - } + typedef typename detail::operand_select::template wrapped::type true_operand; + def_operators(operators()); + } // export heterogeneous operators (type of lhs: 'left', of rhs: 'right') // usage: foo_class.def(py::operators<(py::op_add | py::op_sub), Foo>(), // py::right_operand()); - template - void def(operators, right_operand) - { - register_coerce(); - - if(which & py::op_add) - add_method(new typename detail::define_operator<(which & py::op_add)>:: - operator_function(), - detail::define_operator<(which & py::op_add)>::name()); - - if(which & py::op_sub) - add_method(new typename detail::define_operator<(which & py::op_sub)>:: - operator_function(), - detail::define_operator<(which & py::op_sub)>::name()); - - if(which & py::op_mul) - add_method(new typename detail::define_operator<(which & py::op_mul)>:: - operator_function(), - detail::define_operator<(which & py::op_mul)>::name()); - - if(which & py::op_div) - add_method(new typename detail::define_operator<(which & py::op_div)>:: - operator_function(), - detail::define_operator<(which & py::op_div)>::name()); - - if(which & py::op_mod) - add_method(new typename detail::define_operator<(which & py::op_mod)>:: - operator_function(), - detail::define_operator<(which & py::op_mod)>::name()); - - if(which & py::op_divmod) - add_method(new typename detail::define_operator<(which & py::op_divmod)>:: - operator_function(), - detail::define_operator<(which & py::op_divmod)>::name()); - - if(which & py::op_pow) - add_method(new typename detail::define_operator<(which & py::op_pow)>:: - operator_function(), - detail::define_operator<(which & py::op_pow)>::name()); - - if(which & py::op_lshift) - add_method(new typename detail::define_operator<(which & py::op_lshift)>:: - operator_function(), - detail::define_operator<(which & py::op_lshift)>::name()); - - if(which & py::op_rshift) - add_method(new typename detail::define_operator<(which & py::op_rshift)>:: - operator_function(), - detail::define_operator<(which & py::op_rshift)>::name()); - - if(which & py::op_and) - add_method(new typename detail::define_operator<(which & py::op_and)>:: - operator_function(), - detail::define_operator<(which & py::op_and)>::name()); - - if(which & py::op_xor) - add_method(new typename detail::define_operator<(which & py::op_xor)>:: - operator_function(), - detail::define_operator<(which & py::op_xor)>::name()); - - if(which & py::op_or) - add_method(new typename detail::define_operator<(which & py::op_or)>:: - operator_function(), - detail::define_operator<(which & py::op_or)>::name()); - - if(which & py::op_cmp) - add_method(new typename detail::define_operator<(which & py::op_cmp)>:: - operator_function(), - detail::define_operator<(which & py::op_cmp)>::name()); - - } - + // export heterogeneous operators (type of lhs: 'T const &', of rhs: 'right') // usage: foo_class.def(py::operators<(py::op_add | py::op_sub)>(), // py::right_operand()); - template - void def(operators, right_operand r) + template + inline void def(operators, right_operand r) { - def(operators(), r); + typedef typename detail::operand_select::template wrapped::type true_left; + def_operators(operators(), r); } // export heterogeneous reverse-argument operators // (type of lhs: 'left', of rhs: 'right') // usage: foo_class.def(py::operators<(py::op_add | py::op_sub), Foo>(), // py::left_operand()); - template - void def(operators, left_operand) - { - register_coerce(); - - if(which & py::op_add) - add_method(new typename detail::define_operator<(which & py::op_add)>:: - roperator_function(), - detail::define_operator<(which & py::op_add)>::rname()); - - if(which & py::op_sub) - add_method(new typename detail::define_operator<(which & py::op_sub)>:: - roperator_function(), - detail::define_operator<(which & py::op_sub)>::rname()); - - if(which & py::op_mul) - add_method(new typename detail::define_operator<(which & py::op_mul)>:: - roperator_function(), - detail::define_operator<(which & py::op_mul)>::rname()); - - if(which & py::op_div) - add_method(new typename detail::define_operator<(which & py::op_div)>:: - roperator_function(), - detail::define_operator<(which & py::op_div)>::rname()); - - if(which & py::op_mod) - add_method(new typename detail::define_operator<(which & py::op_mod)>:: - roperator_function(), - detail::define_operator<(which & py::op_mod)>::rname()); - - if(which & py::op_divmod) - add_method(new typename detail::define_operator<(which & py::op_divmod)>:: - roperator_function(), - detail::define_operator<(which & py::op_divmod)>::rname()); - - if(which & py::op_pow) - add_method(new typename detail::define_operator<(which & py::op_pow)>:: - roperator_function(), - detail::define_operator<(which & py::op_pow)>::rname()); - - if(which & py::op_lshift) - add_method(new typename detail::define_operator<(which & py::op_lshift)>:: - roperator_function(), - detail::define_operator<(which & py::op_lshift)>::rname()); - - if(which & py::op_rshift) - add_method(new typename detail::define_operator<(which & py::op_rshift)>:: - roperator_function(), - detail::define_operator<(which & py::op_rshift)>::rname()); - - if(which & py::op_and) - add_method(new typename detail::define_operator<(which & py::op_and)>:: - roperator_function(), - detail::define_operator<(which & py::op_and)>::rname()); - - if(which & py::op_xor) - add_method(new typename detail::define_operator<(which & py::op_xor)>:: - roperator_function(), - detail::define_operator<(which & py::op_xor)>::rname()); - - if(which & py::op_or) - add_method(new typename detail::define_operator<(which & py::op_or)>:: - roperator_function(), - detail::define_operator<(which & py::op_or)>::rname()); - - if(which & py::op_cmp) - add_method(new typename detail::define_operator<(which & py::op_cmp)>:: - roperator_function(), - detail::define_operator<(which & py::op_cmp)>::rname()); - - } // export heterogeneous reverse-argument operators // (type of lhs: 'left', of rhs: 'T const &') // usage: foo_class.def(py::operators<(py::op_add | py::op_sub)>(), // py::left_operand()); - template - void def(operators, left_operand l) + template + inline void def(operators, left_operand l) { - def(operators(), l); + typedef typename detail::operand_select::template wrapped::type true_right; + def_operators(operators(), l); } // define a function that passes Python arguments and keywords @@ -748,7 +518,7 @@ class ExtensionClass // Fn must have a signatur that is compatible to // PyObject * (*)(PyObject * aTuple, PyObject * aDictionary) template - void def_raw(Fn fn, const char* name) + inline void def_raw(Fn fn, const char* name) { this->add_method(py::detail::new_raw_arguments_function(fn), name); } @@ -758,7 +528,7 @@ class ExtensionClass // appropriate self argument (as a pointer), they can be used just like // ordinary member functions -- just like Python! template - void def(Fn fn, const char* name) + inline void def(Fn fn, const char* name) { this->add_method(new_wrapped_function(fn), name); } @@ -767,7 +537,7 @@ class ExtensionClass // default_fn should be a function which provides the default implementation. // Be careful that default_fn does not in fact call fn virtually! template - void def(Fn fn, const char* name, DefaultFn default_fn) + inline void def(Fn fn, const char* name, DefaultFn default_fn) { this->add_method(py::detail::new_virtual_function(Type(), fn, default_fn), name); } @@ -775,7 +545,7 @@ class ExtensionClass // Provide a function which implements x., reading from the given // member (pm) of the T instance template - void def_getter(MemberType T::*pm, const char* name) + inline void def_getter(MemberType T::*pm, const char* name) { this->add_getter_method(new GetterFunction(pm), name); } @@ -783,14 +553,14 @@ class ExtensionClass // Provide a function which implements assignment to x., writing to // the given member (pm) of the T instance template - void def_setter(MemberType T::*pm, const char* name) + inline void def_setter(MemberType T::*pm, const char* name) { this->add_setter_method(new SetterFunction(pm), name); } // Expose the given member (pm) of the T instance as a read-only attribute template - void def_readonly(MemberType T::*pm, const char* name) + inline void def_readonly(MemberType T::*pm, const char* name) { this->add_setter_method(new ReadOnlySetattrFunction(name), name); this->def_getter(pm, name); @@ -798,7 +568,7 @@ class ExtensionClass // Expose the given member (pm) of the T instance as a read/write attribute template - void def_read_write(MemberType T::*pm, const char* name) + inline void def_read_write(MemberType T::*pm, const char* name) { this->def_getter(pm, name); this->def_setter(pm, name); @@ -846,6 +616,74 @@ class ExtensionClass void* extract_object_from_holder(InstanceHolderBase* v) const; private: // Utility functions + template + inline void def_operators(operators) + { + register_coerce(); + + detail::choose_op<(which & op_add)>::template args::add(this); + detail::choose_op<(which & op_sub)>::template args::add(this); + detail::choose_op<(which & op_mul)>::template args::add(this); + detail::choose_op<(which & op_div)>::template args::add(this); + detail::choose_op<(which & op_mod)>::template args::add(this); + detail::choose_op<(which & op_divmod)>::template args::add(this); + detail::choose_op<(which & op_pow)>::template args::add(this); + detail::choose_op<(which & op_lshift)>::template args::add(this); + detail::choose_op<(which & op_rshift)>::template args::add(this); + detail::choose_op<(which & op_and)>::template args::add(this); + detail::choose_op<(which & op_xor)>::template args::add(this); + detail::choose_op<(which & op_or)>::template args::add(this); + detail::choose_unary_op<(which & op_neg)>::template args::add(this); + detail::choose_unary_op<(which & op_pos)>::template args::add(this); + detail::choose_unary_op<(which & op_abs)>::template args::add(this); + detail::choose_unary_op<(which & op_invert)>::template args::add(this); + detail::choose_unary_op<(which & op_int)>::template args::add(this); + detail::choose_unary_op<(which & op_long)>::template args::add(this); + detail::choose_unary_op<(which & op_float)>::template args::add(this); + detail::choose_op<(which & op_cmp)>::template args::add(this); + detail::choose_unary_op<(which & op_str)>::template args::add(this); + } + + template + inline void def_operators(operators, right_operand) + { + register_coerce(); + + detail::choose_op<(which & op_add)>::template args::add(this); + detail::choose_op<(which & op_sub)>::template args::add(this); + detail::choose_op<(which & op_mul)>::template args::add(this); + detail::choose_op<(which & op_div)>::template args::add(this); + detail::choose_op<(which & op_mod)>::template args::add(this); + detail::choose_op<(which & op_divmod)>::template args::add(this); + detail::choose_op<(which & op_pow)>::template args::add(this); + detail::choose_op<(which & op_lshift)>::template args::add(this); + detail::choose_op<(which & op_rshift)>::template args::add(this); + detail::choose_op<(which & op_and)>::template args::add(this); + detail::choose_op<(which & op_xor)>::template args::add(this); + detail::choose_op<(which & op_or)>::template args::add(this); + detail::choose_op<(which & op_cmp)>::template args::add(this); + } + + template + inline void def_operators(operators, left_operand) + { + register_coerce(); + + detail::choose_rop<(which & op_add)>::template args::add(this); + detail::choose_rop<(which & op_sub)>::template args::add(this); + detail::choose_rop<(which & op_mul)>::template args::add(this); + detail::choose_rop<(which & op_div)>::template args::add(this); + detail::choose_rop<(which & op_mod)>::template args::add(this); + detail::choose_rop<(which & op_divmod)>::template args::add(this); + detail::choose_rop<(which & op_pow)>::template args::add(this); + detail::choose_rop<(which & op_lshift)>::template args::add(this); + detail::choose_rop<(which & op_rshift)>::template args::add(this); + detail::choose_rop<(which & op_and)>::template args::add(this); + detail::choose_rop<(which & op_xor)>::template args::add(this); + detail::choose_rop<(which & op_or)>::template args::add(this); + detail::choose_rop<(which & op_cmp)>::template args::add(this); + } + template void add_constructor(Signature sig) { diff --git a/gen_extclass.py b/gen_extclass.py index b5598072..3e8896c6 100644 --- a/gen_extclass.py +++ b/gen_extclass.py @@ -68,6 +68,8 @@ namespace detail { }; typedef BaseClassInfo DerivedClassInfo; + + struct add_operator_base; } class ExtensionClassBase : public Class @@ -91,6 +93,7 @@ class ExtensionClassBase : public Class virtual std::vector const& derived_classes() const = 0; protected: + friend struct detail::add_operator_base; void add_method(PyPtr method, const char* name); void add_method(Function* method, const char* name); @@ -372,15 +375,35 @@ enum operator_id namespace detail { + struct auto_operand {}; - struct auto_operand {}; + template + struct operand_select + { + template + struct wrapped + { + typedef Specified type; + }; + }; - template - struct define_operator; + template <> + struct operand_select + { + template + struct wrapped + { + typedef const WrappedType& type; + }; + }; + template struct define_operator; + template struct choose_op; + template struct choose_rop; + template struct choose_unary_op; } -template +template struct operators {}; template @@ -391,21 +414,19 @@ struct right_operand {}; namespace detail { + template + struct DefineConversion + { + static void * upcast_ptr(void * v) + { + return static_cast(static_cast(v)); + } - template - struct DefineConversion - { - static void * upcast_ptr(void * v) - { - return static_cast(static_cast(v)); - } - - static void * downcast_ptr(void * v) - { - return dynamic_cast(static_cast(v)); - } - }; - + static void * downcast_ptr(void * v) + { + return dynamic_cast(static_cast(v)); + } + }; } enum WithoutDowncast { without_downcast }; @@ -443,7 +464,7 @@ class ExtensionClass """ % args + gen_function( """ template <%(class A%n%:, %)> - void def(Constructor<%(A%n%:, %)>) + inline void def(Constructor<%(A%n%:, %)>) // The following incantation builds a Signature1, Signature2,... object. It // should _all_ get optimized away. { add_constructor( @@ -456,294 +477,44 @@ class ExtensionClass // export homogeneous operators (type of both lhs and rhs is 'operator') // usage: foo_class.def(py::operators<(py::op_add | py::op_sub), Foo>()); - template - void def(operators) - { - register_coerce(); - - if(which & py::op_add) - add_method(new typename detail::define_operator<(which & py::op_add)>:: - operator_function(), - detail::define_operator<(which & py::op_add)>::name()); - - if(which & py::op_sub) - add_method(new typename detail::define_operator<(which & py::op_sub)>:: - operator_function(), - detail::define_operator<(which & py::op_sub)>::name()); - - if(which & py::op_mul) - add_method(new typename detail::define_operator<(which & py::op_mul)>:: - operator_function(), - detail::define_operator<(which & py::op_mul)>::name()); - - if(which & py::op_div) - add_method(new typename detail::define_operator<(which & py::op_div)>:: - operator_function(), - detail::define_operator<(which & py::op_div)>::name()); - - if(which & py::op_mod) - add_method(new typename detail::define_operator<(which & py::op_mod)>:: - operator_function(), - detail::define_operator<(which & py::op_mod)>::name()); - - if(which & py::op_divmod) - add_method(new typename detail::define_operator<(which & py::op_divmod)>:: - operator_function(), - detail::define_operator<(which & py::op_divmod)>::name()); - - if(which & py::op_pow) - add_method(new typename detail::define_operator<(which & py::op_pow)>:: - operator_function(), - detail::define_operator<(which & py::op_pow)>::name()); - - if(which & py::op_lshift) - add_method(new typename detail::define_operator<(which & py::op_lshift)>:: - operator_function(), - detail::define_operator<(which & py::op_lshift)>::name()); - - if(which & py::op_rshift) - add_method(new typename detail::define_operator<(which & py::op_rshift)>:: - operator_function(), - detail::define_operator<(which & py::op_rshift)>::name()); - - if(which & py::op_and) - add_method(new typename detail::define_operator<(which & py::op_and)>:: - operator_function(), - detail::define_operator<(which & py::op_and)>::name()); - - if(which & py::op_xor) - add_method(new typename detail::define_operator<(which & py::op_xor)>:: - operator_function(), - detail::define_operator<(which & py::op_xor)>::name()); - - if(which & py::op_or) - add_method(new typename detail::define_operator<(which & py::op_or)>:: - operator_function(), - detail::define_operator<(which & py::op_or)>::name()); - - if(which & py::op_neg) - add_method(new typename detail::define_operator<(which & py::op_neg)>:: - operator_function(), - detail::define_operator<(which & py::op_neg)>::name()); - - if(which & py::op_pos) - add_method(new typename detail::define_operator<(which & py::op_pos)>:: - operator_function(), - detail::define_operator<(which & py::op_pos)>::name()); - - if(which & py::op_abs) - add_method(new typename detail::define_operator<(which & py::op_abs)>:: - operator_function(), - detail::define_operator<(which & py::op_abs)>::name()); - - if(which & py::op_invert) - add_method(new typename detail::define_operator<(which & py::op_invert)>:: - operator_function(), - detail::define_operator<(which & py::op_invert)>::name()); - - if(which & py::op_int) - add_method(new typename detail::define_operator<(which & py::op_int)>:: - operator_function(), - detail::define_operator<(which & py::op_int)>::name()); - - if(which & py::op_long) - add_method(new typename detail::define_operator<(which & py::op_long)>:: - operator_function(), - detail::define_operator<(which & py::op_long)>::name()); - - if(which & py::op_float) - add_method(new typename detail::define_operator<(which & py::op_float)>:: - operator_function(), - detail::define_operator<(which & py::op_float)>::name()); - - if(which & py::op_cmp) - add_method(new typename detail::define_operator<(which & py::op_cmp)>:: - operator_function(), - detail::define_operator<(which & py::op_cmp)>::name()); - - if(which & py::op_str) - add_method(new typename detail::define_operator<(which & py::op_str)>:: - operator_function(), - detail::define_operator<(which & py::op_str)>::name()); - - } - + // export homogeneous operators (type of both lhs and rhs is 'T const &') // usage: foo_class.def(py::operators<(py::op_add | py::op_sub)>()); - template - void def(operators) + template + inline void def(operators) { - def(operators()); - } + typedef typename detail::operand_select::template wrapped::type true_operand; + def_operators(operators()); + } // export heterogeneous operators (type of lhs: 'left', of rhs: 'right') // usage: foo_class.def(py::operators<(py::op_add | py::op_sub), Foo>(), // py::right_operand()); - template - void def(operators, right_operand) - { - register_coerce(); - - if(which & py::op_add) - add_method(new typename detail::define_operator<(which & py::op_add)>:: - operator_function(), - detail::define_operator<(which & py::op_add)>::name()); - - if(which & py::op_sub) - add_method(new typename detail::define_operator<(which & py::op_sub)>:: - operator_function(), - detail::define_operator<(which & py::op_sub)>::name()); - - if(which & py::op_mul) - add_method(new typename detail::define_operator<(which & py::op_mul)>:: - operator_function(), - detail::define_operator<(which & py::op_mul)>::name()); - - if(which & py::op_div) - add_method(new typename detail::define_operator<(which & py::op_div)>:: - operator_function(), - detail::define_operator<(which & py::op_div)>::name()); - - if(which & py::op_mod) - add_method(new typename detail::define_operator<(which & py::op_mod)>:: - operator_function(), - detail::define_operator<(which & py::op_mod)>::name()); - - if(which & py::op_divmod) - add_method(new typename detail::define_operator<(which & py::op_divmod)>:: - operator_function(), - detail::define_operator<(which & py::op_divmod)>::name()); - - if(which & py::op_pow) - add_method(new typename detail::define_operator<(which & py::op_pow)>:: - operator_function(), - detail::define_operator<(which & py::op_pow)>::name()); - - if(which & py::op_lshift) - add_method(new typename detail::define_operator<(which & py::op_lshift)>:: - operator_function(), - detail::define_operator<(which & py::op_lshift)>::name()); - - if(which & py::op_rshift) - add_method(new typename detail::define_operator<(which & py::op_rshift)>:: - operator_function(), - detail::define_operator<(which & py::op_rshift)>::name()); - - if(which & py::op_and) - add_method(new typename detail::define_operator<(which & py::op_and)>:: - operator_function(), - detail::define_operator<(which & py::op_and)>::name()); - - if(which & py::op_xor) - add_method(new typename detail::define_operator<(which & py::op_xor)>:: - operator_function(), - detail::define_operator<(which & py::op_xor)>::name()); - - if(which & py::op_or) - add_method(new typename detail::define_operator<(which & py::op_or)>:: - operator_function(), - detail::define_operator<(which & py::op_or)>::name()); - - if(which & py::op_cmp) - add_method(new typename detail::define_operator<(which & py::op_cmp)>:: - operator_function(), - detail::define_operator<(which & py::op_cmp)>::name()); - - } - + // export heterogeneous operators (type of lhs: 'T const &', of rhs: 'right') // usage: foo_class.def(py::operators<(py::op_add | py::op_sub)>(), // py::right_operand()); - template - void def(operators, right_operand r) + template + inline void def(operators, right_operand r) { - def(operators(), r); + typedef typename detail::operand_select::template wrapped::type true_left; + def_operators(operators(), r); } // export heterogeneous reverse-argument operators // (type of lhs: 'left', of rhs: 'right') // usage: foo_class.def(py::operators<(py::op_add | py::op_sub), Foo>(), // py::left_operand()); - template - void def(operators, left_operand) - { - register_coerce(); - - if(which & py::op_add) - add_method(new typename detail::define_operator<(which & py::op_add)>:: - roperator_function(), - detail::define_operator<(which & py::op_add)>::rname()); - - if(which & py::op_sub) - add_method(new typename detail::define_operator<(which & py::op_sub)>:: - roperator_function(), - detail::define_operator<(which & py::op_sub)>::rname()); - - if(which & py::op_mul) - add_method(new typename detail::define_operator<(which & py::op_mul)>:: - roperator_function(), - detail::define_operator<(which & py::op_mul)>::rname()); - - if(which & py::op_div) - add_method(new typename detail::define_operator<(which & py::op_div)>:: - roperator_function(), - detail::define_operator<(which & py::op_div)>::rname()); - - if(which & py::op_mod) - add_method(new typename detail::define_operator<(which & py::op_mod)>:: - roperator_function(), - detail::define_operator<(which & py::op_mod)>::rname()); - - if(which & py::op_divmod) - add_method(new typename detail::define_operator<(which & py::op_divmod)>:: - roperator_function(), - detail::define_operator<(which & py::op_divmod)>::rname()); - - if(which & py::op_pow) - add_method(new typename detail::define_operator<(which & py::op_pow)>:: - roperator_function(), - detail::define_operator<(which & py::op_pow)>::rname()); - - if(which & py::op_lshift) - add_method(new typename detail::define_operator<(which & py::op_lshift)>:: - roperator_function(), - detail::define_operator<(which & py::op_lshift)>::rname()); - - if(which & py::op_rshift) - add_method(new typename detail::define_operator<(which & py::op_rshift)>:: - roperator_function(), - detail::define_operator<(which & py::op_rshift)>::rname()); - - if(which & py::op_and) - add_method(new typename detail::define_operator<(which & py::op_and)>:: - roperator_function(), - detail::define_operator<(which & py::op_and)>::rname()); - - if(which & py::op_xor) - add_method(new typename detail::define_operator<(which & py::op_xor)>:: - roperator_function(), - detail::define_operator<(which & py::op_xor)>::rname()); - - if(which & py::op_or) - add_method(new typename detail::define_operator<(which & py::op_or)>:: - roperator_function(), - detail::define_operator<(which & py::op_or)>::rname()); - - if(which & py::op_cmp) - add_method(new typename detail::define_operator<(which & py::op_cmp)>:: - roperator_function(), - detail::define_operator<(which & py::op_cmp)>::rname()); - - } // export heterogeneous reverse-argument operators // (type of lhs: 'left', of rhs: 'T const &') // usage: foo_class.def(py::operators<(py::op_add | py::op_sub)>(), // py::left_operand()); - template - void def(operators, left_operand l) + template + inline void def(operators, left_operand l) { - def(operators(), l); + typedef typename detail::operand_select::template wrapped::type true_right; + def_operators(operators(), l); } // define a function that passes Python arguments and keywords @@ -753,7 +524,7 @@ class ExtensionClass // Fn must have a signatur that is compatible to // PyObject * (*)(PyObject * aTuple, PyObject * aDictionary) template - void def_raw(Fn fn, const char* name) + inline void def_raw(Fn fn, const char* name) { this->add_method(py::detail::new_raw_arguments_function(fn), name); } @@ -763,7 +534,7 @@ class ExtensionClass // appropriate self argument (as a pointer), they can be used just like // ordinary member functions -- just like Python! template - void def(Fn fn, const char* name) + inline void def(Fn fn, const char* name) { this->add_method(new_wrapped_function(fn), name); } @@ -772,7 +543,7 @@ class ExtensionClass // default_fn should be a function which provides the default implementation. // Be careful that default_fn does not in fact call fn virtually! template - void def(Fn fn, const char* name, DefaultFn default_fn) + inline void def(Fn fn, const char* name, DefaultFn default_fn) { this->add_method(py::detail::new_virtual_function(Type(), fn, default_fn), name); } @@ -780,7 +551,7 @@ class ExtensionClass // Provide a function which implements x., reading from the given // member (pm) of the T instance template - void def_getter(MemberType T::*pm, const char* name) + inline void def_getter(MemberType T::*pm, const char* name) { this->add_getter_method(new GetterFunction(pm), name); } @@ -788,14 +559,14 @@ class ExtensionClass // Provide a function which implements assignment to x., writing to // the given member (pm) of the T instance template - void def_setter(MemberType T::*pm, const char* name) + inline void def_setter(MemberType T::*pm, const char* name) { this->add_setter_method(new SetterFunction(pm), name); } // Expose the given member (pm) of the T instance as a read-only attribute template - void def_readonly(MemberType T::*pm, const char* name) + inline void def_readonly(MemberType T::*pm, const char* name) { this->add_setter_method(new ReadOnlySetattrFunction(name), name); this->def_getter(pm, name); @@ -803,7 +574,7 @@ class ExtensionClass // Expose the given member (pm) of the T instance as a read/write attribute template - void def_read_write(MemberType T::*pm, const char* name) + inline void def_read_write(MemberType T::*pm, const char* name) { this->def_getter(pm, name); this->def_setter(pm, name); @@ -851,6 +622,74 @@ class ExtensionClass void* extract_object_from_holder(InstanceHolderBase* v) const; private: // Utility functions + template + inline void def_operators(operators) + { + register_coerce(); + + detail::choose_op<(which & op_add)>::template args::add(this); + detail::choose_op<(which & op_sub)>::template args::add(this); + detail::choose_op<(which & op_mul)>::template args::add(this); + detail::choose_op<(which & op_div)>::template args::add(this); + detail::choose_op<(which & op_mod)>::template args::add(this); + detail::choose_op<(which & op_divmod)>::template args::add(this); + detail::choose_op<(which & op_pow)>::template args::add(this); + detail::choose_op<(which & op_lshift)>::template args::add(this); + detail::choose_op<(which & op_rshift)>::template args::add(this); + detail::choose_op<(which & op_and)>::template args::add(this); + detail::choose_op<(which & op_xor)>::template args::add(this); + detail::choose_op<(which & op_or)>::template args::add(this); + detail::choose_unary_op<(which & op_neg)>::template args::add(this); + detail::choose_unary_op<(which & op_pos)>::template args::add(this); + detail::choose_unary_op<(which & op_abs)>::template args::add(this); + detail::choose_unary_op<(which & op_invert)>::template args::add(this); + detail::choose_unary_op<(which & op_int)>::template args::add(this); + detail::choose_unary_op<(which & op_long)>::template args::add(this); + detail::choose_unary_op<(which & op_float)>::template args::add(this); + detail::choose_op<(which & op_cmp)>::template args::add(this); + detail::choose_unary_op<(which & op_str)>::template args::add(this); + } + + template + inline void def_operators(operators, right_operand) + { + register_coerce(); + + detail::choose_op<(which & op_add)>::template args::add(this); + detail::choose_op<(which & op_sub)>::template args::add(this); + detail::choose_op<(which & op_mul)>::template args::add(this); + detail::choose_op<(which & op_div)>::template args::add(this); + detail::choose_op<(which & op_mod)>::template args::add(this); + detail::choose_op<(which & op_divmod)>::template args::add(this); + detail::choose_op<(which & op_pow)>::template args::add(this); + detail::choose_op<(which & op_lshift)>::template args::add(this); + detail::choose_op<(which & op_rshift)>::template args::add(this); + detail::choose_op<(which & op_and)>::template args::add(this); + detail::choose_op<(which & op_xor)>::template args::add(this); + detail::choose_op<(which & op_or)>::template args::add(this); + detail::choose_op<(which & op_cmp)>::template args::add(this); + } + + template + inline void def_operators(operators, left_operand) + { + register_coerce(); + + detail::choose_rop<(which & op_add)>::template args::add(this); + detail::choose_rop<(which & op_sub)>::template args::add(this); + detail::choose_rop<(which & op_mul)>::template args::add(this); + detail::choose_rop<(which & op_div)>::template args::add(this); + detail::choose_rop<(which & op_mod)>::template args::add(this); + detail::choose_rop<(which & op_divmod)>::template args::add(this); + detail::choose_rop<(which & op_pow)>::template args::add(this); + detail::choose_rop<(which & op_lshift)>::template args::add(this); + detail::choose_rop<(which & op_rshift)>::template args::add(this); + detail::choose_rop<(which & op_and)>::template args::add(this); + detail::choose_rop<(which & op_xor)>::template args::add(this); + detail::choose_rop<(which & op_or)>::template args::add(this); + detail::choose_rop<(which & op_cmp)>::template args::add(this); + } + template void add_constructor(Signature sig) {