|
Packit |
534379 |
/*
|
|
Packit |
534379 |
tests/test_tagbased_polymorphic.cpp -- test of polymorphic_type_hook
|
|
Packit |
534379 |
|
|
Packit |
534379 |
Copyright (c) 2018 Hudson River Trading LLC <opensource@hudson-trading.com>
|
|
Packit |
534379 |
|
|
Packit |
534379 |
All rights reserved. Use of this source code is governed by a
|
|
Packit |
534379 |
BSD-style license that can be found in the LICENSE file.
|
|
Packit |
534379 |
*/
|
|
Packit |
534379 |
|
|
Packit |
534379 |
#include "pybind11_tests.h"
|
|
Packit |
534379 |
#include <pybind11/stl.h>
|
|
Packit |
534379 |
|
|
Packit |
534379 |
struct Animal
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
enum class Kind {
|
|
Packit |
534379 |
Unknown = 0,
|
|
Packit |
534379 |
Dog = 100, Labrador, Chihuahua, LastDog = 199,
|
|
Packit |
534379 |
Cat = 200, Panther, LastCat = 299
|
|
Packit |
534379 |
};
|
|
Packit |
534379 |
static const std::type_info* type_of_kind(Kind kind);
|
|
Packit |
534379 |
static std::string name_of_kind(Kind kind);
|
|
Packit |
534379 |
|
|
Packit |
534379 |
const Kind kind;
|
|
Packit |
534379 |
const std::string name;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
protected:
|
|
Packit |
534379 |
Animal(const std::string& _name, Kind _kind)
|
|
Packit |
534379 |
: kind(_kind), name(_name)
|
|
Packit |
534379 |
{}
|
|
Packit |
534379 |
};
|
|
Packit |
534379 |
|
|
Packit |
534379 |
struct Dog : Animal
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
Dog(const std::string& _name, Kind _kind = Kind::Dog) : Animal(_name, _kind) {}
|
|
Packit |
534379 |
std::string bark() const { return name_of_kind(kind) + " " + name + " goes " + sound; }
|
|
Packit |
534379 |
std::string sound = "WOOF!";
|
|
Packit |
534379 |
};
|
|
Packit |
534379 |
|
|
Packit |
534379 |
struct Labrador : Dog
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
Labrador(const std::string& _name, int _excitement = 9001)
|
|
Packit |
534379 |
: Dog(_name, Kind::Labrador), excitement(_excitement) {}
|
|
Packit |
534379 |
int excitement;
|
|
Packit |
534379 |
};
|
|
Packit |
534379 |
|
|
Packit |
534379 |
struct Chihuahua : Dog
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
Chihuahua(const std::string& _name) : Dog(_name, Kind::Chihuahua) { sound = "iyiyiyiyiyi"; }
|
|
Packit |
534379 |
std::string bark() const { return Dog::bark() + " and runs in circles"; }
|
|
Packit |
534379 |
};
|
|
Packit |
534379 |
|
|
Packit |
534379 |
struct Cat : Animal
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
Cat(const std::string& _name, Kind _kind = Kind::Cat) : Animal(_name, _kind) {}
|
|
Packit |
534379 |
std::string purr() const { return "mrowr"; }
|
|
Packit |
534379 |
};
|
|
Packit |
534379 |
|
|
Packit |
534379 |
struct Panther : Cat
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
Panther(const std::string& _name) : Cat(_name, Kind::Panther) {}
|
|
Packit |
534379 |
std::string purr() const { return "mrrrRRRRRR"; }
|
|
Packit |
534379 |
};
|
|
Packit |
534379 |
|
|
Packit |
534379 |
std::vector<std::unique_ptr<Animal>> create_zoo()
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
std::vector<std::unique_ptr<Animal>> ret;
|
|
Packit |
534379 |
ret.emplace_back(new Labrador("Fido", 15000));
|
|
Packit |
534379 |
|
|
Packit |
534379 |
// simulate some new type of Dog that the Python bindings
|
|
Packit |
534379 |
// haven't been updated for; it should still be considered
|
|
Packit |
534379 |
// a Dog, not just an Animal.
|
|
Packit |
534379 |
ret.emplace_back(new Dog("Ginger", Dog::Kind(150)));
|
|
Packit |
534379 |
|
|
Packit |
534379 |
ret.emplace_back(new Chihuahua("Hertzl"));
|
|
Packit |
534379 |
ret.emplace_back(new Cat("Tiger", Cat::Kind::Cat));
|
|
Packit |
534379 |
ret.emplace_back(new Panther("Leo"));
|
|
Packit |
534379 |
return ret;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
const std::type_info* Animal::type_of_kind(Kind kind)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
switch (kind) {
|
|
Packit |
534379 |
case Kind::Unknown: break;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
case Kind::Dog: break;
|
|
Packit |
534379 |
case Kind::Labrador: return &typeid(Labrador);
|
|
Packit |
534379 |
case Kind::Chihuahua: return &typeid(Chihuahua);
|
|
Packit |
534379 |
case Kind::LastDog: break;
|
|
Packit |
534379 |
|
|
Packit |
534379 |
case Kind::Cat: break;
|
|
Packit |
534379 |
case Kind::Panther: return &typeid(Panther);
|
|
Packit |
534379 |
case Kind::LastCat: break;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
if (kind >= Kind::Dog && kind <= Kind::LastDog) return &typeid(Dog);
|
|
Packit |
534379 |
if (kind >= Kind::Cat && kind <= Kind::LastCat) return &typeid(Cat);
|
|
Packit |
534379 |
return nullptr;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
std::string Animal::name_of_kind(Kind kind)
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
std::string raw_name = type_of_kind(kind)->name();
|
|
Packit |
534379 |
py::detail::clean_type_id(raw_name);
|
|
Packit |
534379 |
return raw_name;
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
namespace pybind11 {
|
|
Packit |
534379 |
template <typename itype>
|
|
Packit |
534379 |
struct polymorphic_type_hook<itype, detail::enable_if_t<std::is_base_of<Animal, itype>::value>>
|
|
Packit |
534379 |
{
|
|
Packit |
534379 |
static const void *get(const itype *src, const std::type_info*& type)
|
|
Packit |
534379 |
{ type = src ? Animal::type_of_kind(src->kind) : nullptr; return src; }
|
|
Packit |
534379 |
};
|
|
Packit |
534379 |
}
|
|
Packit |
534379 |
|
|
Packit |
534379 |
TEST_SUBMODULE(tagbased_polymorphic, m) {
|
|
Packit |
534379 |
py::class_<Animal>(m, "Animal")
|
|
Packit |
534379 |
.def_readonly("name", &Animal::name);
|
|
Packit |
534379 |
py::class_<Dog, Animal>(m, "Dog")
|
|
Packit |
534379 |
.def(py::init<std::string>())
|
|
Packit |
534379 |
.def_readwrite("sound", &Dog::sound)
|
|
Packit |
534379 |
.def("bark", &Dog::bark);
|
|
Packit |
534379 |
py::class_<Labrador, Dog>(m, "Labrador")
|
|
Packit |
534379 |
.def(py::init<std::string, int>(), "name"_a, "excitement"_a = 9001)
|
|
Packit |
534379 |
.def_readwrite("excitement", &Labrador::excitement);
|
|
Packit |
534379 |
py::class_<Chihuahua, Dog>(m, "Chihuahua")
|
|
Packit |
534379 |
.def(py::init<std::string>())
|
|
Packit |
534379 |
.def("bark", &Chihuahua::bark);
|
|
Packit |
534379 |
py::class_<Cat, Animal>(m, "Cat")
|
|
Packit |
534379 |
.def(py::init<std::string>())
|
|
Packit |
534379 |
.def("purr", &Cat::purr);
|
|
Packit |
534379 |
py::class_<Panther, Cat>(m, "Panther")
|
|
Packit |
534379 |
.def(py::init<std::string>())
|
|
Packit |
534379 |
.def("purr", &Panther::purr);
|
|
Packit |
534379 |
m.def("create_zoo", &create_zoo);
|
|
Packit |
534379 |
};
|