blob: c19f58dc2eed5be23fc1522dd89df6e779303ee7 [file] [log] [blame]
Jason Rhinelanderb3f3d792016-07-18 16:43:18 -04001/*
Dean Moldovana0c1ccf2016-08-12 13:50:00 +02002 tests/test_inheritance.cpp -- inheritance, automatic upcasting for polymorphic types
Jason Rhinelanderb3f3d792016-07-18 16:43:18 -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
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020010#include "pybind11_tests.h"
Jason Rhinelanderb3f3d792016-07-18 16:43:18 -040011
12class Pet {
13public:
14 Pet(const std::string &name, const std::string &species)
15 : m_name(name), m_species(species) {}
16 std::string name() const { return m_name; }
17 std::string species() const { return m_species; }
18private:
19 std::string m_name;
20 std::string m_species;
21};
22
23class Dog : public Pet {
24public:
25 Dog(const std::string &name) : Pet(name, "dog") {}
Dean Moldovan665e8802016-08-12 22:28:31 +020026 std::string bark() const { return "Woof!"; }
Jason Rhinelanderb3f3d792016-07-18 16:43:18 -040027};
28
29class Rabbit : public Pet {
30public:
31 Rabbit(const std::string &name) : Pet(name, "parrot") {}
32};
33
Jason Rhinelander6b52c832016-09-06 12:27:00 -040034class Hamster : public Pet {
35public:
36 Hamster(const std::string &name) : Pet(name, "rodent") {}
37};
38
Dean Moldovan08cbe8d2017-02-15 21:10:25 +010039class Chimera : public Pet {
40 Chimera() : Pet("Kimmy", "chimera") {}
41};
42
Dean Moldovan665e8802016-08-12 22:28:31 +020043std::string pet_name_species(const Pet &pet) {
44 return pet.name() + " is a " + pet.species();
Jason Rhinelanderb3f3d792016-07-18 16:43:18 -040045}
46
Dean Moldovan665e8802016-08-12 22:28:31 +020047std::string dog_bark(const Dog &dog) {
48 return dog.bark();
Jason Rhinelanderb3f3d792016-07-18 16:43:18 -040049}
50
51
52struct BaseClass { virtual ~BaseClass() {} };
53struct DerivedClass1 : BaseClass { };
54struct DerivedClass2 : BaseClass { };
55
Pim Schellartcc88aae2017-01-31 10:52:11 -050056struct MismatchBase1 { };
57struct MismatchDerived1 : MismatchBase1 { };
58
59struct MismatchBase2 { };
60struct MismatchDerived2 : MismatchBase2 { };
61
Jason Rhinelander52f4be82016-09-03 14:54:22 -040062test_initializer inheritance([](py::module &m) {
Jason Rhinelanderb3f3d792016-07-18 16:43:18 -040063 py::class_<Pet> pet_class(m, "Pet");
64 pet_class
65 .def(py::init<std::string, std::string>())
66 .def("name", &Pet::name)
67 .def("species", &Pet::species);
68
69 /* One way of declaring a subclass relationship: reference parent's class_ object */
70 py::class_<Dog>(m, "Dog", pet_class)
71 .def(py::init<std::string>());
72
73 /* Another way of declaring a subclass relationship: reference parent's C++ type */
Wenzel Jakob8e5dceb2016-09-11 20:00:40 +090074 py::class_<Rabbit, Pet>(m, "Rabbit")
Jason Rhinelanderb3f3d792016-07-18 16:43:18 -040075 .def(py::init<std::string>());
76
Jason Rhinelander6b52c832016-09-06 12:27:00 -040077 /* And another: list parent in class template arguments */
78 py::class_<Hamster, Pet>(m, "Hamster")
79 .def(py::init<std::string>());
80
Dean Moldovan08cbe8d2017-02-15 21:10:25 +010081 py::class_<Chimera, Pet>(m, "Chimera");
82
Dean Moldovan665e8802016-08-12 22:28:31 +020083 m.def("pet_name_species", pet_name_species);
Jason Rhinelanderb3f3d792016-07-18 16:43:18 -040084 m.def("dog_bark", dog_bark);
85
86 py::class_<BaseClass>(m, "BaseClass").def(py::init<>());
87 py::class_<DerivedClass1>(m, "DerivedClass1").def(py::init<>());
88 py::class_<DerivedClass2>(m, "DerivedClass2").def(py::init<>());
89
90 m.def("return_class_1", []() -> BaseClass* { return new DerivedClass1(); });
91 m.def("return_class_2", []() -> BaseClass* { return new DerivedClass2(); });
Jason Rhinelander0e489772016-09-11 18:41:28 -040092 m.def("return_class_n", [](int n) -> BaseClass* {
93 if (n == 1) return new DerivedClass1();
94 if (n == 2) return new DerivedClass2();
95 return new BaseClass();
96 });
Jason Rhinelanderb3f3d792016-07-18 16:43:18 -040097 m.def("return_none", []() -> BaseClass* { return nullptr; });
Dean Moldovanb4498ef2016-10-23 14:50:08 +020098
99 m.def("test_isinstance", [](py::list l) {
100 struct Unregistered { }; // checks missing type_info code path
101
102 return py::make_tuple(
103 py::isinstance<py::tuple>(l[0]),
104 py::isinstance<py::dict>(l[1]),
105 py::isinstance<Pet>(l[2]),
106 py::isinstance<Pet>(l[3]),
107 py::isinstance<Dog>(l[4]),
108 py::isinstance<Rabbit>(l[5]),
109 py::isinstance<Unregistered>(l[6])
110 );
111 });
Pim Schellartcc88aae2017-01-31 10:52:11 -0500112
113 m.def("test_mismatched_holder_type_1", []() {
114 auto m = py::module::import("__main__");
115 py::class_<MismatchBase1, std::shared_ptr<MismatchBase1>>(m, "MismatchBase1");
116 py::class_<MismatchDerived1, MismatchBase1>(m, "MismatchDerived1");
117 });
118 m.def("test_mismatched_holder_type_2", []() {
119 auto m = py::module::import("__main__");
120 py::class_<MismatchBase2>(m, "MismatchBase2");
121 py::class_<MismatchDerived2, std::shared_ptr<MismatchDerived2>, MismatchBase2>(m, "MismatchDerived2");
122 });
Jason Rhinelander52f4be82016-09-03 14:54:22 -0400123});