test_tagbased_polymorphic.cpp
Go to the documentation of this file.
1 /*
2  tests/test_tagbased_polymorphic.cpp -- test of polymorphic_type_hook
3 
4  Copyright (c) 2018 Hudson River Trading LLC <opensource@hudson-trading.com>
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/stl.h>
11 
12 #include "pybind11_tests.h"
13 
14 struct Animal {
15  // Make this type also a "standard" polymorphic type, to confirm that
16  // specializing polymorphic_type_hook using enable_if_t still works
17  // (https://github.com/pybind/pybind11/pull/2016/).
18  virtual ~Animal() = default;
19 
20  // Enum for tag-based polymorphism.
21  enum class Kind {
22  Unknown = 0,
23  Dog = 100,
24  Labrador,
25  Chihuahua,
26  LastDog = 199,
27  Cat = 200,
28  Panther,
29  LastCat = 299
30  };
31  static const std::type_info *type_of_kind(Kind kind);
32  static std::string name_of_kind(Kind kind);
33 
34  const Kind kind;
35  const std::string name;
36 
37 protected:
38  Animal(const std::string &_name, Kind _kind) : kind(_kind), name(_name) {}
39 };
40 
41 struct Dog : Animal {
42  explicit Dog(const std::string &_name, Kind _kind = Kind::Dog) : Animal(_name, _kind) {}
43  std::string bark() const { return name_of_kind(kind) + " " + name + " goes " + sound; }
44  std::string sound = "WOOF!";
45 };
46 
47 struct Labrador : Dog {
48  explicit Labrador(const std::string &_name, int _excitement = 9001)
49  : Dog(_name, Kind::Labrador), excitement(_excitement) {}
51 };
52 
53 struct Chihuahua : Dog {
54  explicit Chihuahua(const std::string &_name) : Dog(_name, Kind::Chihuahua) {
55  sound = "iyiyiyiyiyi";
56  }
57  std::string bark() const { return Dog::bark() + " and runs in circles"; }
58 };
59 
60 struct Cat : Animal {
61  explicit Cat(const std::string &_name, Kind _kind = Kind::Cat) : Animal(_name, _kind) {}
62  std::string purr() const { return "mrowr"; }
63 };
64 
65 struct Panther : Cat {
66  explicit Panther(const std::string &_name) : Cat(_name, Kind::Panther) {}
67  std::string purr() const { return "mrrrRRRRRR"; }
68 };
69 
70 std::vector<std::unique_ptr<Animal>> create_zoo() {
71  std::vector<std::unique_ptr<Animal>> ret;
72  ret.emplace_back(new Labrador("Fido", 15000));
73 
74  // simulate some new type of Dog that the Python bindings
75  // haven't been updated for; it should still be considered
76  // a Dog, not just an Animal.
77  ret.emplace_back(new Dog("Ginger", Dog::Kind(150)));
78 
79  ret.emplace_back(new Chihuahua("Hertzl"));
80  ret.emplace_back(new Cat("Tiger", Cat::Kind::Cat));
81  ret.emplace_back(new Panther("Leo"));
82  return ret;
83 }
84 
85 const std::type_info *Animal::type_of_kind(Kind kind) {
86  switch (kind) {
87  case Kind::Unknown:
88  case Kind::Dog:
89  break;
90 
91  case Kind::Labrador:
92  return &typeid(Labrador);
93  case Kind::Chihuahua:
94  return &typeid(Chihuahua);
95 
96  case Kind::LastDog:
97  case Kind::Cat:
98  break;
99  case Kind::Panther:
100  return &typeid(Panther);
101  case Kind::LastCat:
102  break;
103  }
104 
105  if (kind >= Kind::Dog && kind <= Kind::LastDog) {
106  return &typeid(Dog);
107  }
108  if (kind >= Kind::Cat && kind <= Kind::LastCat) {
109  return &typeid(Cat);
110  }
111  return nullptr;
112 }
113 
114 std::string Animal::name_of_kind(Kind kind) {
115  std::string raw_name = type_of_kind(kind)->name();
116  py::detail::clean_type_id(raw_name);
117  return raw_name;
118 }
119 
120 namespace PYBIND11_NAMESPACE {
121 template <typename itype>
122 struct polymorphic_type_hook<itype, detail::enable_if_t<std::is_base_of<Animal, itype>::value>> {
123  static const void *get(const itype *src, const std::type_info *&type) {
124  type = src ? Animal::type_of_kind(src->kind) : nullptr;
125  return src;
126  }
127 };
128 } // namespace PYBIND11_NAMESPACE
129 
130 TEST_SUBMODULE(tagbased_polymorphic, m) {
131  py::class_<Animal>(m, "Animal").def_readonly("name", &Animal::name);
132  py::class_<Dog, Animal>(m, "Dog")
133  .def(py::init<std::string>())
134  .def_readwrite("sound", &Dog::sound)
135  .def("bark", &Dog::bark);
136  py::class_<Labrador, Dog>(m, "Labrador")
137  .def(py::init<std::string, int>(), "name"_a, "excitement"_a = 9001)
138  .def_readwrite("excitement", &Labrador::excitement);
139  py::class_<Chihuahua, Dog>(m, "Chihuahua")
140  .def(py::init<std::string>())
141  .def("bark", &Chihuahua::bark);
142  py::class_<Cat, Animal>(m, "Cat").def(py::init<std::string>()).def("purr", &Cat::purr);
143  py::class_<Panther, Cat>(m, "Panther")
144  .def(py::init<std::string>())
145  .def("purr", &Panther::purr);
146  m.def("create_zoo", &create_zoo);
147 };
name
Annotation for function names.
Definition: attr.h:51
gtsam.examples.DogLegOptimizerExample.type
type
Definition: DogLegOptimizerExample.py:111
Animal::Kind::LastCat
@ LastCat
Chihuahua::bark
std::string bark() const
Definition: test_tagbased_polymorphic.cpp:57
clean_type_id
PYBIND11_NOINLINE void clean_type_id(std::string &name)
Definition: typeid.h:35
Animal::Kind::Labrador
@ Labrador
Animal::Kind::LastDog
@ LastDog
ret
DenseIndex ret
Definition: level1_cplx_impl.h:44
Animal::Kind::Panther
@ Panther
stl.h
Labrador::Labrador
Labrador(const std::string &_name, int _excitement=9001)
Definition: test_tagbased_polymorphic.cpp:48
Cat::purr
std::string purr() const
Definition: test_tagbased_polymorphic.cpp:62
detail
Definition: testSerializationNonlinear.cpp:70
Animal::Kind
Kind
Definition: test_tagbased_polymorphic.cpp:21
Animal::name_of_kind
static std::string name_of_kind(Kind kind)
Definition: test_tagbased_polymorphic.cpp:114
Animal::Kind::Unknown
@ Unknown
Animal::Animal
Animal(const std::string &_name, Kind _kind)
Definition: test_tagbased_polymorphic.cpp:38
create_zoo
std::vector< std::unique_ptr< Animal > > create_zoo()
Definition: test_tagbased_polymorphic.cpp:70
polymorphic_type_hook
Definition: type_caster_base.h:1057
Panther
Definition: test_tagbased_polymorphic.cpp:65
PYBIND11_NAMESPACE::polymorphic_type_hook< itype, detail::enable_if_t< std::is_base_of< Animal, itype >::value > >::get
static const void * get(const itype *src, const std::type_info *&type)
Definition: test_tagbased_polymorphic.cpp:123
Animal::~Animal
virtual ~Animal()=default
Animal
Definition: test_tagbased_polymorphic.cpp:14
PYBIND11_NAMESPACE
Definition: test_custom_type_casters.cpp:24
m
Matrix3f m
Definition: AngleAxis_mimic_euler.cpp:1
Dog
Definition: test_tagbased_polymorphic.cpp:41
Animal::Kind::Dog
@ Dog
Labrador::excitement
int excitement
Definition: test_tagbased_polymorphic.cpp:50
Cat
Definition: test_tagbased_polymorphic.cpp:60
Chihuahua
Definition: test_tagbased_polymorphic.cpp:53
Dog::Dog
Dog(const std::string &_name, Kind _kind=Kind::Dog)
Definition: test_tagbased_polymorphic.cpp:42
Animal::type_of_kind
static const std::type_info * type_of_kind(Kind kind)
Definition: test_tagbased_polymorphic.cpp:85
pybind11_tests.h
Panther::Panther
Panther(const std::string &_name)
Definition: test_tagbased_polymorphic.cpp:66
Panther::purr
std::string purr() const
Definition: test_tagbased_polymorphic.cpp:67
Cat::Cat
Cat(const std::string &_name, Kind _kind=Kind::Cat)
Definition: test_tagbased_polymorphic.cpp:61
Animal::kind
const Kind kind
Definition: test_tagbased_polymorphic.cpp:34
Animal::Kind::Chihuahua
@ Chihuahua
Labrador
Definition: test_tagbased_polymorphic.cpp:47
Animal::Kind::Cat
@ Cat
TEST_SUBMODULE
TEST_SUBMODULE(tagbased_polymorphic, m)
Definition: test_tagbased_polymorphic.cpp:130
enable_if_t
typename std::enable_if< B, T >::type enable_if_t
from cpp_future import (convenient aliases from C++14/17)
Definition: wrap/pybind11/include/pybind11/detail/common.h:640
Animal::name
const std::string name
Definition: test_tagbased_polymorphic.cpp:35
Dog::bark
std::string bark() const
Definition: test_tagbased_polymorphic.cpp:43
Chihuahua::Chihuahua
Chihuahua(const std::string &_name)
Definition: test_tagbased_polymorphic.cpp:54
Dog::sound
std::string sound
Definition: test_tagbased_polymorphic.cpp:44


gtsam
Author(s):
autogenerated on Tue Jun 25 2024 03:05:31