diff --git a/init_function.h b/init_function.h index c22c627f..ac6d0e8d 100644 --- a/init_function.h +++ b/init_function.h @@ -18,6 +18,82 @@ namespace py { +namespace detail { + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + // parameter_traits - so far, this is a way to pass a const T& when we can be + // sure T is not a reference type, and a raw T otherwise. This should be + // rolled into boost::call_traits. + template + struct const_ref_selector + { + template + struct const_ref + { + typedef const T& type; + }; + }; + + template <> + struct const_ref_selector + { + template + struct const_ref + { + typedef T type; + }; + }; + +# ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable: 4181) +# endif // BOOST_MSVC + template + struct parameter_traits + { + private: + typedef const_ref_selector::value> selector; + public: + typedef typename selector::const_ref::type const_reference; + }; +# ifdef BOOST_MSVC +# pragma warning(pop) +# endif // BOOST_MSVC + +#else + template + struct parameter_traits + { + typedef const T& const_reference; + }; + + template + struct parameter_traits + { + typedef T& const_reference; + }; +#endif + + template <> + struct parameter_traits + { + typedef void const_reference; + }; + + template + class reference_parameter + { + typedef typename parameter_traits::const_reference const_reference; + public: + reference_parameter(const_reference value) + : value(value) {} + operator const_reference() { return value; } + private: + const_reference value; + }; +} + class ExtensionInstance; class InstanceHolderBase; @@ -32,28 +108,49 @@ template struct Init template struct InitFunction { - static Init* create(Signature0) - { return new Init0; } + static Init* create(Signature0) { + return new Init0; + } template - static Init* create(Signature1) - { return new Init1; } + static Init* create(Signature1) { + return new Init1::const_reference>; + } template - static Init* create(Signature2) - { return new Init2; } + static Init* create(Signature2) { + return new Init2::const_reference, + detail::parameter_traits::const_reference>; + } template - static Init* create(Signature3) - { return new Init3; } + static Init* create(Signature3) { + return new Init3::const_reference, + detail::parameter_traits::const_reference, + detail::parameter_traits::const_reference>; + } template - static Init* create(Signature4) - { return new Init4; } + static Init* create(Signature4) { + return new Init4::const_reference, + detail::parameter_traits::const_reference, + detail::parameter_traits::const_reference, + detail::parameter_traits::const_reference>; + } template - static Init* create(Signature5) - { return new Init5; } + static Init* create(Signature5) { + return new Init5::const_reference, + detail::parameter_traits::const_reference, + detail::parameter_traits::const_reference, + detail::parameter_traits::const_reference, + detail::parameter_traits::const_reference>; + } }; class Init : public Function @@ -76,7 +173,7 @@ struct Init0 : Init ); } const char* description() const - { return typeid(void (*)()).name(); } + { return typeid(void (*)(T&)).name(); } }; template @@ -88,11 +185,11 @@ struct Init1 : Init if (!PyArg_ParseTuple(args, const_cast("O"), &a1)) throw ArgumentError(); return new T(self, - from_python(a1, Type()) + py::detail::reference_parameter(from_python(a1, Type())) ); } const char* description() const - { return typeid(void (*)(A1)).name(); } + { return typeid(void (*)(T&, A1)).name(); } }; template @@ -105,12 +202,12 @@ struct Init2 : Init if (!PyArg_ParseTuple(args, const_cast("OO"), &a1, &a2)) throw ArgumentError(); return new T(self, - from_python(a1, Type()), - from_python(a2, Type()) + py::detail::reference_parameter(from_python(a1, Type())), + py::detail::reference_parameter(from_python(a2, Type())) ); } const char* description() const - { return typeid(void (*)(A1, A2)).name(); } + { return typeid(void (*)(T&, A1, A2)).name(); } }; template @@ -124,13 +221,13 @@ struct Init3 : Init if (!PyArg_ParseTuple(args, const_cast("OOO"), &a1, &a2, &a3)) throw ArgumentError(); return new T(self, - from_python(a1, Type()), - from_python(a2, Type()), - from_python(a3, Type()) + py::detail::reference_parameter(from_python(a1, Type())), + py::detail::reference_parameter(from_python(a2, Type())), + py::detail::reference_parameter(from_python(a3, Type())) ); } const char* description() const - { return typeid(void (*)(A1, A2, A3)).name(); } + { return typeid(void (*)(T&, A1, A2, A3)).name(); } }; template @@ -145,14 +242,14 @@ struct Init4 : Init if (!PyArg_ParseTuple(args, const_cast("OOOO"), &a1, &a2, &a3, &a4)) throw ArgumentError(); return new T(self, - from_python(a1, Type()), - from_python(a2, Type()), - from_python(a3, Type()), - from_python(a4, Type()) + py::detail::reference_parameter(from_python(a1, Type())), + py::detail::reference_parameter(from_python(a2, Type())), + py::detail::reference_parameter(from_python(a3, Type())), + py::detail::reference_parameter(from_python(a4, Type())) ); } const char* description() const - { return typeid(void (*)(A1, A2, A3, A4)).name(); } + { return typeid(void (*)(T&, A1, A2, A3, A4)).name(); } }; template @@ -168,17 +265,18 @@ struct Init5 : Init if (!PyArg_ParseTuple(args, const_cast("OOOOO"), &a1, &a2, &a3, &a4, &a5)) throw ArgumentError(); return new T(self, - from_python(a1, Type()), - from_python(a2, Type()), - from_python(a3, Type()), - from_python(a4, Type()), - from_python(a5, Type()) + py::detail::reference_parameter(from_python(a1, Type())), + py::detail::reference_parameter(from_python(a2, Type())), + py::detail::reference_parameter(from_python(a3, Type())), + py::detail::reference_parameter(from_python(a4, Type())), + py::detail::reference_parameter(from_python(a5, Type())) ); } const char* description() const - { return typeid(void (*)(A1, A2, A3, A4, A5)).name(); } + { return typeid(void (*)(T&, A1, A2, A3, A4, A5)).name(); } }; } #endif // INIT_FUNCTION_DWA052000_H_ +