Skip to content

[BUG]: Overloaded (pure) virtual function not inherited #4996

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
2 of 3 tasks
MatthijsBurgh opened this issue Jan 2, 2024 · 0 comments
Open
2 of 3 tasks

[BUG]: Overloaded (pure) virtual function not inherited #4996

MatthijsBurgh opened this issue Jan 2, 2024 · 0 comments
Labels
triage New bug, unverified

Comments

@MatthijsBurgh
Copy link
Contributor

MatthijsBurgh commented Jan 2, 2024

Required prerequisites

What version (or hash if on master) of pybind11 are you using?

2.11.1

Problem description

Similar to #2351. Though I have overloaded functions defined in child classes, instead of the base class.

I have a base class with multiple child classes. The base class does has a (pure) virtual function (with 2 doubles as arguments). The child classes overload this function with more doubles as arguments, the amount depends on the child class.
The issue is that the (pure) virtual function func is not inherited into the child classes. Only the overloaded version of the function is available in the child classes. The original function (2 doubles as arguments) is only available in the child classes when defining the function for each child. It doesn't matter whether I reference the base class or the child class in the definition. (See the commented lines in the child classes.) It also doesn't matter whether I use the py::overload_cast in the base class or not. (See commented line in the base class.)

The __copy__ and __deepcopy__ functions are inherited from the base class to the child classes without any issue.

The bug: The overloaded (pure) virtual function is not inherited into the child classes unless defined in the child classes.

edit: I think the issue is not related to the virtual functions, but the overloading of base functions in the child classes. As a fully implemented non-virtual function (func2) shows the same issue of not being inherited. Again only the overloaded version of the function is available.

Reproducible example code

mylib.hpp

class Base {
 public:
  Base()
  virtual ~Base() = default;

  virtual void func(double, double) = 0;
  void func2(double);
};

class Child1: public Base {
 public:
  Child1();
  void func(double, double, double, double);
  void func2(double, double);
};

class Child2: public Base {
 public:
  Child2();
  void func(double, double, double, double, double, double);
  void func2(double, double, double);
};

mylib_pybind.cpp

template <class BaseType = Base>
class PyBase : public BaseType
{
  using BaseType::BaseType;  // Inherit constructors
  BaseType* clone() const override
  {
    PYBIND11_OVERRIDE_PURE_NAME(BaseType*, BaseType, "__copy__", clone);
  };
  void func(double arg1, double arg2) override
  {
    PYBIND11_OVERRIDE_PURE_NAME(void, BaseType, "func", func, arg1, arg2);
  };
};

template <class ChildType>
class PyChild : public PyBase<ChildType>
{
public:
  using PyBase<ChildType>::PyBase;  // Inherit constructors
  ChildType* clone() const override
  {
    PYBIND11_OVERRIDE_NAME(ChildType*, ChildType, "__copy__", clone);
  }
  void func(double arg1, double arg2) override
  {
    PYBIND11_OVERRIDE_NAME(void, ChildType, "func", func, arg1, arg2);
  };
};

PYBIND11_MODULE(mypkg, m) {
  py::class_<Base, PyBase>(m, "Base")
      .def(py::init<>())
      .def("__copy__", &Base::clone)
      .def("__deepcopy__", [](const Base& self, py::dict&) { return self.clone(); }, py::arg("memo"))
      .def("func", &Base::func)
//      .def("func", py::overload_cast<double, double>(&Base::func))
      .def("func2", &Base::func2);

    py::class_<Child1, Base, PyChild<Child1>>(m, "Child1")
      .def(py::init<>())
//      .def("func", py::overload_cast<double, double>(&Child1::func))
//      .def("func", py::overload_cast<double, double>(&Base::func))
      .def("func", py::overload_cast<double, double, double, double>(&Child1::func))
//      .def("func2", py::overload_cast<double>(&Child1::func2))
//      .def("func2", py::overload_cast<double>(&Base::func2))
      .def("func2", py::overload_cast<double, double>(&Child1::func2));

    py::class_<Child2, Base, PyChild<Child2>>(m, "Child2")
      .def(py::init<>())
//      .def("func", py::overload_cast<double, double>(&Child2::func))
//      .def("func", py::overload_cast<double, double>(&Base::func))
      .def("func", py::overload_cast<double, double, double, double, double, double>(&Child2::func))
//      .def("func2", py::overload_cast<double>(&Child2::func2))
//      .def("func2", py::overload_cast<double>(&Base::func2))
      .def("func2", py::overload_cast<double, double, double>(&Child2::func2));

}

Is this a regression? Put the last known working version here if it is.

Not a regression

@MatthijsBurgh MatthijsBurgh added the triage New bug, unverified label Jan 2, 2024
MatthijsBurgh added a commit to MatthijsBurgh/geometric_shapes_py that referenced this issue Jan 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
triage New bug, unverified
Projects
None yet
Development

No branches or pull requests

1 participant