blob: af7b0bfb081ce5ad2b55685b59f8b41cf0e8666c [file] [log] [blame]
Jason Rhinelander5fffe202016-09-06 12:17:06 -04001/*
Dean Moldovan83e328f2017-06-09 00:44:49 +02002 tests/test_class.cpp -- test py::class_ definitions and basic functionality
Jason Rhinelander5fffe202016-09-06 12:17:06 -04003
4 Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
5
6 All rights reserved. Use of this source code is governed by a
7 BSD-style license that can be found in the LICENSE file.
8*/
9
10#include "pybind11_tests.h"
Dean Moldovan83e328f2017-06-09 00:44:49 +020011#include "constructor_stats.h"
Jason Rhinelander7437c692017-07-28 22:03:44 -040012#include "local_bindings.h"
Jason Rhinelander5fffe202016-09-06 12:17:06 -040013
Dean Moldovan83e328f2017-06-09 00:44:49 +020014TEST_SUBMODULE(class_, m) {
15 // test_instance
16 struct NoConstructor {
17 static NoConstructor *new_instance() {
18 auto *ptr = new NoConstructor();
19 print_created(ptr, "via new_instance");
20 return ptr;
21 }
22 ~NoConstructor() { print_destroyed(this); }
23 };
24
25 py::class_<NoConstructor>(m, "NoConstructor")
26 .def_static("new_instance", &NoConstructor::new_instance, "Return an instance");
Dean Moldovan0bc272b2017-06-22 23:42:11 +020027
28 // test_inheritance
29 class Pet {
30 public:
31 Pet(const std::string &name, const std::string &species)
32 : m_name(name), m_species(species) {}
33 std::string name() const { return m_name; }
34 std::string species() const { return m_species; }
35 private:
36 std::string m_name;
37 std::string m_species;
38 };
39
40 class Dog : public Pet {
41 public:
42 Dog(const std::string &name) : Pet(name, "dog") {}
43 std::string bark() const { return "Woof!"; }
44 };
45
46 class Rabbit : public Pet {
47 public:
48 Rabbit(const std::string &name) : Pet(name, "parrot") {}
49 };
50
51 class Hamster : public Pet {
52 public:
53 Hamster(const std::string &name) : Pet(name, "rodent") {}
54 };
55
56 class Chimera : public Pet {
57 Chimera() : Pet("Kimmy", "chimera") {}
58 };
59
60 py::class_<Pet> pet_class(m, "Pet");
61 pet_class
62 .def(py::init<std::string, std::string>())
63 .def("name", &Pet::name)
64 .def("species", &Pet::species);
65
66 /* One way of declaring a subclass relationship: reference parent's class_ object */
67 py::class_<Dog>(m, "Dog", pet_class)
68 .def(py::init<std::string>());
69
70 /* Another way of declaring a subclass relationship: reference parent's C++ type */
71 py::class_<Rabbit, Pet>(m, "Rabbit")
72 .def(py::init<std::string>());
73
74 /* And another: list parent in class template arguments */
75 py::class_<Hamster, Pet>(m, "Hamster")
76 .def(py::init<std::string>());
77
78 /* Constructors are not inherited by default */
79 py::class_<Chimera, Pet>(m, "Chimera");
80
81 m.def("pet_name_species", [](const Pet &pet) { return pet.name() + " is a " + pet.species(); });
82 m.def("dog_bark", [](const Dog &dog) { return dog.bark(); });
83
84 // test_automatic_upcasting
85 struct BaseClass { virtual ~BaseClass() {} };
86 struct DerivedClass1 : BaseClass { };
87 struct DerivedClass2 : BaseClass { };
88
89 py::class_<BaseClass>(m, "BaseClass").def(py::init<>());
90 py::class_<DerivedClass1>(m, "DerivedClass1").def(py::init<>());
91 py::class_<DerivedClass2>(m, "DerivedClass2").def(py::init<>());
92
93 m.def("return_class_1", []() -> BaseClass* { return new DerivedClass1(); });
94 m.def("return_class_2", []() -> BaseClass* { return new DerivedClass2(); });
95 m.def("return_class_n", [](int n) -> BaseClass* {
96 if (n == 1) return new DerivedClass1();
97 if (n == 2) return new DerivedClass2();
98 return new BaseClass();
99 });
100 m.def("return_none", []() -> BaseClass* { return nullptr; });
101
102 // test_isinstance
103 m.def("check_instances", [](py::list l) {
104 return py::make_tuple(
105 py::isinstance<py::tuple>(l[0]),
106 py::isinstance<py::dict>(l[1]),
107 py::isinstance<Pet>(l[2]),
108 py::isinstance<Pet>(l[3]),
109 py::isinstance<Dog>(l[4]),
110 py::isinstance<Rabbit>(l[5]),
111 py::isinstance<UnregisteredType>(l[6])
112 );
113 });
114
115 // test_mismatched_holder
116 struct MismatchBase1 { };
117 struct MismatchDerived1 : MismatchBase1 { };
118
119 struct MismatchBase2 { };
120 struct MismatchDerived2 : MismatchBase2 { };
121
122 m.def("mismatched_holder_1", []() {
123 auto mod = py::module::import("__main__");
124 py::class_<MismatchBase1, std::shared_ptr<MismatchBase1>>(mod, "MismatchBase1");
125 py::class_<MismatchDerived1, MismatchBase1>(mod, "MismatchDerived1");
126 });
127 m.def("mismatched_holder_2", []() {
128 auto mod = py::module::import("__main__");
129 py::class_<MismatchBase2>(mod, "MismatchBase2");
130 py::class_<MismatchDerived2, std::shared_ptr<MismatchDerived2>,
131 MismatchBase2>(mod, "MismatchDerived2");
132 });
133
134 // test_override_static
135 // #511: problem with inheritance + overwritten def_static
136 struct MyBase {
137 static std::unique_ptr<MyBase> make() {
138 return std::unique_ptr<MyBase>(new MyBase());
139 }
140 };
141
142 struct MyDerived : MyBase {
143 static std::unique_ptr<MyDerived> make() {
144 return std::unique_ptr<MyDerived>(new MyDerived());
145 }
146 };
147
148 py::class_<MyBase>(m, "MyBase")
149 .def_static("make", &MyBase::make);
150
151 py::class_<MyDerived, MyBase>(m, "MyDerived")
152 .def_static("make", &MyDerived::make)
153 .def_static("make2", &MyDerived::make);
Dean Moldovanaf2dda32017-06-26 20:34:06 +0200154
155 // test_implicit_conversion_life_support
156 struct ConvertibleFromUserType {
157 int i;
158
159 ConvertibleFromUserType(UserType u) : i(u.value()) { }
160 };
161
162 py::class_<ConvertibleFromUserType>(m, "AcceptsUserType")
163 .def(py::init<UserType>());
164 py::implicitly_convertible<UserType, ConvertibleFromUserType>();
165
166 m.def("implicitly_convert_argument", [](const ConvertibleFromUserType &r) { return r.i; });
167 m.def("implicitly_convert_variable", [](py::object o) {
168 // `o` is `UserType` and `r` is a reference to a temporary created by implicit
169 // conversion. This is valid when called inside a bound function because the temp
170 // object is attached to the same life support system as the arguments.
171 const auto &r = o.cast<const ConvertibleFromUserType &>();
172 return r.i;
173 });
174 m.add_object("implicitly_convert_variable_fail", [&] {
175 auto f = [](PyObject *, PyObject *args) -> PyObject * {
176 auto o = py::reinterpret_borrow<py::tuple>(args)[0];
177 try { // It should fail here because there is no life support.
178 o.cast<const ConvertibleFromUserType &>();
179 } catch (const py::cast_error &e) {
180 return py::str(e.what()).release().ptr();
181 }
182 return py::str().release().ptr();
183 };
184
185 auto def = new PyMethodDef{"f", f, METH_VARARGS, nullptr};
186 return py::reinterpret_steal<py::object>(PyCFunction_NewEx(def, nullptr, m.ptr()));
187 }());
Jason Rhinelandera03408c2017-07-23 00:32:58 -0400188
189 // test_operator_new_delete
190 struct HasOpNewDel {
191 std::uint64_t i;
192 static void *operator new(size_t s) { py::print("A new", s); return ::operator new(s); }
193 static void *operator new(size_t s, void *ptr) { py::print("A placement-new", s); return ptr; }
194 static void operator delete(void *p) { py::print("A delete"); return ::operator delete(p); }
195 };
196 struct HasOpNewDelSize {
197 std::uint32_t i;
198 static void *operator new(size_t s) { py::print("B new", s); return ::operator new(s); }
199 static void *operator new(size_t s, void *ptr) { py::print("B placement-new", s); return ptr; }
200 static void operator delete(void *p, size_t s) { py::print("B delete", s); return ::operator delete(p); }
201 };
202 struct AliasedHasOpNewDelSize {
203 std::uint64_t i;
204 static void *operator new(size_t s) { py::print("C new", s); return ::operator new(s); }
205 static void *operator new(size_t s, void *ptr) { py::print("C placement-new", s); return ptr; }
206 static void operator delete(void *p, size_t s) { py::print("C delete", s); return ::operator delete(p); }
207 virtual ~AliasedHasOpNewDelSize() = default;
208 };
209 struct PyAliasedHasOpNewDelSize : AliasedHasOpNewDelSize {
210 PyAliasedHasOpNewDelSize() = default;
211 PyAliasedHasOpNewDelSize(int) { }
212 std::uint64_t j;
213 };
214 struct HasOpNewDelBoth {
215 std::uint32_t i[8];
216 static void *operator new(size_t s) { py::print("D new", s); return ::operator new(s); }
217 static void *operator new(size_t s, void *ptr) { py::print("D placement-new", s); return ptr; }
218 static void operator delete(void *p) { py::print("D delete"); return ::operator delete(p); }
219 static void operator delete(void *p, size_t s) { py::print("D wrong delete", s); return ::operator delete(p); }
220 };
221 py::class_<HasOpNewDel>(m, "HasOpNewDel").def(py::init<>());
222 py::class_<HasOpNewDelSize>(m, "HasOpNewDelSize").def(py::init<>());
223 py::class_<HasOpNewDelBoth>(m, "HasOpNewDelBoth").def(py::init<>());
224 py::class_<AliasedHasOpNewDelSize, PyAliasedHasOpNewDelSize> aliased(m, "AliasedHasOpNewDelSize");
225 aliased.def(py::init<>());
226 aliased.attr("size_noalias") = py::int_(sizeof(AliasedHasOpNewDelSize));
227 aliased.attr("size_alias") = py::int_(sizeof(PyAliasedHasOpNewDelSize));
Jason Rhinelander7437c692017-07-28 22:03:44 -0400228
229 // This test is actually part of test_local_bindings (test_duplicate_local), but we need a
230 // definition in a different compilation unit within the same module:
231 bind_local<LocalExternal, 17>(m, "LocalExternal", py::module_local());
Dean Moldovan234f7c32017-08-17 17:03:46 +0200232
233 // test_bind_protected_functions
234 class ProtectedA {
235 protected:
236 int foo() const { return value; }
237
238 private:
239 int value = 42;
240 };
241
242 class PublicistA : public ProtectedA {
243 public:
244 using ProtectedA::foo;
245 };
246
247 py::class_<ProtectedA>(m, "ProtectedA")
248 .def(py::init<>())
249#if !defined(_MSC_VER) || _MSC_VER >= 1910
250 .def("foo", &PublicistA::foo);
251#else
252 .def("foo", static_cast<int (ProtectedA::*)() const>(&PublicistA::foo));
253#endif
254
255 class ProtectedB {
256 public:
257 virtual ~ProtectedB() = default;
258
259 protected:
260 virtual int foo() const { return value; }
261
262 private:
263 int value = 42;
264 };
265
266 class TrampolineB : public ProtectedB {
267 public:
268 int foo() const override { PYBIND11_OVERLOAD(int, ProtectedB, foo, ); }
269 };
270
271 class PublicistB : public ProtectedB {
272 public:
273 using ProtectedB::foo;
274 };
275
276 py::class_<ProtectedB, TrampolineB>(m, "ProtectedB")
277 .def(py::init<>())
278#if !defined(_MSC_VER) || _MSC_VER >= 1910
279 .def("foo", &PublicistB::foo);
280#else
281 .def("foo", static_cast<int (ProtectedB::*)() const>(&PublicistB::foo));
282#endif
Dean Moldovan83e328f2017-06-09 00:44:49 +0200283}
Jason Rhinelander5fffe202016-09-06 12:17:06 -0400284
Jason Rhinelander42e5ddc2017-06-12 21:48:36 -0400285template <int N> class BreaksBase { public: virtual ~BreaksBase() = default; };
Jason Rhinelander5fffe202016-09-06 12:17:06 -0400286template <int N> class BreaksTramp : public BreaksBase<N> {};
287// These should all compile just fine:
288typedef py::class_<BreaksBase<1>, std::unique_ptr<BreaksBase<1>>, BreaksTramp<1>> DoesntBreak1;
289typedef py::class_<BreaksBase<2>, BreaksTramp<2>, std::unique_ptr<BreaksBase<2>>> DoesntBreak2;
290typedef py::class_<BreaksBase<3>, std::unique_ptr<BreaksBase<3>>> DoesntBreak3;
291typedef py::class_<BreaksBase<4>, BreaksTramp<4>> DoesntBreak4;
292typedef py::class_<BreaksBase<5>> DoesntBreak5;
293typedef py::class_<BreaksBase<6>, std::shared_ptr<BreaksBase<6>>, BreaksTramp<6>> DoesntBreak6;
294typedef py::class_<BreaksBase<7>, BreaksTramp<7>, std::shared_ptr<BreaksBase<7>>> DoesntBreak7;
295typedef py::class_<BreaksBase<8>, std::shared_ptr<BreaksBase<8>>> DoesntBreak8;
296#define CHECK_BASE(N) static_assert(std::is_same<typename DoesntBreak##N::type, BreaksBase<N>>::value, \
297 "DoesntBreak" #N " has wrong type!")
298CHECK_BASE(1); CHECK_BASE(2); CHECK_BASE(3); CHECK_BASE(4); CHECK_BASE(5); CHECK_BASE(6); CHECK_BASE(7); CHECK_BASE(8);
299#define CHECK_ALIAS(N) static_assert(DoesntBreak##N::has_alias && std::is_same<typename DoesntBreak##N::type_alias, BreaksTramp<N>>::value, \
300 "DoesntBreak" #N " has wrong type_alias!")
301#define CHECK_NOALIAS(N) static_assert(!DoesntBreak##N::has_alias && std::is_void<typename DoesntBreak##N::type_alias>::value, \
302 "DoesntBreak" #N " has type alias, but shouldn't!")
303CHECK_ALIAS(1); CHECK_ALIAS(2); CHECK_NOALIAS(3); CHECK_ALIAS(4); CHECK_NOALIAS(5); CHECK_ALIAS(6); CHECK_ALIAS(7); CHECK_NOALIAS(8);
304#define CHECK_HOLDER(N, TYPE) static_assert(std::is_same<typename DoesntBreak##N::holder_type, std::TYPE##_ptr<BreaksBase<N>>>::value, \
305 "DoesntBreak" #N " has wrong holder_type!")
306CHECK_HOLDER(1, unique); CHECK_HOLDER(2, unique); CHECK_HOLDER(3, unique); CHECK_HOLDER(4, unique); CHECK_HOLDER(5, unique);
307CHECK_HOLDER(6, shared); CHECK_HOLDER(7, shared); CHECK_HOLDER(8, shared);
308
309// There's no nice way to test that these fail because they fail to compile; leave them here,
310// though, so that they can be manually tested by uncommenting them (and seeing that compilation
311// failures occurs).
312
313// We have to actually look into the type: the typedef alone isn't enough to instantiate the type:
314#define CHECK_BROKEN(N) static_assert(std::is_same<typename Breaks##N::type, BreaksBase<-N>>::value, \
315 "Breaks1 has wrong type!");
316
317//// Two holder classes:
318//typedef py::class_<BreaksBase<-1>, std::unique_ptr<BreaksBase<-1>>, std::unique_ptr<BreaksBase<-1>>> Breaks1;
319//CHECK_BROKEN(1);
320//// Two aliases:
321//typedef py::class_<BreaksBase<-2>, BreaksTramp<-2>, BreaksTramp<-2>> Breaks2;
322//CHECK_BROKEN(2);
323//// Holder + 2 aliases
324//typedef py::class_<BreaksBase<-3>, std::unique_ptr<BreaksBase<-3>>, BreaksTramp<-3>, BreaksTramp<-3>> Breaks3;
325//CHECK_BROKEN(3);
326//// Alias + 2 holders
327//typedef py::class_<BreaksBase<-4>, std::unique_ptr<BreaksBase<-4>>, BreaksTramp<-4>, std::shared_ptr<BreaksBase<-4>>> Breaks4;
328//CHECK_BROKEN(4);
329//// Invalid option (not a subclass or holder)
330//typedef py::class_<BreaksBase<-5>, BreaksTramp<-4>> Breaks5;
331//CHECK_BROKEN(5);
332//// Invalid option: multiple inheritance not supported:
333//template <> struct BreaksBase<-8> : BreaksBase<-6>, BreaksBase<-7> {};
334//typedef py::class_<BreaksBase<-8>, BreaksBase<-6>, BreaksBase<-7>> Breaks8;
335//CHECK_BROKEN(8);