test_classh_wip.cpp 7.86 KB
Newer Older
1
2
3
4
5
#include "pybind11_tests.h"

#include <pybind11/classh.h>

#include <memory>
6
#include <string>
7
8
9
10

namespace pybind11_tests {
namespace classh_wip {

11
12
13
14
15
struct mpty {
    std::string mtxt;
};

// clang-format off
16

17
18
19
20
21
22
mpty        rtrn_mpty_valu() { mpty obj{"rtrn_valu"}; return obj; }
mpty&&      rtrn_mpty_rref() { mpty obj{"rtrn_rref"}; return std::move(obj); }
mpty const& rtrn_mpty_cref() { static mpty obj; obj.mtxt = "rtrn_cref"; return obj; }
mpty&       rtrn_mpty_mref() { static mpty obj; obj.mtxt = "rtrn_mref"; return obj; }
mpty const* rtrn_mpty_cptr() { static mpty obj; obj.mtxt = "rtrn_cptr"; return &obj; }
mpty*       rtrn_mpty_mptr() { static mpty obj; obj.mtxt = "rtrn_mptr"; return &obj; }
23

24
25
26
27
28
29
std::string pass_mpty_valu(mpty obj)        { return "pass_valu:" + obj.mtxt; }
std::string pass_mpty_rref(mpty&& obj)      { return "pass_rref:" + obj.mtxt; }
std::string pass_mpty_cref(mpty const& obj) { return "pass_cref:" + obj.mtxt; }
std::string pass_mpty_mref(mpty& obj)       { return "pass_mref:" + obj.mtxt; }
std::string pass_mpty_cptr(mpty const* obj) { return "pass_cptr:" + obj->mtxt; }
std::string pass_mpty_mptr(mpty* obj)       { return "pass_mptr:" + obj->mtxt; }
30

31
32
std::shared_ptr<mpty>       rtrn_mpty_shmp() { return std::shared_ptr<mpty      >(new mpty{"rtrn_shmp"}); }
std::shared_ptr<mpty const> rtrn_mpty_shcp() { return std::shared_ptr<mpty const>(new mpty{"rtrn_shcp"}); }
33

34
std::string pass_mpty_shmp(std::shared_ptr<mpty>       obj) { return "pass_shmp:" + obj->mtxt; }
35
std::string pass_mpty_shcp(std::shared_ptr<mpty const> obj) { return "pass_shcp:" + obj->mtxt; }
36

37
38
std::unique_ptr<mpty>       rtrn_mpty_uqmp() { return std::unique_ptr<mpty      >(new mpty{"rtrn_uqmp"}); }
std::unique_ptr<mpty const> rtrn_mpty_uqcp() { return std::unique_ptr<mpty const>(new mpty{"rtrn_uqmp"}); }
39

40
std::string pass_mpty_uqmp(std::unique_ptr<mpty      > obj) { return "pass_uqmp:" + obj->mtxt; }
41
std::string pass_mpty_uqcp(std::unique_ptr<mpty const> obj) { return "pass_uqcp:" + obj->mtxt; }
42

43
44
45
46
// clang-format on

} // namespace classh_wip
} // namespace pybind11_tests
47
48
49
50
51
52

namespace pybind11 {
namespace detail {

using namespace pybind11_tests::classh_wip;

53
54
55
template <typename T>
struct smart_holder_type_caster_load {
    bool load(handle src, bool /*convert*/) {
56
57
58
59
        if (!isinstance<T>(src))
            return false;
        auto inst  = reinterpret_cast<instance *>(src.ptr());
        auto v_h   = inst->get_value_and_holder(get_type_info(typeid(T)));
60
61
62
63
        smhldr_ptr = &v_h.holder<pybindit::memory::smart_holder>();
        return true;
    }

64
65
protected:
    pybindit::memory::smart_holder *smhldr_ptr = nullptr;
66
67
};

68
template <>
69
struct type_caster<mpty> : smart_holder_type_caster_load<mpty> {
70
71
72
73
74
    static constexpr auto name = _<mpty>();

    // static handle cast(mpty, ...)
    // is redundant (leads to ambiguous overloads).

75
    static handle cast(mpty && /*src*/, return_value_policy /*policy*/, handle /*parent*/) {
76
77
78
        return str("cast_rref").release();
    }

79
    static handle cast(mpty const & /*src*/, return_value_policy /*policy*/, handle /*parent*/) {
80
81
82
        return str("cast_cref").release();
    }

83
    static handle cast(mpty & /*src*/, return_value_policy /*policy*/, handle /*parent*/) {
84
85
86
        return str("cast_mref").release();
    }

87
    static handle cast(mpty const * /*src*/, return_value_policy /*policy*/, handle /*parent*/) {
88
89
90
        return str("cast_cptr").release();
    }

91
    static handle cast(mpty * /*src*/, return_value_policy /*policy*/, handle /*parent*/) {
92
93
94
95
96
        return str("cast_mptr").release();
    }

    template <typename T_>
    using cast_op_type = conditional_t<
97
98
        std::is_same<remove_reference_t<T_>, mpty const *>::value,
        mpty const *,
99
        conditional_t<
100
101
            std::is_same<remove_reference_t<T_>, mpty *>::value,
            mpty *,
102
            conditional_t<
103
104
105
106
107
108
109
                std::is_same<T_, mpty const &>::value,
                mpty const &,
                conditional_t<std::is_same<T_, mpty &>::value,
                              mpty &,
                              conditional_t<std::is_same<T_, mpty &&>::value, mpty &&, mpty>>>>>;

