diff --git a/include/pybind11/detail/common.h b/include/pybind11/detail/common.h index 6d328ba8b8..427f1c87d4 100644 --- a/include/pybind11/detail/common.h +++ b/include/pybind11/detail/common.h @@ -581,6 +581,11 @@ template using deferred_t = typename deferred_type< template using is_strict_base_of = bool_constant< std::is_base_of::value && !std::is_same::value>; +/// Like is_base_of, but also requires that the base type is accessible (i.e. that a Derived pointer +/// can be converted to a Base pointer) +template using is_accessible_base_of = bool_constant< + std::is_base_of::value && std::is_convertible::value>; + template class Base> struct is_template_base_of_impl { template static std::true_type check(Base *); diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 59af022927..90b8ebcc63 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -997,10 +997,18 @@ template auto method_adaptor(F &&f) -> decltype(std::forward(f)) { return std::forward(f); } template -auto method_adaptor(Return (Class::*pmf)(Args...)) -> Return (Derived::*)(Args...) { return pmf; } +auto method_adaptor(Return (Class::*pmf)(Args...)) -> Return (Derived::*)(Args...) { + static_assert(detail::is_accessible_base_of::value, + "Cannot bind an inaccessible base class method; use a lambda definition instead"); + return pmf; +} template -auto method_adaptor(Return (Class::*pmf)(Args...) const) -> Return (Derived::*)(Args...) const { return pmf; } +auto method_adaptor(Return (Class::*pmf)(Args...) const) -> Return (Derived::*)(Args...) const { + static_assert(detail::is_accessible_base_of::value, + "Cannot bind an inaccessible base class method; use a lambda definition instead"); + return pmf; +} template class class_ : public detail::generic_type {