@@ -1600,8 +1600,6 @@ PYBIND11_NAMESPACE_BEGIN(detail)
1600
1600
template <typename PM>
1601
1601
using must_be_member_function_pointer = enable_if_t <std::is_member_pointer<PM>::value, int >;
1602
1602
1603
- PYBIND11_NAMESPACE_END (detail)
1604
-
1605
1603
// Note that property_cpp_function is intentionally in the main pybind11 namespace,
1606
1604
// because user-defined specializations could be useful.
1607
1605
@@ -1611,24 +1609,31 @@ PYBIND11_NAMESPACE_END(detail)
1611
1609
// WARNING: This classic implementation can lead to dangling pointers for raw pointer members.
1612
1610
// See test_ptr() in tests/test_class_sh_property.py
1613
1611
// This implementation works as-is (and safely) for smart_holder std::shared_ptr members.
1614
- template <typename T, typename D, typename SFINAE = void >
1615
- struct property_cpp_function {
1616
- template <typename PM, detail:: must_be_member_function_pointer<PM> = 0 >
1612
+ template <typename T, typename D>
1613
+ struct property_cpp_function_classic {
1614
+ template <typename PM, must_be_member_function_pointer<PM> = 0 >
1617
1615
static cpp_function readonly (PM pm, const handle &hdl) {
1618
1616
return cpp_function ([pm](const T &c) -> const D & { return c.*pm; }, is_method (hdl));
1619
1617
}
1620
1618
1621
- template <typename PM, detail:: must_be_member_function_pointer<PM> = 0 >
1619
+ template <typename PM, must_be_member_function_pointer<PM> = 0 >
1622
1620
static cpp_function read (PM pm, const handle &hdl) {
1623
1621
return readonly (pm, hdl);
1624
1622
}
1625
1623
1626
- template <typename PM, detail:: must_be_member_function_pointer<PM> = 0 >
1624
+ template <typename PM, must_be_member_function_pointer<PM> = 0 >
1627
1625
static cpp_function write (PM pm, const handle &hdl) {
1628
1626
return cpp_function ([pm](T &c, const D &value) { c.*pm = value; }, is_method (hdl));
1629
1627
}
1630
1628
};
1631
1629
1630
+ PYBIND11_NAMESPACE_END (detail)
1631
+
1632
+ template <typename T, typename D, typename SFINAE = void >
1633
+ struct property_cpp_function : detail::property_cpp_function_classic<T, D> {};
1634
+
1635
+ #ifdef PYBIND11_HAVE_INTERNALS_WITH_SMART_HOLDER_SUPPORT
1636
+
1632
1637
PYBIND11_NAMESPACE_BEGIN (detail)
1633
1638
1634
1639
template <typename T, typename D, typename SFINAE = void >
@@ -1644,10 +1649,6 @@ struct both_t_and_d_use_type_caster_base<
1644
1649
std::is_base_of<type_caster_base<intrinsic_t <D>>, make_caster<D>>>::value>>
1645
1650
: std::true_type {};
1646
1651
1647
- PYBIND11_NAMESPACE_END (detail)
1648
-
1649
- #ifdef PYBIND11_HAVE_INTERNALS_WITH_SMART_HOLDER_SUPPORT
1650
-
1651
1652
// BAKEIN_WIP: Rewrite comment.
1652
1653
// smart_holder specializations for raw pointer members.
1653
1654
// WARNING: Like the classic implementation, this implementation can lead to dangling pointers.
@@ -1656,22 +1657,18 @@ PYBIND11_NAMESPACE_END(detail)
1656
1657
// https://github.com/google/clif/blob/c371a6d4b28d25d53a16e6d2a6d97305fb1be25a/clif/python/instance.h#L233
1657
1658
// This prevents disowning of the Python object owning the raw pointer member.
1658
1659
template <typename T, typename D>
1659
- struct property_cpp_function <
1660
- T,
1661
- D,
1662
- detail::enable_if_t <detail::all_of<std::is_pointer<D>,
1663
- detail::both_t_and_d_use_type_caster_base<T, D>>::value>> {
1664
-
1660
+ struct property_cpp_function_sh_raw_ptr_member {
1665
1661
using drp = typename std::remove_pointer<D>::type;
1666
1662
1667
- template <typename PM, detail:: must_be_member_function_pointer<PM> = 0 >
1663
+ template <typename PM, must_be_member_function_pointer<PM> = 0 >
1668
1664
static cpp_function readonly (PM pm, const handle &hdl) {
1669
- detail:: type_info *tinfo = detail:: get_type_info (typeid (T), /* throw_if_missing=*/ true );
1670
- if (tinfo->holder_enum_v == detail:: holder_enum_t ::smart_holder) {
1665
+ type_info *tinfo = get_type_info (typeid (T), /* throw_if_missing=*/ true );
1666
+ if (tinfo->holder_enum_v == holder_enum_t ::smart_holder) {
1671
1667
return cpp_function (
1672
1668
[pm](handle c_hdl) -> std::shared_ptr<drp> {
1673
- std::shared_ptr<T> c_sp = detail::type_caster<
1674
- std::shared_ptr<T>>::shared_ptr_with_responsible_parent (c_hdl);
1669
+ std::shared_ptr<T> c_sp
1670
+ = type_caster<std::shared_ptr<T>>::shared_ptr_with_responsible_parent (
1671
+ c_hdl);
1675
1672
D ptr = (*c_sp).*pm;
1676
1673
return std::shared_ptr<drp>(c_sp, ptr);
1677
1674
},
@@ -1680,15 +1677,15 @@ struct property_cpp_function<
1680
1677
return cpp_function ([pm](const T &c) -> const D & { return c.*pm; }, is_method (hdl));
1681
1678
}
1682
1679
1683
- template <typename PM, detail:: must_be_member_function_pointer<PM> = 0 >
1680
+ template <typename PM, must_be_member_function_pointer<PM> = 0 >
1684
1681
static cpp_function read (PM pm, const handle &hdl) {
1685
1682
return readonly (pm, hdl);
1686
1683
}
1687
1684
1688
- template <typename PM, detail:: must_be_member_function_pointer<PM> = 0 >
1685
+ template <typename PM, must_be_member_function_pointer<PM> = 0 >
1689
1686
static cpp_function write (PM pm, const handle &hdl) {
1690
- detail:: type_info *tinfo = detail:: get_type_info (typeid (T), /* throw_if_missing=*/ true );
1691
- if (tinfo->holder_enum_v == detail:: holder_enum_t ::smart_holder) {
1687
+ type_info *tinfo = get_type_info (typeid (T), /* throw_if_missing=*/ true );
1688
+ if (tinfo->holder_enum_v == holder_enum_t ::smart_holder) {
1692
1689
return cpp_function ([pm](T &c, D value) { c.*pm = std::forward<D>(std::move (value)); },
1693
1690
is_method (hdl));
1694
1691
}
@@ -1702,23 +1699,16 @@ struct property_cpp_function<
1702
1699
// https://github.com/google/clif/blob/c371a6d4b28d25d53a16e6d2a6d97305fb1be25a/clif/python/instance.h#L233
1703
1700
// This prevents disowning of the Python object owning the member.
1704
1701
template <typename T, typename D>
1705
- struct property_cpp_function <T,
1706
- D,
1707
- detail::enable_if_t <detail::all_of<
1708
- detail::none_of<std::is_pointer<D>,
1709
- std::is_array<D>,
1710
- detail::is_instantiation<std::unique_ptr, D>,
1711
- detail::is_instantiation<std::shared_ptr, D>>,
1712
- detail::both_t_and_d_use_type_caster_base<T, D>>::value>> {
1713
-
1714
- template <typename PM, detail::must_be_member_function_pointer<PM> = 0 >
1702
+ struct property_cpp_function_sh_member_held_by_value {
1703
+ template <typename PM, must_be_member_function_pointer<PM> = 0 >
1715
1704
static cpp_function readonly (PM pm, const handle &hdl) {
1716
- detail:: type_info *tinfo = detail:: get_type_info (typeid (T), /* throw_if_missing=*/ true );
1717
- if (tinfo->holder_enum_v == detail:: holder_enum_t ::smart_holder) {
1705
+ type_info *tinfo = get_type_info (typeid (T), /* throw_if_missing=*/ true );
1706
+ if (tinfo->holder_enum_v == holder_enum_t ::smart_holder) {
1718
1707
return cpp_function (
1719
1708
[pm](handle c_hdl) -> std::shared_ptr<typename std::add_const<D>::type> {
1720
- std::shared_ptr<T> c_sp = detail::type_caster<
1721
- std::shared_ptr<T>>::shared_ptr_with_responsible_parent (c_hdl);
1709
+ std::shared_ptr<T> c_sp
1710
+ = type_caster<std::shared_ptr<T>>::shared_ptr_with_responsible_parent (
1711
+ c_hdl);
1722
1712
return std::shared_ptr<typename std::add_const<D>::type>(c_sp,
1723
1713
&(c_sp.get ()->*pm));
1724
1714
},
@@ -1727,25 +1717,26 @@ struct property_cpp_function<T,
1727
1717
return cpp_function ([pm](const T &c) -> const D & { return c.*pm; }, is_method (hdl));
1728
1718
}
1729
1719
1730
- template <typename PM, detail:: must_be_member_function_pointer<PM> = 0 >
1720
+ template <typename PM, must_be_member_function_pointer<PM> = 0 >
1731
1721
static cpp_function read (PM pm, const handle &hdl) {
1732
- detail:: type_info *tinfo = detail:: get_type_info (typeid (T), /* throw_if_missing=*/ true );
1733
- if (tinfo->holder_enum_v == detail:: holder_enum_t ::smart_holder) {
1722
+ type_info *tinfo = get_type_info (typeid (T), /* throw_if_missing=*/ true );
1723
+ if (tinfo->holder_enum_v == holder_enum_t ::smart_holder) {
1734
1724
return cpp_function (
1735
1725
[pm](handle c_hdl) -> std::shared_ptr<D> {
1736
- std::shared_ptr<T> c_sp = detail::type_caster<
1737
- std::shared_ptr<T>>::shared_ptr_with_responsible_parent (c_hdl);
1726
+ std::shared_ptr<T> c_sp
1727
+ = type_caster<std::shared_ptr<T>>::shared_ptr_with_responsible_parent (
1728
+ c_hdl);
1738
1729
return std::shared_ptr<D>(c_sp, &(c_sp.get ()->*pm));
1739
1730
},
1740
1731
is_method (hdl));
1741
1732
}
1742
1733
return cpp_function ([pm](const T &c) -> const D & { return c.*pm; }, is_method (hdl));
1743
1734
}
1744
1735
1745
- template <typename PM, detail:: must_be_member_function_pointer<PM> = 0 >
1736
+ template <typename PM, must_be_member_function_pointer<PM> = 0 >
1746
1737
static cpp_function write (PM pm, const handle &hdl) {
1747
- detail:: type_info *tinfo = detail:: get_type_info (typeid (T), /* throw_if_missing=*/ true );
1748
- if (tinfo->holder_enum_v == detail:: holder_enum_t ::smart_holder) {
1738
+ type_info *tinfo = get_type_info (typeid (T), /* throw_if_missing=*/ true );
1739
+ if (tinfo->holder_enum_v == holder_enum_t ::smart_holder) {
1749
1740
return cpp_function ([pm](T &c, const D &value) { c.*pm = value; }, is_method (hdl));
1750
1741
}
1751
1742
return cpp_function ([pm](T &c, const D &value) { c.*pm = value; }, is_method (hdl));
@@ -1760,41 +1751,66 @@ struct property_cpp_function<T,
1760
1751
// accessible as a Python object without disowning the member unique_ptr. A .def_readonly disowning
1761
1752
// the unique_ptr member is deemed highly prone to misunderstandings.
1762
1753
template <typename T, typename D>
1763
- struct property_cpp_function <
1764
- T,
1765
- D,
1766
- detail::enable_if_t <detail::all_of<
1767
- detail::is_instantiation<std::unique_ptr, D>,
1768
- detail::both_t_and_d_use_type_caster_base<T, typename D::element_type>>::value>> {
1769
-
1770
- template <typename PM, detail::must_be_member_function_pointer<PM> = 0 >
1754
+ struct property_cpp_function_sh_unique_ptr_member {
1755
+ template <typename PM, must_be_member_function_pointer<PM> = 0 >
1771
1756
static cpp_function readonly (PM, const handle &) {
1772
- static_assert (!detail:: is_instantiation<std::unique_ptr, D>::value,
1757
+ static_assert (!is_instantiation<std::unique_ptr, D>::value,
1773
1758
" def_readonly cannot be used for std::unique_ptr members." );
1774
1759
return cpp_function{}; // Unreachable.
1775
1760
}
1776
1761
1777
- template <typename PM, detail:: must_be_member_function_pointer<PM> = 0 >
1762
+ template <typename PM, must_be_member_function_pointer<PM> = 0 >
1778
1763
static cpp_function read (PM pm, const handle &hdl) {
1779
- detail:: type_info *tinfo = detail:: get_type_info (typeid (T), /* throw_if_missing=*/ true );
1780
- if (tinfo->holder_enum_v == detail:: holder_enum_t ::smart_holder) {
1764
+ type_info *tinfo = get_type_info (typeid (T), /* throw_if_missing=*/ true );
1765
+ if (tinfo->holder_enum_v == holder_enum_t ::smart_holder) {
1781
1766
return cpp_function (
1782
1767
[pm](handle c_hdl) -> D {
1783
- std::shared_ptr<T> c_sp = detail::type_caster<
1784
- std::shared_ptr<T>>::shared_ptr_with_responsible_parent (c_hdl);
1768
+ std::shared_ptr<T> c_sp
1769
+ = type_caster<std::shared_ptr<T>>::shared_ptr_with_responsible_parent (
1770
+ c_hdl);
1785
1771
return D{std::move (c_sp.get ()->*pm)};
1786
1772
},
1787
1773
is_method (hdl));
1788
1774
}
1789
1775
return cpp_function ([pm](const T &c) -> const D & { return c.*pm; }, is_method (hdl));
1790
1776
}
1791
1777
1792
- template <typename PM, detail:: must_be_member_function_pointer<PM> = 0 >
1778
+ template <typename PM, must_be_member_function_pointer<PM> = 0 >
1793
1779
static cpp_function write (PM pm, const handle &hdl) {
1794
1780
return cpp_function ([pm](T &c, D &&value) { c.*pm = std::move (value); }, is_method (hdl));
1795
1781
}
1796
1782
};
1797
1783
1784
+ PYBIND11_NAMESPACE_END (detail)
1785
+
1786
+ template <typename T, typename D>
1787
+ struct property_cpp_function <
1788
+ T,
1789
+ D,
1790
+ detail::enable_if_t <detail::all_of<std::is_pointer<D>,
1791
+ detail::both_t_and_d_use_type_caster_base<T, D>>::value>>
1792
+ : detail::property_cpp_function_sh_raw_ptr_member<T, D> {};
1793
+
1794
+ template <typename T, typename D>
1795
+ struct property_cpp_function <T,
1796
+ D,
1797
+ detail::enable_if_t <detail::all_of<
1798
+ detail::none_of<std::is_pointer<D>,
1799
+ std::is_array<D>,
1800
+ detail::is_instantiation<std::unique_ptr, D>,
1801
+ detail::is_instantiation<std::shared_ptr, D>>,
1802
+ detail::both_t_and_d_use_type_caster_base<T, D>>::value>>
1803
+ : detail::property_cpp_function_sh_member_held_by_value<T, D> {};
1804
+
1805
+ template <typename T, typename D>
1806
+ struct property_cpp_function <
1807
+ T,
1808
+ D,
1809
+ detail::enable_if_t <detail::all_of<
1810
+ detail::is_instantiation<std::unique_ptr, D>,
1811
+ detail::both_t_and_d_use_type_caster_base<T, typename D::element_type>>::value>>
1812
+ : detail::property_cpp_function_sh_unique_ptr_member<T, D> {};
1813
+
1798
1814
#endif // PYBIND11_HAVE_INTERNALS_WITH_SMART_HOLDER_SUPPORT
1799
1815
1800
1816
#if defined(PYBIND11_USE_SMART_HOLDER_AS_DEFAULT) \
0 commit comments