blob: 914b7a8399f26f4ff5d399699d013c1ee9421a31 [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 Moldovan665e8802016-08-12 22:28:31 +020039std::string pet_name_species(const Pet &pet) {
40 return pet.name() + " is a " + pet.species();
Jason Rhinelanderb3f3d792016-07-18 16:43:18 -040041}
42
Dean Moldovan665e8802016-08-12 22:28:31 +020043std::string dog_bark(const Dog &dog) {
44 return dog.bark();
Jason Rhinelanderb3f3d792016-07-18 16:43:18 -040045}
46
47
48struct BaseClass { virtual ~BaseClass() {} };
49struct DerivedClass1 : BaseClass { };
50struct DerivedClass2 : BaseClass { };
51
Pim Schellartcc88aae2017-01-31 10:52:11 -050052struct MismatchBase1 { };
53struct MismatchDerived1 : MismatchBase1 { };
54
55struct MismatchBase2 { };
56struct MismatchDerived2 : MismatchBase2 { };
57
Jason Rhinelander52f4be82016-09-03 14:54:22 -040058test_initializer inheritance([](py::module &m) {
Jason Rhinelanderb3f3d792016-07-18 16:43:18 -040059 py::class_<Pet> pet_class(m, "Pet");
60 pet_class
61 .def(py::init<std::string, std::string>())
62 .def("name", &Pet::name)
63 .def("species", &Pet::species);
64
65 /* One way of declaring a subclass relationship: reference parent's class_ object */
66 py::class_<Dog>(m, "Dog", pet_class)
67 .def(py::init<std::string>());
68
69 /* Another way of declaring a subclass relationship: reference parent's C++ type */
Wenzel Jakob8e5dceb2016-09-11 20:00:40 +090070 py::class_<Rabbit, Pet>(m, "Rabbit")
Jason Rhinelanderb3f3d792016-07-18 16:43:18 -040071 .def(py::init<std::string>());
72
Jason Rhinelander6b52c832016-09-06 12:27:00 -040073 /* And another: list parent in class template arguments */
74 py::class_<Hamster, Pet>(m, "Hamster")
75 .def(py::init<std::string>());
76
Dean Moldovan665e8802016-08-12 22:28:31 +020077 m.def("pet_name_species", pet_name_species);
Jason Rhinelanderb3f3d792016-07-18 16:43:18 -040078 m.def("dog_bark", dog_bark);
79
80 py::class_<BaseClass>(m, "BaseClass").def(py::init<>());
81 py::class_<DerivedClass1>(m, "DerivedClass1").def(py::init<>());
82 py::class_<DerivedClass2>(m, "DerivedClass2").def(py::init<>());
83
84 m.def("return_class_1", []() -> BaseClass* { return new DerivedClass1(); });
85 m.def("return_class_2", []() -> BaseClass* { return new DerivedClass2(); });
Jason Rhinelander0e489772016-09-11 18:41:28 -040086 m.def("return_class_n", [](int n) -> BaseClass* {
87 if (n == 1) return new DerivedClass1();
88 if (n == 2) return new DerivedClass2();
89 return new BaseClass();
90 });
Jason Rhinelanderb3f3d792016-07-18 16:43:18 -040091 m.def("return_none", []() -> BaseClass* { return nullptr; });
Dean Moldovanb4498ef2016-10-23 14:50:08 +020092
93 m.def("test_isinstance", [](py::list l) {
94 struct Unregistered { }; // checks missing type_info code path
95
96 return py::make_tuple(
97 py::isinstance<py::tuple>(l[0]),
98 py::isinstance<py::dict>(l[1]),
99 py::isinstance<Pet>(l[2]),
100 py::isinstance<Pet>(l[3]),
101 py::isinstance<Dog>(l[4]),
102 py::isinstance<Rabbit>(l[5]),
103 py::isinstance<Unregistered>(l[6])
104 );
105 });
Pim Schellartcc88aae2017-01-31 10:52:11 -0500106
107 m.def("test_mismatched_holder_type_1", []() {
108 auto m = py::module::import("__main__");
109 py::class_<MismatchBase1, std::shared_ptr<MismatchBase1>>(m, "MismatchBase1");
110 py::class_<MismatchDerived1, MismatchBase1>(m, "MismatchDerived1");
111 });
112 m.def("test_mismatched_holder_type_2", []() {
113 auto m = py::module::import("__main__");
114 py::class_<MismatchBase2>(m, "MismatchBase2");
115 py::class_<MismatchDerived2, std::shared_ptr<MismatchDerived2>, MismatchBase2>(m, "MismatchDerived2");
116 });
Jason Rhinelander52f4be82016-09-03 14:54:22 -0400117});