mirror of
https://github.com/pybind/pybind11.git
synced 2026-03-14 20:27:47 +00:00
Add support for shared_ptr<const T> in py::init() with smart_holder (#5731)
* Add overload to enable `.def(py::init(&rtrn_shcp))`. Also uncomment `.def(py::init(&rtrn_uqcp))` and `.def(py::init(&rtrn_udcp))`, which happen to work already (not sure what change in the past made those work). * Introduce `construct_from_shared_ptr()` helper for DRY-ness.
This commit is contained in:
committed by
GitHub
parent
365d41a4ba
commit
86e82ddbc2
@@ -246,20 +246,38 @@ void construct(value_and_holder &v_h,
|
||||
v_h.type->init_instance(v_h.inst, &smhldr);
|
||||
}
|
||||
|
||||
template <typename Class, detail::enable_if_t<is_smart_holder<Holder<Class>>::value, int> = 0>
|
||||
void construct(value_and_holder &v_h, std::shared_ptr<Cpp<Class>> &&shd_ptr, bool need_alias) {
|
||||
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(need_alias);
|
||||
template <typename PtrType, typename Class>
|
||||
void construct_from_shared_ptr(value_and_holder &v_h,
|
||||
std::shared_ptr<PtrType> &&shd_ptr,
|
||||
bool need_alias) {
|
||||
static_assert(std::is_same<PtrType, Cpp<Class>>::value
|
||||
|| std::is_same<PtrType, const Cpp<Class>>::value,
|
||||
"Expected (const) Cpp<Class> as shared_ptr pointee");
|
||||
auto *ptr = shd_ptr.get();
|
||||
no_nullptr(ptr);
|
||||
if (Class::has_alias && need_alias && !is_alias<Class>(ptr)) {
|
||||
throw type_error("pybind11::init(): construction failed: returned std::shared_ptr pointee "
|
||||
"is not an alias instance");
|
||||
}
|
||||
auto smhldr = smart_holder::from_shared_ptr(shd_ptr);
|
||||
v_h.value_ptr() = ptr;
|
||||
// Cast to non-const if needed, consistent with internal design
|
||||
auto smhldr
|
||||
= smart_holder::from_shared_ptr(std::const_pointer_cast<Cpp<Class>>(std::move(shd_ptr)));
|
||||
v_h.value_ptr() = const_cast<Cpp<Class> *>(ptr);
|
||||
v_h.type->init_instance(v_h.inst, &smhldr);
|
||||
}
|
||||
|
||||
template <typename Class, detail::enable_if_t<is_smart_holder<Holder<Class>>::value, int> = 0>
|
||||
void construct(value_and_holder &v_h, std::shared_ptr<Cpp<Class>> &&shd_ptr, bool need_alias) {
|
||||
construct_from_shared_ptr<Cpp<Class>, Class>(v_h, std::move(shd_ptr), need_alias);
|
||||
}
|
||||
|
||||
template <typename Class, detail::enable_if_t<is_smart_holder<Holder<Class>>::value, int> = 0>
|
||||
void construct(value_and_holder &v_h,
|
||||
std::shared_ptr<const Cpp<Class>> &&shd_ptr,
|
||||
bool need_alias) {
|
||||
construct_from_shared_ptr<const Cpp<Class>, Class>(v_h, std::move(shd_ptr), need_alias);
|
||||
}
|
||||
|
||||
template <typename Class, detail::enable_if_t<is_smart_holder<Holder<Class>>::value, int> = 0>
|
||||
void construct(value_and_holder &v_h,
|
||||
std::shared_ptr<Alias<Class>> &&shd_ptr,
|
||||
|
||||
@@ -108,10 +108,7 @@ TEST_SUBMODULE(class_sh_factory_constructors, m) {
|
||||
.def("get_mtxt", get_mtxt<atyp_shmp>);
|
||||
|
||||
py::classh<atyp_shcp>(m, "atyp_shcp")
|
||||
// py::class_<atyp_shcp, std::shared_ptr<atyp_shcp>>(m, "atyp_shcp")
|
||||
// class_: ... must return a compatible ...
|
||||
// classh: ... cannot pass object of non-trivial type ...
|
||||
// .def(py::init(&rtrn_shcp))
|
||||
.def(py::init(&rtrn_shcp))
|
||||
.def("get_mtxt", get_mtxt<atyp_shcp>);
|
||||
|
||||
py::classh<atyp_uqmp>(m, "atyp_uqmp")
|
||||
@@ -119,9 +116,7 @@ TEST_SUBMODULE(class_sh_factory_constructors, m) {
|
||||
.def("get_mtxt", get_mtxt<atyp_uqmp>);
|
||||
|
||||
py::classh<atyp_uqcp>(m, "atyp_uqcp")
|
||||
// class_: ... cannot pass object of non-trivial type ...
|
||||
// classh: ... cannot pass object of non-trivial type ...
|
||||
// .def(py::init(&rtrn_uqcp))
|
||||
.def(py::init(&rtrn_uqcp))
|
||||
.def("get_mtxt", get_mtxt<atyp_uqcp>);
|
||||
|
||||
py::classh<atyp_udmp>(m, "atyp_udmp")
|
||||
@@ -129,10 +124,7 @@ TEST_SUBMODULE(class_sh_factory_constructors, m) {
|
||||
.def("get_mtxt", get_mtxt<atyp_udmp>);
|
||||
|
||||
py::classh<atyp_udcp>(m, "atyp_udcp")
|
||||
// py::class_<atyp_udcp, std::unique_ptr<atyp_udcp, sddc>>(m, "atyp_udcp")
|
||||
// class_: ... must return a compatible ...
|
||||
// classh: ... cannot pass object of non-trivial type ...
|
||||
// .def(py::init(&rtrn_udcp))
|
||||
.def(py::init(&rtrn_udcp))
|
||||
.def("get_mtxt", get_mtxt<atyp_udcp>);
|
||||
|
||||
py::classh<with_alias, with_alias_alias>(m, "with_alias")
|
||||
|
||||
@@ -13,11 +13,11 @@ def test_atyp_factories():
|
||||
# sert m.atyp_cptr().get_mtxt() == "Cptr"
|
||||
assert m.atyp_mptr().get_mtxt() == "Mptr"
|
||||
assert m.atyp_shmp().get_mtxt() == "Shmp"
|
||||
# sert m.atyp_shcp().get_mtxt() == "Shcp"
|
||||
assert m.atyp_shcp().get_mtxt() == "Shcp"
|
||||
assert m.atyp_uqmp().get_mtxt() == "Uqmp"
|
||||
# sert m.atyp_uqcp().get_mtxt() == "Uqcp"
|
||||
assert m.atyp_uqcp().get_mtxt() == "Uqcp"
|
||||
assert m.atyp_udmp().get_mtxt() == "Udmp"
|
||||
# sert m.atyp_udcp().get_mtxt() == "Udcp"
|
||||
assert m.atyp_udcp().get_mtxt() == "Udcp"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
Reference in New Issue
Block a user