    // clang-format off
110

111
112
113
114
115
116
    operator mpty()        { return smhldr_ptr->lvalue_ref<mpty>(); }
    operator mpty&&() &&   { return smhldr_ptr->rvalue_ref<mpty>(); }
    operator mpty const&() { return smhldr_ptr->lvalue_ref<mpty>(); }
    operator mpty&()       { return smhldr_ptr->lvalue_ref<mpty>(); }
    operator mpty const*() { return smhldr_ptr->as_raw_ptr_unowned<mpty>(); }
    operator mpty*()       { return smhldr_ptr->as_raw_ptr_unowned<mpty>(); }
117
118

    // clang-format on
119
120
121
};

template <>
122
struct type_caster<std::shared_ptr<mpty>> : smart_holder_type_caster_load<mpty> {
123
124
    static constexpr auto name = _<std::shared_ptr<mpty>>();

125
    static handle cast(const std::shared_ptr<mpty> & /*src*/,
126
127
128
129
130
                       return_value_policy /*policy*/,
                       handle /*parent*/) {
        return str("cast_shmp").release();
    }

131
132
    template <typename>
    using cast_op_type = std::shared_ptr<mpty>;
133

134
    operator std::shared_ptr<mpty>() { return smhldr_ptr->as_shared_ptr<mpty>(); }
135
136
137
};

template <>
138
struct type_caster<std::shared_ptr<mpty const>> : smart_holder_type_caster_load<mpty> {
139
140
    static constexpr auto name = _<std::shared_ptr<mpty const>>();

141
    static handle cast(const std::shared_ptr<mpty const> & /*src*/,
142
143
144
145
146
                       return_value_policy /*policy*/,
                       handle /*parent*/) {
        return str("cast_shcp").release();
    }

147
148
    template <typename>
    using cast_op_type = std::shared_ptr<mpty const>;
149

150
    operator std::shared_ptr<mpty const>() { return smhldr_ptr->as_shared_ptr<mpty>(); }
151
152
153
};

template <>
154
struct type_caster<std::unique_ptr<mpty>> : smart_holder_type_caster_load<mpty> {
155
156
    static constexpr auto name = _<std::unique_ptr<mpty>>();

157
158
    static handle
    cast(std::unique_ptr<mpty> && /*src*/, return_value_policy /*policy*/, handle /*parent*/) {
159
160
161
        return str("cast_uqmp").release();
    }

162
163
    template <typename>
    using cast_op_type = std::unique_ptr<mpty>;
164

165
    operator std::unique_ptr<mpty>() { return smhldr_ptr->as_unique_ptr<mpty>(); }
166
167
168
};

template <>
169
struct type_caster<std::unique_ptr<mpty const>> : smart_holder_type_caster_load<mpty> {
170
171
    static constexpr auto name = _<std::unique_ptr<mpty const>>();

172
    static handle cast(std::unique_ptr<mpty const> && /*src*/,
173
174
175
176
177
                       return_value_policy /*policy*/,
                       handle /*parent*/) {
        return str("cast_uqcp").release();
    }

178
179
    template <typename>
    using cast_op_type = std::unique_ptr<mpty const>;
180

181
    operator std::unique_ptr<mpty const>() { return smhldr_ptr->as_unique_ptr<mpty>(); }
182
183
};

184
185
} // namespace detail
} // namespace pybind11
186
187
188
189
190
191
192

namespace pybind11_tests {
namespace classh_wip {

TEST_SUBMODULE(classh_wip, m) {
    namespace py = pybind11;

193
194
195
196
197
    py::classh<mpty>(m, "mpty").def(py::init<>()).def(py::init([](const std::string &mtxt) {
        mpty obj;
        obj.mtxt = mtxt;
        return obj;
    }));
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225

    m.def("rtrn_mpty_valu", rtrn_mpty_valu);
    m.def("rtrn_mpty_rref", rtrn_mpty_rref);
    m.def("rtrn_mpty_cref", rtrn_mpty_cref);
    m.def("rtrn_mpty_mref", rtrn_mpty_mref);
    m.def("rtrn_mpty_cptr", rtrn_mpty_cptr);
    m.def("rtrn_mpty_mptr", rtrn_mpty_mptr);

    m.def("pass_mpty_valu", pass_mpty_valu);
    m.def("pass_mpty_rref", pass_mpty_rref);
    m.def("pass_mpty_cref", pass_mpty_cref);
    m.def("pass_mpty_mref", pass_mpty_mref);
    m.def("pass_mpty_cptr", pass_mpty_cptr);
    m.def("pass_mpty_mptr", pass_mpty_mptr);

    m.def("rtrn_mpty_shmp", rtrn_mpty_shmp);
    m.def("rtrn_mpty_shcp", rtrn_mpty_shcp);

    m.def("pass_mpty_shmp", pass_mpty_shmp);
    m.def("pass_mpty_shcp", pass_mpty_shcp);

    m.def("rtrn_mpty_uqmp", rtrn_mpty_uqmp);
    m.def("rtrn_mpty_uqcp", rtrn_mpty_uqcp);

    m.def("pass_mpty_uqmp", pass_mpty_uqmp);
    m.def("pass_mpty_uqcp", pass_mpty_uqcp);
}

226
227
} // namespace classh_wip
} // namespace pybind11_tests