Skip to content

Commit b6092e9

Browse files
committed
Simplify method adaptor into 2 template instatiations with enable_if_t
1 parent 0e0669d commit b6092e9

File tree

1 file changed

+19
-33
lines changed

1 file changed

+19
-33
lines changed

include/pybind11/pybind11.h

Lines changed: 19 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2026,45 +2026,31 @@ constexpr PYBIND11_ALWAYS_INLINE Adapted adapt_member_ptr(T pmf) {
20262026
PYBIND11_NAMESPACE_END(detail)
20272027

20282028
/// Given a pointer to a member function, cast it to its `Derived` version.
2029-
/// Forward everything else unchanged.
2030-
template <typename /*Derived*/, typename F>
2029+
/// For all other callables (lambdas, function pointers, etc.), forward unchanged.
2030+
///
2031+
/// Two overloads cover all cases without explicit per-qualifier instantiations:
2032+
///
2033+
/// (1) Generic fallback — disabled for member function pointers so that (2) wins
2034+
/// without any partial-ordering ambiguity.
2035+
/// (2) MFP overload — SFINAE on rebind_member_ptr::type, which exists for every
2036+
/// supported qualifier combination (const, &, &&, noexcept, ...). A single
2037+
/// template therefore covers all combinations that rebind_member_ptr handles.
2038+
template <
2039+
typename /*Derived*/,
2040+
typename F,
2041+
detail::enable_if_t<!std::is_member_function_pointer<detail::remove_reference_t<F>>::value,
2042+
int>
2043+
= 0>
20312044
constexpr auto method_adaptor(F &&f) -> decltype(std::forward<F>(f)) {
20322045
return std::forward<F>(f);
20332046
}
20342047

2035-
// One thin overload per supported member-function-pointer qualifier combination.
2036-
// Specific parameter types are required so partial ordering prefers these over the F&& fallback.
2037-
// The shared body (static_assert + implicit cast) lives in detail::adapt_member_ptr.
2038-
// The no-qualifier overload is written out explicitly to avoid invoking the macro with an empty
2039-
// argument, which triggers MSVC warning C4003.
2040-
template <typename Derived, typename Return, typename Class, typename... Args>
2041-
constexpr auto method_adaptor(Return (Class::*pmf)(Args...)) -> Return (Derived::*)(Args...) {
2048+
template <typename Derived,
2049+
typename T,
2050+
typename Adapted = typename detail::rebind_member_ptr<Derived, T>::type>
2051+
constexpr Adapted method_adaptor(T pmf) {
20422052
return detail::adapt_member_ptr<Derived>(pmf);
20432053
}
2044-
// The qualifiers argument appears in type position, not expression position, so
2045-
// parenthesizing it would produce invalid C++.
2046-
// NOLINTBEGIN(bugprone-macro-parentheses)
2047-
#define PYBIND11_METHOD_ADAPTOR(qualifiers) \
2048-
template <typename Derived, typename Return, typename Class, typename... Args> \
2049-
constexpr auto method_adaptor(Return (Class::*pmf)(Args...) qualifiers) \
2050-
-> Return (Derived::*)(Args...) qualifiers { \
2051-
return detail::adapt_member_ptr<Derived>(pmf); \
2052-
}
2053-
PYBIND11_METHOD_ADAPTOR(const)
2054-
PYBIND11_METHOD_ADAPTOR(&)
2055-
PYBIND11_METHOD_ADAPTOR(const &)
2056-
PYBIND11_METHOD_ADAPTOR(&&)
2057-
PYBIND11_METHOD_ADAPTOR(const &&)
2058-
#ifdef __cpp_noexcept_function_type
2059-
PYBIND11_METHOD_ADAPTOR(noexcept)
2060-
PYBIND11_METHOD_ADAPTOR(const noexcept)
2061-
PYBIND11_METHOD_ADAPTOR(& noexcept)
2062-
PYBIND11_METHOD_ADAPTOR(const & noexcept)
2063-
PYBIND11_METHOD_ADAPTOR(&& noexcept)
2064-
PYBIND11_METHOD_ADAPTOR(const && noexcept)
2065-
#endif
2066-
#undef PYBIND11_METHOD_ADAPTOR
2067-
// NOLINTEND(bugprone-macro-parentheses)
20682054

20692055
PYBIND11_NAMESPACE_BEGIN(detail)
20702056

0 commit comments

Comments
 (0)