Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

boost-python select between overloaded methods

Tags:

Assume exist some class Foo with two overloaded methods:

class Foo
{
  ...
   void m1(A& a);
   void m1(B& b);

I need expose one of these methods over boost-python:

boost::python::class_<Foo>("Foo")
    .def("m1", &Foo::m1)

How should I specify that signature of m1(A&a) should be used over m1(B&b)

like image 625
Dewfy Avatar asked Sep 28 '11 01:09

Dewfy


4 Answers

Just for completion, it is also possible to have both of them exposed at python side:

void (Foo::*m1_a)(A&) = &Foo::m1;
void (Foo::*m1_b)(B&) = &Foo::m1;

boost::python::class_<Foo>("Foo")
    .def("m1", m1_a)
    .def("m1", m1_b)
like image 130
Werner Avatar answered Sep 24 '22 02:09

Werner


void (Foo::*m1)(A&) = &Foo::m1;
boost::python::class_<Foo>("Foo")
    .def("m1", m1)
like image 36
Luc Danton Avatar answered Sep 23 '22 02:09

Luc Danton


While the other answers are correct there is no need to do any shenanigans with temporary variables or static_cast.

The def function prototypes look like this:

template <class Fn>
class_& def(char const* name, Fn fn);
template <class Fn, class A1>
class_& def(char const* name, Fn fn, A1 const&);
template <class Fn, class A1, class A2>
class_& def(char const* name, Fn fn, A1 const&, A2 const&);
template <class Fn, class A1, class A2, class A3>
class_& def(char const* name, Fn fn, A1 const&, A2 const&, A3 const&);

As you can see the first template parameter (Fn) is the type of the function pointer you want to wrap. Usually, all the template parameters are deduced by the compiler for you. However, if there is an ambiguity you need to help the compiler. If the function pointer is ambiguous due to an overloaded function you have to provide the proper type explicitly. In your case:

boost::python::class_<Foo>("Foo")
    .def<void (Foo::*)(A&)>("m1", &Foo::m1)
    .def<void (Foo::*)(B&)>("m1", &Foo::m1)
    ;

Simple, isn't it? No need to cast or capture outside. The same thing is valid for creating free standing function at the module level, i.e. using boost::python::def.

like image 22
vaclav.blazek Avatar answered Sep 26 '22 02:09

vaclav.blazek


You can use static_cast to specify which signature to use. With this method, you do not need to create a named function pointer while also keeping your overload resolution within the context of a single line.

boost::python::class_<Foo>("Foo")
    .def("m1", static_cast<void (Foo::*)(A&)>(&Foo::m1))
    .def("m1", static_cast<void (Foo::*)(B&)>(&Foo::m1))
like image 24
noddy Avatar answered Sep 26 '22 02:09

noddy