blob: 670949f80469c4771410e572b4c74a27411f64cc [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 Moldovan83e328f2017-06-09 00:44:49 +0200232}
Jason Rhinelander5fffe202016-09-06 12:17:06 -0400233
Jason Rhinelander42e5ddc2017-06-12 21:48:36 -0400234template <int N> class BreaksBase { public: virtual ~BreaksBase() = default; };
Jason Rhinelander5fffe202016-09-06 12:17:06 -0400235template <int N> class BreaksTramp : public BreaksBase<N> {};
236// These should all compile just fine:
237typedef py::class_<BreaksBase<1>, std::unique_ptr<BreaksBase<1>>, BreaksTramp<1>> DoesntBreak1;
238typedef py::class_<BreaksBase<2>, BreaksTramp<2>, std::unique_ptr<BreaksBase<2>>> DoesntBreak2;
239typedef py::class_<BreaksBase<3>, std::unique_ptr<BreaksBase<3>>> DoesntBreak3;
240typedef py::class_<BreaksBase<4>, BreaksTramp<4>> DoesntBreak4;
241typedef py::class_<BreaksBase<5>> DoesntBreak5;
242typedef py::class_<BreaksBase<6>, std::shared_ptr<BreaksBase<6>>, BreaksTramp<6>> DoesntBreak6;
243typedef py::class_<BreaksBase<7>, BreaksTramp<7>, std::shared_ptr<BreaksBase<7>>> DoesntBreak7;
244typedef py::class_<BreaksBase<8>, std::shared_ptr<BreaksBase<8>>> DoesntBreak8;
245#define CHECK_BASE(N) static_assert(std::is_same<typename DoesntBreak##N::type, BreaksBase<N>>::value, \
246 "DoesntBreak" #N " has wrong type!")
247CHECK_BASE(1); CHECK_BASE(2); CHECK_BASE(3); CHECK_BASE(4); CHECK_BASE(5); CHECK_BASE(6); CHECK_BASE(7); CHECK_BASE(8);
248#define CHECK_ALIAS(N) static_assert(DoesntBreak##N::has_alias && std::is_same<typename DoesntBreak##N::type_alias, BreaksTramp<N>>::value, \
249 "DoesntBreak" #N " has wrong type_alias!")
250#define CHECK_NOALIAS(N) static_assert(!DoesntBreak##N::has_alias && std::is_void<typename DoesntBreak##N::type_alias>::value, \
251 "DoesntBreak" #N " has type alias, but shouldn't!")
252CHECK_ALIAS(1); CHECK_ALIAS(2); CHECK_NOALIAS(3); CHECK_ALIAS(4); CHECK_NOALIAS(5); CHECK_ALIAS(6); CHECK_ALIAS(7); CHECK_NOALIAS(8);
253#define CHECK_HOLDER(N, TYPE) static_assert(std::is_same<typename DoesntBreak##N::holder_type, std::TYPE##_ptr<BreaksBase<N>>>::value, \
254 "DoesntBreak" #N " has wrong holder_type!")
255CHECK_HOLDER(1, unique); CHECK_HOLDER(2, unique); CHECK_HOLDER(3, unique); CHECK_HOLDER(4, unique); CHECK_HOLDER(5, unique);
256CHECK_HOLDER(6, shared); CHECK_HOLDER(7, shared); CHECK_HOLDER(8, shared);
257
258// There's no nice way to test that these fail because they fail to compile; leave them here,
259// though, so that they can be manually tested by uncommenting them (and seeing that compilation
260// failures occurs).
261
262// We have to actually look into the type: the typedef alone isn't enough to instantiate the type:
263#define CHECK_BROKEN(N) static_assert(std::is_same<typename Breaks##N::type, BreaksBase<-N>>::value, \
264 "Breaks1 has wrong type!");
265
266//// Two holder classes:
267//typedef py::class_<BreaksBase<-1>, std::unique_ptr<BreaksBase<-1>>, std::unique_ptr<BreaksBase<-1>>> Breaks1;
268//CHECK_BROKEN(1);
269//// Two aliases:
270//typedef py::class_<BreaksBase<-2>, BreaksTramp<-2>, BreaksTramp<-2>> Breaks2;
271//CHECK_BROKEN(2);
272//// Holder + 2 aliases
273//typedef py::class_<BreaksBase<-3>, std::unique_ptr<BreaksBase<-3>>, BreaksTramp<-3>, BreaksTramp<-3>> Breaks3;
274//CHECK_BROKEN(3);
275//// Alias + 2 holders
276//typedef py::class_<BreaksBase<-4>, std::unique_ptr<BreaksBase<-4>>, BreaksTramp<-4>, std::shared_ptr<BreaksBase<-4>>> Breaks4;
277//CHECK_BROKEN(4);
278//// Invalid option (not a subclass or holder)
279//typedef py::class_<BreaksBase<-5>, BreaksTramp<-4>> Breaks5;
280//CHECK_BROKEN(5);
281//// Invalid option: multiple inheritance not supported:
282//template <> struct BreaksBase<-8> : BreaksBase<-6>, BreaksBase<-7> {};
283//typedef py::class_<BreaksBase<-8>, BreaksBase<-6>, BreaksBase<-7>> Breaks8;
284//CHECK_BROKEN(8);