2 tests/test_class.cpp -- test py::class_ definitions and basic functionality
4 Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
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.
10 #include "pybind11_tests.h"
11 #include "constructor_stats.h"
12 #include "local_bindings.h"
13 #include <pybind11/stl.h>
16 # pragma warning(disable: 4324) // warning C4324: structure was padded due to alignment specifier
19 // test_brace_initialization
20 struct NoBraceInitialization
{
21 NoBraceInitialization(std::vector
<int> v
) : vec
{std::move(v
)} {}
23 NoBraceInitialization(std::initializer_list
<T
> l
) : vec(l
) {}
28 TEST_SUBMODULE(class_
, m
) {
30 struct NoConstructor
{
31 NoConstructor() = default;
32 NoConstructor(const NoConstructor
&) = default;
33 NoConstructor(NoConstructor
&&) = default;
34 static NoConstructor
*new_instance() {
35 auto *ptr
= new NoConstructor();
36 print_created(ptr
, "via new_instance");
39 ~NoConstructor() { print_destroyed(this); }
42 py::class_
<NoConstructor
>(m
, "NoConstructor")
43 .def_static("new_instance", &NoConstructor::new_instance
, "Return an instance");
48 Pet(const std::string
&name
, const std::string
&species
)
49 : m_name(name
), m_species(species
) {}
50 std::string
name() const { return m_name
; }
51 std::string
species() const { return m_species
; }
54 std::string m_species
;
57 class Dog
: public Pet
{
59 Dog(const std::string
&name
) : Pet(name
, "dog") {}
60 std::string
bark() const { return "Woof!"; }
63 class Rabbit
: public Pet
{
65 Rabbit(const std::string
&name
) : Pet(name
, "parrot") {}
68 class Hamster
: public Pet
{
70 Hamster(const std::string
&name
) : Pet(name
, "rodent") {}
73 class Chimera
: public Pet
{
74 Chimera() : Pet("Kimmy", "chimera") {}
77 py::class_
<Pet
> pet_class(m
, "Pet");
79 .def(py::init
<std::string
, std::string
>())
80 .def("name", &Pet::name
)
81 .def("species", &Pet::species
);
83 /* One way of declaring a subclass relationship: reference parent's class_ object */
84 py::class_
<Dog
>(m
, "Dog", pet_class
)
85 .def(py::init
<std::string
>());
87 /* Another way of declaring a subclass relationship: reference parent's C++ type */
88 py::class_
<Rabbit
, Pet
>(m
, "Rabbit")
89 .def(py::init
<std::string
>());
91 /* And another: list parent in class template arguments */
92 py::class_
<Hamster
, Pet
>(m
, "Hamster")
93 .def(py::init
<std::string
>());
95 /* Constructors are not inherited by default */
96 py::class_
<Chimera
, Pet
>(m
, "Chimera");
98 m
.def("pet_name_species", [](const Pet
&pet
) { return pet
.name() + " is a " + pet
.species(); });
99 m
.def("dog_bark", [](const Dog
&dog
) { return dog
.bark(); });
101 // test_automatic_upcasting
103 BaseClass() = default;
104 BaseClass(const BaseClass
&) = default;
105 BaseClass(BaseClass
&&) = default;
106 virtual ~BaseClass() {}
108 struct DerivedClass1
: BaseClass
{ };
109 struct DerivedClass2
: BaseClass
{ };
111 py::class_
<BaseClass
>(m
, "BaseClass").def(py::init
<>());
112 py::class_
<DerivedClass1
>(m
, "DerivedClass1").def(py::init
<>());
113 py::class_
<DerivedClass2
>(m
, "DerivedClass2").def(py::init
<>());
115 m
.def("return_class_1", []() -> BaseClass
* { return new DerivedClass1(); });
116 m
.def("return_class_2", []() -> BaseClass
* { return new DerivedClass2(); });
117 m
.def("return_class_n", [](int n
) -> BaseClass
* {
118 if (n
== 1) return new DerivedClass1();
119 if (n
== 2) return new DerivedClass2();
120 return new BaseClass();
122 m
.def("return_none", []() -> BaseClass
* { return nullptr; });
125 m
.def("check_instances", [](py::list l
) {
126 return py::make_tuple(
127 py::isinstance
<py::tuple
>(l
[0]),
128 py::isinstance
<py::dict
>(l
[1]),
129 py::isinstance
<Pet
>(l
[2]),
130 py::isinstance
<Pet
>(l
[3]),
131 py::isinstance
<Dog
>(l
[4]),
132 py::isinstance
<Rabbit
>(l
[5]),
133 py::isinstance
<UnregisteredType
>(l
[6])
137 // test_mismatched_holder
138 struct MismatchBase1
{ };
139 struct MismatchDerived1
: MismatchBase1
{ };
141 struct MismatchBase2
{ };
142 struct MismatchDerived2
: MismatchBase2
{ };
144 m
.def("mismatched_holder_1", []() {
145 auto mod
= py::module::import("__main__");
146 py::class_
<MismatchBase1
, std::shared_ptr
<MismatchBase1
>>(mod
, "MismatchBase1");
147 py::class_
<MismatchDerived1
, MismatchBase1
>(mod
, "MismatchDerived1");
149 m
.def("mismatched_holder_2", []() {
150 auto mod
= py::module::import("__main__");
151 py::class_
<MismatchBase2
>(mod
, "MismatchBase2");
152 py::class_
<MismatchDerived2
, std::shared_ptr
<MismatchDerived2
>,
153 MismatchBase2
>(mod
, "MismatchDerived2");
156 // test_override_static
157 // #511: problem with inheritance + overwritten def_static
159 static std::unique_ptr
<MyBase
> make() {
160 return std::unique_ptr
<MyBase
>(new MyBase());
164 struct MyDerived
: MyBase
{
165 static std::unique_ptr
<MyDerived
> make() {
166 return std::unique_ptr
<MyDerived
>(new MyDerived());
170 py::class_
<MyBase
>(m
, "MyBase")
171 .def_static("make", &MyBase::make
);
173 py::class_
<MyDerived
, MyBase
>(m
, "MyDerived")
174 .def_static("make", &MyDerived::make
)
175 .def_static("make2", &MyDerived::make
);
177 // test_implicit_conversion_life_support
178 struct ConvertibleFromUserType
{
181 ConvertibleFromUserType(UserType u
) : i(u
.value()) { }
184 py::class_
<ConvertibleFromUserType
>(m
, "AcceptsUserType")
185 .def(py::init
<UserType
>());
186 py::implicitly_convertible
<UserType
, ConvertibleFromUserType
>();
188 m
.def("implicitly_convert_argument", [](const ConvertibleFromUserType
&r
) { return r
.i
; });
189 m
.def("implicitly_convert_variable", [](py::object o
) {
190 // `o` is `UserType` and `r` is a reference to a temporary created by implicit
191 // conversion. This is valid when called inside a bound function because the temp
192 // object is attached to the same life support system as the arguments.
193 const auto &r
= o
.cast
<const ConvertibleFromUserType
&>();
196 m
.add_object("implicitly_convert_variable_fail", [&] {
197 auto f
= [](PyObject
*, PyObject
*args
) -> PyObject
* {
198 auto o
= py::reinterpret_borrow
<py::tuple
>(args
)[0];
199 try { // It should fail here because there is no life support.
200 o
.cast
<const ConvertibleFromUserType
&>();
201 } catch (const py::cast_error
&e
) {
202 return py::str(e
.what()).release().ptr();
204 return py::str().release().ptr();
207 auto def
= new PyMethodDef
{"f", f
, METH_VARARGS
, nullptr};
208 return py::reinterpret_steal
<py::object
>(PyCFunction_NewEx(def
, nullptr, m
.ptr()));
211 // test_operator_new_delete
214 static void *operator new(size_t s
) { py::print("A new", s
); return ::operator new(s
); }
215 static void *operator new(size_t s
, void *ptr
) { py::print("A placement-new", s
); return ptr
; }
216 static void operator delete(void *p
) { py::print("A delete"); return ::operator delete(p
); }
218 struct HasOpNewDelSize
{
220 static void *operator new(size_t s
) { py::print("B new", s
); return ::operator new(s
); }
221 static void *operator new(size_t s
, void *ptr
) { py::print("B placement-new", s
); return ptr
; }
222 static void operator delete(void *p
, size_t s
) { py::print("B delete", s
); return ::operator delete(p
); }
224 struct AliasedHasOpNewDelSize
{
226 static void *operator new(size_t s
) { py::print("C new", s
); return ::operator new(s
); }
227 static void *operator new(size_t s
, void *ptr
) { py::print("C placement-new", s
); return ptr
; }
228 static void operator delete(void *p
, size_t s
) { py::print("C delete", s
); return ::operator delete(p
); }
229 virtual ~AliasedHasOpNewDelSize() = default;
231 struct PyAliasedHasOpNewDelSize
: AliasedHasOpNewDelSize
{
232 PyAliasedHasOpNewDelSize() = default;
233 PyAliasedHasOpNewDelSize(int) { }
236 struct HasOpNewDelBoth
{
238 static void *operator new(size_t s
) { py::print("D new", s
); return ::operator new(s
); }
239 static void *operator new(size_t s
, void *ptr
) { py::print("D placement-new", s
); return ptr
; }
240 static void operator delete(void *p
) { py::print("D delete"); return ::operator delete(p
); }
241 static void operator delete(void *p
, size_t s
) { py::print("D wrong delete", s
); return ::operator delete(p
); }
243 py::class_
<HasOpNewDel
>(m
, "HasOpNewDel").def(py::init
<>());
244 py::class_
<HasOpNewDelSize
>(m
, "HasOpNewDelSize").def(py::init
<>());
245 py::class_
<HasOpNewDelBoth
>(m
, "HasOpNewDelBoth").def(py::init
<>());
246 py::class_
<AliasedHasOpNewDelSize
, PyAliasedHasOpNewDelSize
> aliased(m
, "AliasedHasOpNewDelSize");
247 aliased
.def(py::init
<>());
248 aliased
.attr("size_noalias") = py::int_(sizeof(AliasedHasOpNewDelSize
));
249 aliased
.attr("size_alias") = py::int_(sizeof(PyAliasedHasOpNewDelSize
));
251 // This test is actually part of test_local_bindings (test_duplicate_local), but we need a
252 // definition in a different compilation unit within the same module:
253 bind_local
<LocalExternal
, 17>(m
, "LocalExternal", py::module_local());
255 // test_bind_protected_functions
258 int foo() const { return value
; }
264 class PublicistA
: public ProtectedA
{
266 using ProtectedA::foo
;
269 py::class_
<ProtectedA
>(m
, "ProtectedA")
271 #if !defined(_MSC_VER) || _MSC_VER >= 1910
272 .def("foo", &PublicistA::foo
);
274 .def("foo", static_cast<int (ProtectedA::*)() const>(&PublicistA::foo
));
279 virtual ~ProtectedB() = default;
282 virtual int foo() const { return value
; }
288 class TrampolineB
: public ProtectedB
{
290 int foo() const override
{ PYBIND11_OVERLOAD(int, ProtectedB
, foo
, ); }
293 class PublicistB
: public ProtectedB
{
295 using ProtectedB::foo
;
298 py::class_
<ProtectedB
, TrampolineB
>(m
, "ProtectedB")
300 #if !defined(_MSC_VER) || _MSC_VER >= 1910
301 .def("foo", &PublicistB::foo
);
303 .def("foo", static_cast<int (ProtectedB::*)() const>(&PublicistB::foo
));
306 // test_brace_initialization
307 struct BraceInitialization
{
312 py::class_
<BraceInitialization
>(m
, "BraceInitialization")
313 .def(py::init
<int, const std::string
&>())
314 .def_readwrite("field1", &BraceInitialization::field1
)
315 .def_readwrite("field2", &BraceInitialization::field2
);
316 // We *don't* want to construct using braces when the given constructor argument maps to a
317 // constructor, because brace initialization could go to the wrong place (in particular when
318 // there is also an `initializer_list<T>`-accept constructor):
319 py::class_
<NoBraceInitialization
>(m
, "NoBraceInitialization")
320 .def(py::init
<std::vector
<int>>())
321 .def_readonly("vec", &NoBraceInitialization::vec
);
323 // test_reentrant_implicit_conversion_failure
324 // #1035: issue with runaway reentrant implicit conversion
325 struct BogusImplicitConversion
{
326 BogusImplicitConversion(const BogusImplicitConversion
&) { }
329 py::class_
<BogusImplicitConversion
>(m
, "BogusImplicitConversion")
330 .def(py::init
<const BogusImplicitConversion
&>());
332 py::implicitly_convertible
<int, BogusImplicitConversion
>();
335 // #1166: nested class docstring doesn't show nested name
336 // Also related: tests that __qualname__ is set properly
339 py::class_
<NestBase
> base(m
, "NestBase");
340 base
.def(py::init
<>());
341 py::class_
<Nested
>(base
, "Nested")
343 .def("fn", [](Nested
&, int, NestBase
&, Nested
&) {})
344 .def("fa", [](Nested
&, int, NestBase
&, Nested
&) {},
345 "a"_a
, "b"_a
, "c"_a
);
346 base
.def("g", [](NestBase
&, Nested
&) {});
347 base
.def("h", []() { return NestBase(); });
349 // test_error_after_conversion
350 // The second-pass path through dispatcher() previously didn't
351 // remember which overload was used, and would crash trying to
352 // generate a useful error message
354 struct NotRegistered
{};
355 struct StringWrapper
{ std::string str
; };
356 m
.def("test_error_after_conversions", [](int) {});
357 m
.def("test_error_after_conversions",
358 [](StringWrapper
) -> NotRegistered
{ return {}; });
359 py::class_
<StringWrapper
>(m
, "StringWrapper").def(py::init
<std::string
>());
360 py::implicitly_convertible
<std::string
, StringWrapper
>();
362 #if defined(PYBIND11_CPP17)
363 struct alignas(1024) Aligned
{
364 std::uintptr_t ptr() const { return (uintptr_t) this; }
366 py::class_
<Aligned
>(m
, "Aligned")
368 .def("ptr", &Aligned::ptr
);
372 template <int N
> class BreaksBase
{ public: virtual ~BreaksBase() = default; };
373 template <int N
> class BreaksTramp
: public BreaksBase
<N
> {};
374 // These should all compile just fine:
375 typedef py::class_
<BreaksBase
<1>, std::unique_ptr
<BreaksBase
<1>>, BreaksTramp
<1>> DoesntBreak1
;
376 typedef py::class_
<BreaksBase
<2>, BreaksTramp
<2>, std::unique_ptr
<BreaksBase
<2>>> DoesntBreak2
;
377 typedef py::class_
<BreaksBase
<3>, std::unique_ptr
<BreaksBase
<3>>> DoesntBreak3
;
378 typedef py::class_
<BreaksBase
<4>, BreaksTramp
<4>> DoesntBreak4
;
379 typedef py::class_
<BreaksBase
<5>> DoesntBreak5
;
380 typedef py::class_
<BreaksBase
<6>, std::shared_ptr
<BreaksBase
<6>>, BreaksTramp
<6>> DoesntBreak6
;
381 typedef py::class_
<BreaksBase
<7>, BreaksTramp
<7>, std::shared_ptr
<BreaksBase
<7>>> DoesntBreak7
;
382 typedef py::class_
<BreaksBase
<8>, std::shared_ptr
<BreaksBase
<8>>> DoesntBreak8
;
383 #define CHECK_BASE(N) static_assert(std::is_same<typename DoesntBreak##N::type, BreaksBase<N>>::value, \
384 "DoesntBreak" #N " has wrong type!")
385 CHECK_BASE(1); CHECK_BASE(2); CHECK_BASE(3); CHECK_BASE(4); CHECK_BASE(5); CHECK_BASE(6); CHECK_BASE(7); CHECK_BASE(8);
386 #define CHECK_ALIAS(N) static_assert(DoesntBreak##N::has_alias && std::is_same<typename DoesntBreak##N::type_alias, BreaksTramp<N>>::value, \
387 "DoesntBreak" #N " has wrong type_alias!")
388 #define CHECK_NOALIAS(N) static_assert(!DoesntBreak##N::has_alias && std::is_void<typename DoesntBreak##N::type_alias>::value, \
389 "DoesntBreak" #N " has type alias, but shouldn't!")
390 CHECK_ALIAS(1); CHECK_ALIAS(2); CHECK_NOALIAS(3); CHECK_ALIAS(4); CHECK_NOALIAS(5); CHECK_ALIAS(6); CHECK_ALIAS(7); CHECK_NOALIAS(8);
391 #define CHECK_HOLDER(N, TYPE) static_assert(std::is_same<typename DoesntBreak##N::holder_type, std::TYPE##_ptr<BreaksBase<N>>>::value, \
392 "DoesntBreak" #N " has wrong holder_type!")
393 CHECK_HOLDER(1, unique
); CHECK_HOLDER(2, unique
); CHECK_HOLDER(3, unique
); CHECK_HOLDER(4, unique
); CHECK_HOLDER(5, unique
);
394 CHECK_HOLDER(6, shared
); CHECK_HOLDER(7, shared
); CHECK_HOLDER(8, shared
);
396 // There's no nice way to test that these fail because they fail to compile; leave them here,
397 // though, so that they can be manually tested by uncommenting them (and seeing that compilation
400 // We have to actually look into the type: the typedef alone isn't enough to instantiate the type:
401 #define CHECK_BROKEN(N) static_assert(std::is_same<typename Breaks##N::type, BreaksBase<-N>>::value, \
402 "Breaks1 has wrong type!");
404 //// Two holder classes:
405 //typedef py::class_<BreaksBase<-1>, std::unique_ptr<BreaksBase<-1>>, std::unique_ptr<BreaksBase<-1>>> Breaks1;
408 //typedef py::class_<BreaksBase<-2>, BreaksTramp<-2>, BreaksTramp<-2>> Breaks2;
410 //// Holder + 2 aliases
411 //typedef py::class_<BreaksBase<-3>, std::unique_ptr<BreaksBase<-3>>, BreaksTramp<-3>, BreaksTramp<-3>> Breaks3;
413 //// Alias + 2 holders
414 //typedef py::class_<BreaksBase<-4>, std::unique_ptr<BreaksBase<-4>>, BreaksTramp<-4>, std::shared_ptr<BreaksBase<-4>>> Breaks4;
416 //// Invalid option (not a subclass or holder)
417 //typedef py::class_<BreaksBase<-5>, BreaksTramp<-4>> Breaks5;
419 //// Invalid option: multiple inheritance not supported:
420 //template <> struct BreaksBase<-8> : BreaksBase<-6>, BreaksBase<-7> {};
421 //typedef py::class_<BreaksBase<-8>, BreaksBase<-6>, BreaksBase<-7>> Breaks8;