@@ -1378,24 +1378,28 @@ using default_holder_type = smart_holder;
13781378
13791379#endif
13801380
1381+ template <typename PM>
1382+ using must_be_member_function_pointer
1383+ = detail::enable_if_t <std::is_member_pointer<PM>::value, int >;
1384+
13811385// Classic (non-smart_holder) implementations for .def_readonly and .def_readwrite
13821386// getter and setter functions.
13831387// WARNING: This classic implementation can lead to dangling pointers for raw pointer members.
13841388// See test_ptr() in tests/test_class_sh_property.py
13851389// This implementation works as-is for smart_holder std::shared_ptr members.
13861390template <typename T, typename D, typename SFINAE = void >
13871391struct xetter_cpp_function {
1388- template <typename PM>
1392+ template <typename PM, must_be_member_function_pointer<PM> = 0 >
13891393 static cpp_function readonly (PM pm, const handle &hdl) {
13901394 return cpp_function ([pm](const T &c) -> const D & { return c.*pm; }, is_method (hdl));
13911395 }
13921396
1393- template <typename PM>
1397+ template <typename PM, must_be_member_function_pointer<PM> = 0 >
13941398 static cpp_function read (PM pm, const handle &hdl) {
13951399 return readonly (pm, hdl);
13961400 }
13971401
1398- template <typename PM>
1402+ template <typename PM, must_be_member_function_pointer<PM> = 0 >
13991403 static cpp_function write (PM pm, const handle &hdl) {
14001404 return cpp_function ([pm](T &c, const D &value) { c.*pm = value; }, is_method (hdl));
14011405 }
@@ -1417,7 +1421,7 @@ struct xetter_cpp_function<
14171421
14181422 using drp = typename std::remove_pointer<D>::type;
14191423
1420- template <typename PM>
1424+ template <typename PM, must_be_member_function_pointer<PM> = 0 >
14211425 static cpp_function readonly (PM pm, const handle &hdl) {
14221426 return cpp_function (
14231427 [pm](const std::shared_ptr<T> &c_sp) -> std::shared_ptr<drp> {
@@ -1427,12 +1431,12 @@ struct xetter_cpp_function<
14271431 is_method (hdl));
14281432 }
14291433
1430- template <typename PM>
1434+ template <typename PM, must_be_member_function_pointer<PM> = 0 >
14311435 static cpp_function read (PM pm, const handle &hdl) {
14321436 return readonly (pm, hdl);
14331437 }
14341438
1435- template <typename PM>
1439+ template <typename PM, must_be_member_function_pointer<PM> = 0 >
14361440 static cpp_function write (PM pm, const handle &hdl) {
14371441 return cpp_function ([pm](T &c, D value) { c.*pm = value; }, is_method (hdl));
14381442 }
@@ -1452,7 +1456,7 @@ struct xetter_cpp_function<
14521456 && !detail::is_std_unique_ptr<D>::value //
14531457 && !detail::is_std_shared_ptr<D>::value>> {
14541458
1455- template <typename PM>
1459+ template <typename PM, must_be_member_function_pointer<PM> = 0 >
14561460 static cpp_function readonly (PM pm, const handle &hdl) {
14571461 return cpp_function (
14581462 [pm](const std::shared_ptr<T> &c_sp)
@@ -1462,7 +1466,7 @@ struct xetter_cpp_function<
14621466 is_method (hdl));
14631467 }
14641468
1465- template <typename PM>
1469+ template <typename PM, must_be_member_function_pointer<PM> = 0 >
14661470 static cpp_function read (PM pm, const handle &hdl) {
14671471 return cpp_function (
14681472 [pm](const std::shared_ptr<T> &c_sp) -> std::shared_ptr<D> {
@@ -1471,7 +1475,7 @@ struct xetter_cpp_function<
14711475 is_method (hdl));
14721476 }
14731477
1474- template <typename PM>
1478+ template <typename PM, must_be_member_function_pointer<PM> = 0 >
14751479 static cpp_function write (PM pm, const handle &hdl) {
14761480 return cpp_function ([pm](T &c, const D &value) { c.*pm = value; }, is_method (hdl));
14771481 }
@@ -1492,21 +1496,21 @@ struct xetter_cpp_function<
14921496 && detail::is_std_unique_ptr<D>::value
14931497 && detail::type_uses_smart_holder_type_caster<typename D::element_type>::value>> {
14941498
1495- template <typename PM>
1499+ template <typename PM, must_be_member_function_pointer<PM> = 0 >
14961500 static cpp_function readonly (PM, const handle &) {
14971501 static_assert (!detail::is_std_unique_ptr<D>::value,
14981502 " def_readonly cannot be used for std::unique_ptr members." );
14991503 return cpp_function{}; // Unreachable.
15001504 }
15011505
1502- template <typename PM>
1506+ template <typename PM, must_be_member_function_pointer<PM> = 0 >
15031507 static cpp_function read (PM pm, const handle &hdl) {
15041508 return cpp_function (
15051509 [pm](const std::shared_ptr<T> &c_sp) -> D { return D{std::move (c_sp.get ()->*pm)}; },
15061510 is_method (hdl));
15071511 }
15081512
1509- template <typename PM>
1513+ template <typename PM, must_be_member_function_pointer<PM> = 0 >
15101514 static cpp_function write (PM pm, const handle &hdl) {
15111515 return cpp_function ([pm](T &c, D &&value) { c.*pm = std::move (value); }, is_method (hdl));
15121516 }
0 commit comments