@@ -150,6 +150,40 @@ TEST_SUBMODULE(class_, m) {
150
150
py::class_<MyDerived, MyBase>(m, " MyDerived" )
151
151
.def_static (" make" , &MyDerived::make)
152
152
.def_static (" make2" , &MyDerived::make);
153
+
154
+ // test_implicit_conversion_life_support
155
+ struct ConvertibleFromUserType {
156
+ int i;
157
+
158
+ ConvertibleFromUserType (UserType u) : i(u.value()) { }
159
+ };
160
+
161
+ py::class_<ConvertibleFromUserType>(m, " AcceptsUserType" )
162
+ .def (py::init<UserType>());
163
+ py::implicitly_convertible<UserType, ConvertibleFromUserType>();
164
+
165
+ m.def (" implicitly_convert_argument" , [](const ConvertibleFromUserType &r) { return r.i ; });
166
+ m.def (" implicitly_convert_variable" , [](py::object o) {
167
+ // `o` is `UserType` and `r` is a reference to a temporary created by implicit
168
+ // conversion. This is valid when called inside a bound function because the temp
169
+ // object is attached to the same life support system as the arguments.
170
+ auto r = o.cast <const ConvertibleFromUserType &>();
171
+ return r.i ;
172
+ });
173
+ m.add_object (" implicitly_convert_variable_fail" , [&] {
174
+ auto f = [](PyObject *, PyObject *args) -> PyObject * {
175
+ auto o = py::reinterpret_borrow<py::tuple>(args)[0 ];
176
+ try { // It should fail here because there is no life support.
177
+ o.cast <const ConvertibleFromUserType &>();
178
+ } catch (const py::cast_error &e) {
179
+ return py::str (e.what ()).release ().ptr ();
180
+ }
181
+ return py::str ().release ().ptr ();
182
+ };
183
+
184
+ auto def = new PyMethodDef{" f" , f, METH_VARARGS, nullptr };
185
+ return py::reinterpret_steal<py::object>(PyCFunction_NewEx (def, nullptr , m.ptr ()));
186
+ }());
153
187
}
154
188
155
189
template <int N> class BreaksBase {};
0 commit comments