pybind11 icon indicating copy to clipboard operation
pybind11 copied to clipboard

[BUG]: expose lifted private/protected methods from non-exposed base class cause compile errors on MSVC

Open YunchengLiu opened this issue 2 years ago • 1 comments

Required prerequisites

  • [X] Make sure you've read the documentation. Your issue may be addressed there.
  • [X] Search the issue tracker and Discussions to verify that this hasn't already been reported. +1 or comment there if it has.
  • [X] Consider asking first in the Gitter chat room or in a Discussion.

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

2.10.3

Problem description

In the MSVC17.5.5 version (Windows10 19045.2965), when compiling with C++20, the derived class cannot export the method that is privately inherited in multiple inheritance but promoted to public, resulting in a compilation error.

The error message is as follows: error C2247: 'Mixined' is not accessible because 'Derived' inherits from 'Mixined' using 'private'.

But I don't want to expose any information of the Mixin class in Python, I just want to export the method

Using a lambda method wrapper for every method that is promoted to public can solve this problem, but in my project, which uses this kind of private inheritance a lot to add functionality, creating a lambda for each one seems a bit too annoying.

#1124 seems to be the same problem, but so far only lambda seems to be the solution?

Can anyone give me some help? I would be grateful!

Reproducible example code

#include <iostream>
#include <pybind11/pybind11.h>

struct Base {

    void base_fun() {
        std::cout << "base function.\n";
    }

};

struct Mixined {
    void mixin_fun() {
        std::cout << "mixined function.\n";
    }
};

struct Derived : public Base, private Mixined /*just add functions*/{

    using Mixined::mixin_fun; // lifted to public

};

namespace py = pybind11;

PYBIND11_MODULE(test_module, m) {

    py::class_<Base>(m, "Base")
    .def(::py::init<>())
        .def("base_fun", &Base::base_fun);

    py::class_<Derived, Base>(m, "Derived")
        .def(::py::init<>())
        .def("mixin_fun", &Derived::mixin_fun); // get compiler errors for can not cast to mixined class
        // .def("mixin_fun",[](Derived& d) {d.mixin_fun();});// use lambda is ok, but i have too many mixined methods

}

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

Not a regression

YunchengLiu avatar May 18 '23 06:05 YunchengLiu


#include <iostream>
#include <pybind11/pybind11.h>

struct Base {
    void base_fun() {
        std::cout << "base function.\n";
    }
};

struct Mixined {
    void mixin_fun() {
        std::cout << "mixined function.\n";
    }
};

struct Derived : public Base, private Mixined {
    using Mixined::mixin_fun;  // lifted to public

    // Explicitly expose the mixin_fun method to Python
    void exposed_mixin_fun() {
        mixin_fun();  // Call the mixin_fun method from Mixined
    }
};

namespace py = pybind11;

PYBIND11_MODULE(test_module, m) {
    py::class_<Base>(m, "Base")
        .def(py::init<>())
        .def("base_fun", &Base::base_fun);

    py::class_<Derived, Base>(m, "Derived")
        .def(py::init<>())
        .def("exposed_mixin_fun", &Derived::exposed_mixin_fun);  // Bind the exposed method
}

ljluestc avatar Nov 23 '24 22:11 ljluestc