@@ -174,6 +174,25 @@ struct DispatchIssue : Base {
174174 }
175175};
176176
177+ // An abstract adder class that uses visitor pattern to add two data
178+ // objects and send the result to the visitor functor
179+ struct AdderBase {
180+ struct Data {};
181+ using DataVisitor = std::function<void (const Data&)>;
182+
183+ virtual void operator ()(const Data& first, const Data& second, const DataVisitor& visitor) const = 0;
184+ virtual ~AdderBase () = default ;
185+ AdderBase () = default ;
186+ AdderBase (const AdderBase&) = delete ;
187+ };
188+
189+ struct Adder : AdderBase {
190+ void operator ()(const Data& first, const Data& second, const DataVisitor& visitor) const override {
191+ PYBIND11_OVERRIDE_PURE_NAME (void , AdderBase, " __call__" , operator (), first, second, visitor);
192+ }
193+ };
194+
195+
177196static void test_gil () {
178197 {
179198 py::gil_scoped_acquire lock;
@@ -295,6 +314,27 @@ TEST_SUBMODULE(virtual_functions, m) {
295314
296315 m.def (" dispatch_issue_go" , [](const Base * b) { return b->dispatch (); });
297316
317+ // test_recursive_dispatch_issue
318+ // #3357: Recursive dispatch fails to find python function override
319+ pybind11::class_<AdderBase, Adder>(m, " Adder" )
320+ .def (pybind11::init<>())
321+ .def (" __call__" , &AdderBase::operator ());
322+
323+ pybind11::class_<AdderBase::Data>(m, " Data" )
324+ .def (pybind11::init<>());
325+
326+ m.def (" add2" , [](const AdderBase::Data& first, const AdderBase::Data& second,
327+ const AdderBase& adder, const AdderBase::DataVisitor& visitor) {
328+ adder (first, second, visitor);
329+ });
330+
331+ m.def (" add3" , [](const AdderBase::Data& first, const AdderBase::Data& second, const AdderBase::Data& third,
332+ const AdderBase& adder, const AdderBase::DataVisitor& visitor) {
333+ adder (first, second, [&] (const AdderBase::Data& first_plus_second) {
334+ adder (first_plus_second, third, visitor);
335+ });
336+ });
337+
298338 // test_override_ref
299339 // #392/397: overriding reference-returning functions
300340 class OverrideTest {
0 commit comments