114299Sbbruce@ucdavis.edu/* 214299Sbbruce@ucdavis.edu tests/test_tagbased_polymorphic.cpp -- test of polymorphic_type_hook 314299Sbbruce@ucdavis.edu 414299Sbbruce@ucdavis.edu Copyright (c) 2018 Hudson River Trading LLC <opensource@hudson-trading.com> 514299Sbbruce@ucdavis.edu 614299Sbbruce@ucdavis.edu All rights reserved. Use of this source code is governed by a 714299Sbbruce@ucdavis.edu BSD-style license that can be found in the LICENSE file. 814299Sbbruce@ucdavis.edu*/ 914299Sbbruce@ucdavis.edu 1014299Sbbruce@ucdavis.edu#include "pybind11_tests.h" 1114299Sbbruce@ucdavis.edu#include <pybind11/stl.h> 1214299Sbbruce@ucdavis.edu 1314299Sbbruce@ucdavis.edustruct Animal 1414299Sbbruce@ucdavis.edu{ 1514299Sbbruce@ucdavis.edu enum class Kind { 1614299Sbbruce@ucdavis.edu Unknown = 0, 1714299Sbbruce@ucdavis.edu Dog = 100, Labrador, Chihuahua, LastDog = 199, 1814299Sbbruce@ucdavis.edu Cat = 200, Panther, LastCat = 299 1914299Sbbruce@ucdavis.edu }; 2014299Sbbruce@ucdavis.edu static const std::type_info* type_of_kind(Kind kind); 2114299Sbbruce@ucdavis.edu static std::string name_of_kind(Kind kind); 2214299Sbbruce@ucdavis.edu 2314299Sbbruce@ucdavis.edu const Kind kind; 2414299Sbbruce@ucdavis.edu const std::string name; 2514299Sbbruce@ucdavis.edu 2614299Sbbruce@ucdavis.edu protected: 2714299Sbbruce@ucdavis.edu Animal(const std::string& _name, Kind _kind) 2814299Sbbruce@ucdavis.edu : kind(_kind), name(_name) 2914299Sbbruce@ucdavis.edu {} 3014299Sbbruce@ucdavis.edu}; 3114299Sbbruce@ucdavis.edu 3214299Sbbruce@ucdavis.edustruct Dog : Animal 3314299Sbbruce@ucdavis.edu{ 3414299Sbbruce@ucdavis.edu Dog(const std::string& _name, Kind _kind = Kind::Dog) : Animal(_name, _kind) {} 3514299Sbbruce@ucdavis.edu std::string bark() const { return name_of_kind(kind) + " " + name + " goes " + sound; } 3614299Sbbruce@ucdavis.edu std::string sound = "WOOF!"; 3714299Sbbruce@ucdavis.edu}; 3814299Sbbruce@ucdavis.edu 3914299Sbbruce@ucdavis.edustruct Labrador : Dog 4014299Sbbruce@ucdavis.edu{ 4114299Sbbruce@ucdavis.edu Labrador(const std::string& _name, int _excitement = 9001) 4214299Sbbruce@ucdavis.edu : Dog(_name, Kind::Labrador), excitement(_excitement) {} 4314299Sbbruce@ucdavis.edu int excitement; 4414299Sbbruce@ucdavis.edu}; 4514299Sbbruce@ucdavis.edu 4614299Sbbruce@ucdavis.edustruct Chihuahua : Dog 4714299Sbbruce@ucdavis.edu{ 4814299Sbbruce@ucdavis.edu Chihuahua(const std::string& _name) : Dog(_name, Kind::Chihuahua) { sound = "iyiyiyiyiyi"; } 4914299Sbbruce@ucdavis.edu std::string bark() const { return Dog::bark() + " and runs in circles"; } 5014299Sbbruce@ucdavis.edu}; 5114299Sbbruce@ucdavis.edu 5214299Sbbruce@ucdavis.edustruct Cat : Animal 5314299Sbbruce@ucdavis.edu{ 5414299Sbbruce@ucdavis.edu Cat(const std::string& _name, Kind _kind = Kind::Cat) : Animal(_name, _kind) {} 5514299Sbbruce@ucdavis.edu std::string purr() const { return "mrowr"; } 5614299Sbbruce@ucdavis.edu}; 5714299Sbbruce@ucdavis.edu 5814299Sbbruce@ucdavis.edustruct Panther : Cat 5914299Sbbruce@ucdavis.edu{ 6014299Sbbruce@ucdavis.edu Panther(const std::string& _name) : Cat(_name, Kind::Panther) {} 6114299Sbbruce@ucdavis.edu std::string purr() const { return "mrrrRRRRRR"; } 6214299Sbbruce@ucdavis.edu}; 6314299Sbbruce@ucdavis.edu 6414299Sbbruce@ucdavis.edustd::vector<std::unique_ptr<Animal>> create_zoo() 6514299Sbbruce@ucdavis.edu{ 6614299Sbbruce@ucdavis.edu std::vector<std::unique_ptr<Animal>> ret; 6714299Sbbruce@ucdavis.edu ret.emplace_back(new Labrador("Fido", 15000)); 6814299Sbbruce@ucdavis.edu 6914299Sbbruce@ucdavis.edu // simulate some new type of Dog that the Python bindings 7014299Sbbruce@ucdavis.edu // haven't been updated for; it should still be considered 7114299Sbbruce@ucdavis.edu // a Dog, not just an Animal. 7214299Sbbruce@ucdavis.edu ret.emplace_back(new Dog("Ginger", Dog::Kind(150))); 7314299Sbbruce@ucdavis.edu 7414299Sbbruce@ucdavis.edu ret.emplace_back(new Chihuahua("Hertzl")); 7514299Sbbruce@ucdavis.edu ret.emplace_back(new Cat("Tiger", Cat::Kind::Cat)); 7614299Sbbruce@ucdavis.edu ret.emplace_back(new Panther("Leo")); 7714299Sbbruce@ucdavis.edu return ret; 7814299Sbbruce@ucdavis.edu} 7914299Sbbruce@ucdavis.edu 8014299Sbbruce@ucdavis.educonst std::type_info* Animal::type_of_kind(Kind kind) 8114299Sbbruce@ucdavis.edu{ 8214299Sbbruce@ucdavis.edu switch (kind) { 8314299Sbbruce@ucdavis.edu case Kind::Unknown: break; 8414299Sbbruce@ucdavis.edu 8514299Sbbruce@ucdavis.edu case Kind::Dog: break; 8614299Sbbruce@ucdavis.edu case Kind::Labrador: return &typeid(Labrador); 8714299Sbbruce@ucdavis.edu case Kind::Chihuahua: return &typeid(Chihuahua); 8814299Sbbruce@ucdavis.edu case Kind::LastDog: break; 8914299Sbbruce@ucdavis.edu 9014299Sbbruce@ucdavis.edu case Kind::Cat: break; 9114299Sbbruce@ucdavis.edu case Kind::Panther: return &typeid(Panther); 9214299Sbbruce@ucdavis.edu case Kind::LastCat: break; 9314299Sbbruce@ucdavis.edu } 9414299Sbbruce@ucdavis.edu 9514299Sbbruce@ucdavis.edu if (kind >= Kind::Dog && kind <= Kind::LastDog) return &typeid(Dog); 9614299Sbbruce@ucdavis.edu if (kind >= Kind::Cat && kind <= Kind::LastCat) return &typeid(Cat); 9714299Sbbruce@ucdavis.edu return nullptr; 9814299Sbbruce@ucdavis.edu} 9914299Sbbruce@ucdavis.edu 10014299Sbbruce@ucdavis.edustd::string Animal::name_of_kind(Kind kind) 10114299Sbbruce@ucdavis.edu{ 10214299Sbbruce@ucdavis.edu std::string raw_name = type_of_kind(kind)->name(); 10314299Sbbruce@ucdavis.edu py::detail::clean_type_id(raw_name); 10414299Sbbruce@ucdavis.edu return raw_name; 10514299Sbbruce@ucdavis.edu} 10614299Sbbruce@ucdavis.edu 10714299Sbbruce@ucdavis.edunamespace pybind11 { 10814299Sbbruce@ucdavis.edu template <typename itype> 10914299Sbbruce@ucdavis.edu struct polymorphic_type_hook<itype, detail::enable_if_t<std::is_base_of<Animal, itype>::value>> 11014299Sbbruce@ucdavis.edu { 11114299Sbbruce@ucdavis.edu static const void *get(const itype *src, const std::type_info*& type) 11214299Sbbruce@ucdavis.edu { type = src ? Animal::type_of_kind(src->kind) : nullptr; return src; } 11314299Sbbruce@ucdavis.edu }; 11414299Sbbruce@ucdavis.edu} 11514299Sbbruce@ucdavis.edu 11614299Sbbruce@ucdavis.eduTEST_SUBMODULE(tagbased_polymorphic, m) { 11714299Sbbruce@ucdavis.edu py::class_<Animal>(m, "Animal") 11814299Sbbruce@ucdavis.edu .def_readonly("name", &Animal::name); 11914299Sbbruce@ucdavis.edu py::class_<Dog, Animal>(m, "Dog") 12014299Sbbruce@ucdavis.edu .def(py::init<std::string>()) 12114299Sbbruce@ucdavis.edu .def_readwrite("sound", &Dog::sound) 12214299Sbbruce@ucdavis.edu .def("bark", &Dog::bark); 12314299Sbbruce@ucdavis.edu py::class_<Labrador, Dog>(m, "Labrador") 12414299Sbbruce@ucdavis.edu .def(py::init<std::string, int>(), "name"_a, "excitement"_a = 9001) 12514299Sbbruce@ucdavis.edu .def_readwrite("excitement", &Labrador::excitement); 12614299Sbbruce@ucdavis.edu py::class_<Chihuahua, Dog>(m, "Chihuahua") 12714299Sbbruce@ucdavis.edu .def(py::init<std::string>()) 12814299Sbbruce@ucdavis.edu .def("bark", &Chihuahua::bark); 12914299Sbbruce@ucdavis.edu py::class_<Cat, Animal>(m, "Cat") 13014299Sbbruce@ucdavis.edu .def(py::init<std::string>()) 13114299Sbbruce@ucdavis.edu .def("purr", &Cat::purr); 13214299Sbbruce@ucdavis.edu py::class_<Panther, Cat>(m, "Panther") 13314299Sbbruce@ucdavis.edu .def(py::init<std::string>()) 13414299Sbbruce@ucdavis.edu .def("purr", &Panther::purr); 13514299Sbbruce@ucdavis.edu m.def("create_zoo", &create_zoo); 13614299Sbbruce@ucdavis.edu}; 137