| #include "pybind11_tests.h" | |
| #include <memory> | |
| namespace pybind11_tests { | |
| namespace class_sh_inheritance { | |
| template <int Id> | |
| struct base_template { | |
| base_template() : base_id(Id) {} | |
| virtual ~base_template() = default; | |
| virtual int id() const { return base_id; } | |
| int base_id; | |
| // Some compilers complain about implicitly defined versions of some of the following: | |
| base_template(const base_template &) = default; | |
| base_template(base_template &&) noexcept = default; | |
| base_template &operator=(const base_template &) = default; | |
| base_template &operator=(base_template &&) noexcept = default; | |
| }; | |
| using base = base_template<100>; | |
| struct drvd : base { | |
| int id() const override { return 2 * base_id; } | |
| }; | |
| // clang-format off | |
| inline drvd *rtrn_mptr_drvd() { return new drvd; } | |
| inline base *rtrn_mptr_drvd_up_cast() { return new drvd; } | |
| inline int pass_cptr_base(base const *b) { return b->id() + 11; } | |
| inline int pass_cptr_drvd(drvd const *d) { return d->id() + 12; } | |
| inline std::shared_ptr<drvd> rtrn_shmp_drvd() { return std::make_shared<drvd>(); } | |
| inline std::shared_ptr<base> rtrn_shmp_drvd_up_cast() { return std::make_shared<drvd>(); } | |
| inline int pass_shcp_base(const std::shared_ptr<base const>& b) { return b->id() + 21; } | |
| inline int pass_shcp_drvd(const std::shared_ptr<drvd const>& d) { return d->id() + 22; } | |
| // clang-format on | |
| using base1 = base_template<110>; | |
| using base2 = base_template<120>; | |
| // Not reusing base here because it would interfere with the single-inheritance test. | |
| struct drvd2 : base1, base2 { | |
| int id() const override { return 3 * base1::base_id + 4 * base2::base_id; } | |
| }; | |
| // clang-format off | |
| inline drvd2 *rtrn_mptr_drvd2() { return new drvd2; } | |
| inline base1 *rtrn_mptr_drvd2_up_cast1() { return new drvd2; } | |
| inline base2 *rtrn_mptr_drvd2_up_cast2() { return new drvd2; } | |
| inline int pass_cptr_base1(base1 const *b) { return b->id() + 21; } | |
| inline int pass_cptr_base2(base2 const *b) { return b->id() + 22; } | |
| inline int pass_cptr_drvd2(drvd2 const *d) { return d->id() + 23; } | |
| // clang-format on | |
| TEST_SUBMODULE(class_sh_inheritance, m) { | |
| py::classh<base>(m, "base"); | |
| py::classh<drvd, base>(m, "drvd"); | |
| auto rvto = py::return_value_policy::take_ownership; | |
| m.def("rtrn_mptr_drvd", rtrn_mptr_drvd, rvto); | |
| m.def("rtrn_mptr_drvd_up_cast", rtrn_mptr_drvd_up_cast, rvto); | |
| m.def("pass_cptr_base", pass_cptr_base); | |
| m.def("pass_cptr_drvd", pass_cptr_drvd); | |
| m.def("rtrn_shmp_drvd", rtrn_shmp_drvd); | |
| m.def("rtrn_shmp_drvd_up_cast", rtrn_shmp_drvd_up_cast); | |
| m.def("pass_shcp_base", pass_shcp_base); | |
| m.def("pass_shcp_drvd", pass_shcp_drvd); | |
| // __init__ needed for Python inheritance. | |
| py::classh<base1>(m, "base1").def(py::init<>()); | |
| py::classh<base2>(m, "base2").def(py::init<>()); | |
| py::classh<drvd2, base1, base2>(m, "drvd2"); | |
| m.def("rtrn_mptr_drvd2", rtrn_mptr_drvd2, rvto); | |
| m.def("rtrn_mptr_drvd2_up_cast1", rtrn_mptr_drvd2_up_cast1, rvto); | |
| m.def("rtrn_mptr_drvd2_up_cast2", rtrn_mptr_drvd2_up_cast2, rvto); | |
| m.def("pass_cptr_base1", pass_cptr_base1); | |
| m.def("pass_cptr_base2", pass_cptr_base2); | |
| m.def("pass_cptr_drvd2", pass_cptr_drvd2); | |
| } | |
| } // namespace class_sh_inheritance | |
| } // namespace pybind11_tests |