pybind11 will downcast is stead of using overload resolution resulting in unexpected behavior
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 18k
- Forks
- 2.3k
- Avg merge
- 5d 17h
- Merged PRs (30d)
- 10
Description
Coming from C++ I expected overload resolution to be maintained through pybind11. This is not the case. I dont know if it is not possible to implement in pybind11. If that is the case, It could be (more) clearly stated in the documentation, and a feature request would be that the overload function priority could be explicitly given.
An example:
#include <pybind11/pybind11.h>
namespace py = pybind11;
class A
{
public:
A(int v_) : v{ v_ } {}
int val() const { return v; }
void val(int i) { v = i; }
private:
int v = 0;
};
class B: public A
{
public:
B(int v) : A{ v-1 } {}
int val() const { return A::val() + 1; }
void val(int i) { A::val(i-1); }
};
template <typename T>
T& f(T& t, int i) { t.val(i); return t; }
PYBIND11_MODULE(pyreftest, m) {
py::class_<A>(m, "A")
.def(py::init<int>())
.def("__repr__", [](const A&a) {return "<A(" + std::to_string(a.val()) + ")>"; });
py::class_<B,A>(m, "B")
.def(py::init<int>())
.def("__repr__", [](const B&b) {return "<B(" + std::to_string(b.val()) + ")>"; });
m.def("f", &f<A>);
m.def("f", &f<B>);
}
Result:
In [1]: from pyreftest import *
In [2]: b = B(3)
In [3]: b
Out[3]: <B(3)>
In [4]: f(b,4)
Out[4]: <A(4)>
In [5]: b
Out[5]: <B(5)>
Expected result:
In [1]: from pyreftest import *
In [2]: b = B(3)
In [3]: b
Out[3]: <B(3)>
In [4]: f(b,4)
Out[4]: <B(4)>
In [5]: b
Out[5]: <B(4)>
I realize that a workaround is to swap the two last lines of code i.e:
m.def("f", &f<B>);
m.def("f", &f<A>);
but I think this is more a workaround than a fix.
Otherwise awesome project
Best regards Troels
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the supplied pyreftest reproducer and the two m.def("f", ...) registrations, then inspect how overload resolution handles A and B arguments. Done would be a confirmed behavior with either an implementation and regression test or clear documentation of the limitation and the registration-order workaround.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, python
- Domain
- api, backend-api-design
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 30/100