Skip to content

Commit a281ef8

Browse files
committed
must_be_member_function_pointer<PM>
1 parent 0589ec9 commit a281ef8

File tree

1 file changed

+16
-12
lines changed

1 file changed

+16
-12
lines changed

include/pybind11/pybind11.h

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
13861390
template <typename T, typename D, typename SFINAE = void>
13871391
struct 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

Comments
 (0)