|
| 1 | +// Copyright (c) 2021 The Pybind Development Team. |
| 2 | +// All rights reserved. Use of this source code is governed by a |
| 3 | +// BSD-style license that can be found in the LICENSE file. |
| 4 | + |
| 5 | +#include "pybind11/smart_holder.h" |
| 6 | +#include "pybind11/trampoline_self_life_support.h" |
| 7 | +#include "pybind11_tests.h" |
| 8 | + |
| 9 | +#include <memory> |
| 10 | +#include <string> |
| 11 | + |
| 12 | +namespace { |
| 13 | + |
| 14 | +struct Big5 { // Also known as "rule of five". |
| 15 | + std::string history; |
| 16 | + |
| 17 | + explicit Big5(std::string history_start) : history{history_start} {} |
| 18 | + |
| 19 | + Big5(const Big5 &other) { history = other.history + "_CpCtor"; } |
| 20 | + |
| 21 | + Big5(Big5 &&other) { history = other.history + "_MvCtor"; } |
| 22 | + |
| 23 | + Big5 &operator=(const Big5 &other) { |
| 24 | + history = other.history + "_OpEqLv"; |
| 25 | + return *this; |
| 26 | + } |
| 27 | + |
| 28 | + Big5 &operator=(Big5 &&other) { |
| 29 | + history = other.history + "_OpEqRv"; |
| 30 | + return *this; |
| 31 | + } |
| 32 | + |
| 33 | + virtual ~Big5() = default; |
| 34 | + |
| 35 | +protected: |
| 36 | + Big5() : history{"DefaultConstructor"} {} |
| 37 | +}; |
| 38 | + |
| 39 | +struct Big5Trampoline : Big5, py::trampoline_self_life_support { |
| 40 | + using Big5::Big5; |
| 41 | +}; |
| 42 | + |
| 43 | +} // namespace |
| 44 | + |
| 45 | +PYBIND11_SMART_HOLDER_TYPE_CASTERS(Big5) |
| 46 | + |
| 47 | +TEST_SUBMODULE(class_sh_trampoline_self_life_support, m) { |
| 48 | + py::classh<Big5, Big5Trampoline>(m, "Big5") |
| 49 | + .def(py::init<std::string>()) |
| 50 | + .def_readonly("history", &Big5::history); |
| 51 | + |
| 52 | + m.def("action", [](std::unique_ptr<Big5> obj, int action_id) { |
| 53 | + py::object o2 = py::none(); |
| 54 | + // This is very unusual, but needed to directly exercise the trampoline_self_life_support |
| 55 | + // CpCtor, MvCtor, operator= lvalue, operator= rvalue. |
| 56 | + auto obj_trampoline = dynamic_cast<Big5Trampoline *>(obj.get()); |
| 57 | + if (obj_trampoline != nullptr) { |
| 58 | + switch (action_id) { |
| 59 | + case 0: { // CpCtor |
| 60 | + std::unique_ptr<Big5> cp(new Big5Trampoline(*obj_trampoline)); |
| 61 | + o2 = py::cast(std::move(cp)); |
| 62 | + } break; |
| 63 | + case 1: { // MvCtor |
| 64 | + std::unique_ptr<Big5> mv(new Big5Trampoline(std::move(*obj_trampoline))); |
| 65 | + o2 = py::cast(std::move(mv)); |
| 66 | + } break; |
| 67 | + case 2: { // operator= lvalue |
| 68 | + std::unique_ptr<Big5> lv(new Big5Trampoline); |
| 69 | + *lv = *obj_trampoline; |
| 70 | + o2 = py::cast(std::move(lv)); |
| 71 | + } break; |
| 72 | + case 3: { // operator= rvalue |
| 73 | + std::unique_ptr<Big5> rv(new Big5Trampoline); |
| 74 | + *rv = std::move(*obj_trampoline); |
| 75 | + o2 = py::cast(std::move(rv)); |
| 76 | + } break; |
| 77 | + default: |
| 78 | + break; |
| 79 | + } |
| 80 | + } |
| 81 | + py::object o1 = py::cast(std::move(obj)); |
| 82 | + return py::make_tuple(o1, o2); |
| 83 | + }); |
| 84 | +} |
0 commit comments