@@ -370,6 +370,30 @@ class cpp_function : public function {
370370 extra...);
371371 }
372372
373+ // / Construct a cpp_function from a class method (non-const, rvalue ref-qualifier)
374+ template <typename Return, typename Class, typename ... Arg, typename ... Extra>
375+ // NOLINTNEXTLINE(google-explicit-constructor)
376+ cpp_function (Return (Class::*f)(Arg...) &&, const Extra &...extra ) {
377+ initialize (
378+ [f](Class *c, Arg... args) -> Return {
379+ return (std::move (*c).*f)(std::forward<Arg>(args)...);
380+ },
381+ (Return (*)(Class *, Arg...)) nullptr ,
382+ extra...);
383+ }
384+
385+ // / Construct a cpp_function from a class method (const, rvalue ref-qualifier)
386+ template <typename Return, typename Class, typename ... Arg, typename ... Extra>
387+ // NOLINTNEXTLINE(google-explicit-constructor)
388+ cpp_function (Return (Class::*f)(Arg...) const &&, const Extra &...extra ) {
389+ initialize (
390+ [f](const Class *c, Arg... args) -> Return {
391+ return (std::move (*c).*f)(std::forward<Arg>(args)...);
392+ },
393+ (Return (*)(const Class *, Arg...)) nullptr ,
394+ extra...);
395+ }
396+
373397#ifdef __cpp_noexcept_function_type
374398 // / Construct a cpp_function from a class method (non-const, no ref-qualifier, noexcept)
375399 template <typename Return, typename Class, typename ... Arg, typename ... Extra>
@@ -410,6 +434,30 @@ class cpp_function : public function {
410434 (Return (*)(const Class *, Arg...)) nullptr ,
411435 extra...);
412436 }
437+
438+ // / Construct a cpp_function from a class method (non-const, rvalue ref-qualifier, noexcept)
439+ template <typename Return, typename Class, typename ... Arg, typename ... Extra>
440+ // NOLINTNEXTLINE(google-explicit-constructor)
441+ cpp_function (Return (Class::*f)(Arg...) && noexcept , const Extra &...extra ) {
442+ initialize (
443+ [f](Class *c, Arg... args) -> Return {
444+ return (std::move (*c).*f)(std::forward<Arg>(args)...);
445+ },
446+ (Return (*)(Class *, Arg...)) nullptr ,
447+ extra...);
448+ }
449+
450+ // / Construct a cpp_function from a class method (const, rvalue ref-qualifier, noexcept)
451+ template <typename Return, typename Class, typename ... Arg, typename ... Extra>
452+ // NOLINTNEXTLINE(google-explicit-constructor)
453+ cpp_function (Return (Class::*f)(Arg...) const && noexcept , const Extra &...extra ) {
454+ initialize (
455+ [f](const Class *c, Arg... args) -> Return {
456+ return (std::move (*c).*f)(std::forward<Arg>(args)...);
457+ },
458+ (Return (*)(const Class *, Arg...)) nullptr ,
459+ extra...);
460+ }
413461#endif
414462
415463 // / Return the function name
@@ -1922,6 +1970,49 @@ inline void add_class_method(object &cls, const char *name_, const cpp_function
19221970 }
19231971}
19241972
1973+ // / Type trait to rebind a member function pointer's class to `Derived`, preserving all
1974+ // / cv/ref/noexcept qualifiers. The primary template has no `type` member, providing SFINAE
1975+ // / failure for unsupported member function pointer types. `source_class` holds the original
1976+ // / class for use in `is_accessible_base_of` checks.
1977+ template <typename Derived, typename T>
1978+ struct rebind_member_ptr {};
1979+
1980+ // Define one specialization per supported qualifier combination via a local macro.
1981+ #define PYBIND11_REBIND_MEMBER_PTR (qualifiers ) \
1982+ template <typename Derived, typename Return, typename Class, typename ... Args> \
1983+ struct rebind_member_ptr <Derived, Return (Class::*)(Args...) qualifiers> { \
1984+ using type = Return (Derived::*)(Args...) qualifiers; \
1985+ using source_class = Class; \
1986+ }
1987+ PYBIND11_REBIND_MEMBER_PTR ();
1988+ PYBIND11_REBIND_MEMBER_PTR (const );
1989+ PYBIND11_REBIND_MEMBER_PTR (&);
1990+ PYBIND11_REBIND_MEMBER_PTR (const &);
1991+ PYBIND11_REBIND_MEMBER_PTR (&&);
1992+ PYBIND11_REBIND_MEMBER_PTR (const &&);
1993+ #ifdef __cpp_noexcept_function_type
1994+ PYBIND11_REBIND_MEMBER_PTR (noexcept );
1995+ PYBIND11_REBIND_MEMBER_PTR (const noexcept );
1996+ PYBIND11_REBIND_MEMBER_PTR (& noexcept );
1997+ PYBIND11_REBIND_MEMBER_PTR (const & noexcept );
1998+ PYBIND11_REBIND_MEMBER_PTR (&& noexcept );
1999+ PYBIND11_REBIND_MEMBER_PTR (const && noexcept );
2000+ #endif
2001+ #undef PYBIND11_REBIND_MEMBER_PTR
2002+
2003+ // / Shared implementation body for all method_adaptor member-function-pointer overloads.
2004+ // / Asserts Base is accessible from Derived, then casts the member pointer.
2005+ template <typename Derived,
2006+ typename T,
2007+ typename Traits = rebind_member_ptr<Derived, T>,
2008+ typename Adapted = typename Traits::type>
2009+ PYBIND11_ALWAYS_INLINE Adapted adapt_member_ptr (T pmf) {
2010+ static_assert (
2011+ is_accessible_base_of<typename Traits::source_class, Derived>::value,
2012+ " Cannot bind an inaccessible base class method; use a lambda definition instead" );
2013+ return pmf;
2014+ }
2015+
19252016PYBIND11_NAMESPACE_END (detail)
19262017
19272018// / Given a pointer to a member function, cast it to its `Derived` version.
@@ -1931,76 +2022,30 @@ auto method_adaptor(F &&f) -> decltype(std::forward<F>(f)) {
19312022 return std::forward<F>(f);
19322023}
19332024
1934- template <typename Derived, typename Return, typename Class, typename ... Args>
1935- auto method_adaptor (Return (Class::*pmf)(Args...)) -> Return (Derived::*)(Args...) {
1936- static_assert (
1937- detail::is_accessible_base_of<Class, Derived>::value,
1938- " Cannot bind an inaccessible base class method; use a lambda definition instead" );
1939- return pmf;
1940- }
1941-
1942- template <typename Derived, typename Return, typename Class, typename ... Args>
1943- auto method_adaptor (Return (Class::*pmf)(Args...) const ) -> Return (Derived::*)(Args...) const {
1944- static_assert (
1945- detail::is_accessible_base_of<Class, Derived>::value,
1946- " Cannot bind an inaccessible base class method; use a lambda definition instead" );
1947- return pmf;
1948- }
1949-
1950- template <typename Derived, typename Return, typename Class, typename ... Args>
1951- auto method_adaptor (Return (Class::*pmf)(Args...) &) -> Return (Derived::*)(Args...) & {
1952- static_assert (
1953- detail::is_accessible_base_of<Class, Derived>::value,
1954- " Cannot bind an inaccessible base class method; use a lambda definition instead" );
1955- return pmf;
1956- }
1957-
1958- template <typename Derived, typename Return, typename Class, typename ... Args>
1959- auto method_adaptor (Return (Class::*pmf)(Args...) const &)
1960- -> Return (Derived::*)(Args...) const & {
1961- static_assert (
1962- detail::is_accessible_base_of<Class, Derived>::value,
1963- " Cannot bind an inaccessible base class method; use a lambda definition instead" );
1964- return pmf;
1965- }
1966-
2025+ // One thin overload per supported member-function-pointer qualifier combination.
2026+ // Specific parameter types are required so partial ordering prefers these over the F&& fallback.
2027+ // The shared body (static_assert + implicit cast) lives in detail::adapt_member_ptr.
2028+ #define PYBIND11_METHOD_ADAPTOR (qualifiers ) \
2029+ template <typename Derived, typename Return, typename Class, typename ... Args> \
2030+ auto method_adaptor (Return (Class::*pmf)(Args...) qualifiers) -> Return (Derived::*)(Args...) \
2031+ qualifiers { \
2032+ return detail::adapt_member_ptr<Derived>(pmf); \
2033+ }
2034+ PYBIND11_METHOD_ADAPTOR ()
2035+ PYBIND11_METHOD_ADAPTOR (const )
2036+ PYBIND11_METHOD_ADAPTOR (&)
2037+ PYBIND11_METHOD_ADAPTOR (const &)
2038+ PYBIND11_METHOD_ADAPTOR (&&)
2039+ PYBIND11_METHOD_ADAPTOR (const &&)
19672040#ifdef __cpp_noexcept_function_type
1968- template <typename Derived, typename Return, typename Class, typename ... Args>
1969- auto method_adaptor (Return (Class::*pmf)(Args...) noexcept )
1970- -> Return (Derived::*)(Args...) noexcept {
1971- static_assert (
1972- detail::is_accessible_base_of<Class, Derived>::value,
1973- " Cannot bind an inaccessible base class method; use a lambda definition instead" );
1974- return pmf;
1975- }
1976-
1977- template <typename Derived, typename Return, typename Class, typename ... Args>
1978- auto method_adaptor (Return (Class::*pmf)(Args...) const noexcept )
1979- -> Return (Derived::*)(Args...) const noexcept {
1980- static_assert (
1981- detail::is_accessible_base_of<Class, Derived>::value,
1982- " Cannot bind an inaccessible base class method; use a lambda definition instead" );
1983- return pmf;
1984- }
1985-
1986- template <typename Derived, typename Return, typename Class, typename ... Args>
1987- auto method_adaptor (Return (Class::*pmf)(Args...) & noexcept )
1988- -> Return (Derived::*)(Args...) & noexcept {
1989- static_assert (
1990- detail::is_accessible_base_of<Class, Derived>::value,
1991- " Cannot bind an inaccessible base class method; use a lambda definition instead" );
1992- return pmf;
1993- }
1994-
1995- template <typename Derived, typename Return, typename Class, typename ... Args>
1996- auto method_adaptor (Return (Class::*pmf)(Args...) const & noexcept )
1997- -> Return (Derived::*)(Args...) const & noexcept {
1998- static_assert (
1999- detail::is_accessible_base_of<Class, Derived>::value,
2000- " Cannot bind an inaccessible base class method; use a lambda definition instead" );
2001- return pmf;
2002- }
2041+ PYBIND11_METHOD_ADAPTOR (noexcept )
2042+ PYBIND11_METHOD_ADAPTOR (const noexcept )
2043+ PYBIND11_METHOD_ADAPTOR (& noexcept )
2044+ PYBIND11_METHOD_ADAPTOR (const & noexcept )
2045+ PYBIND11_METHOD_ADAPTOR (&& noexcept )
2046+ PYBIND11_METHOD_ADAPTOR (const && noexcept )
20032047#endif
2048+ #undef PYBIND11_METHOD_ADAPTOR
20042049
20052050PYBIND11_NAMESPACE_BEGIN (detail)
20062051
0 commit comments