• Jason Rhinelander's avatar
    Override deduced Base class when defining Derived methods · 23bf8945
    Jason Rhinelander authored
    
    
    When defining method from a member function pointer (e.g. `.def("f",
    &Derived::f)`) we run into a problem if `&Derived::f` is actually
    implemented in some base class `Base` when `Base` isn't
    pybind-registered.
    
    This happens because the class type is deduced from the member function
    pointer, which then becomes a lambda with first argument this deduced
    type.  For a base class implementation, the deduced type is `Base`, not
    `Derived`, and so we generate and registered an overload which takes a
    `Base *` as first argument.  Trying to call this fails if `Base` isn't
    registered (e.g.  because it's an implementation detail class that isn't
    intended to be exposed to Python) because the type caster for an
    unregistered type always fails.
    
    This commit adds a `method_adaptor` function that rebinds a member
    function to a derived type member function and otherwise (i.e. regular
    functions/lambda) leaves the argument as-is.  This is now used for class
    definitions so that they are bound with type being registered rather
    than a potential base type.
    
    A closely related fix in this commit is to similarly update the lambdas
    used for `def_readwrite` (and related) to bind to the class type being
    registered rather than the deduced type so that registering a property
    that resolves to a base class member similarly generates a usable
    function.
    
    Fixes #854, #910.
    Co-Authored-By: default avatarDean Moldovan <dean0x7d@gmail.com>
    23bf8945
test_methods_and_attributes.cpp 19.3 KB