From 9c6859ee6e90c6df9f3624968620b82bb22a0e6e Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Thu, 8 Sep 2016 11:03:08 -0400 Subject: [PATCH] Fix type alias initialization Type alias for alias classes with members didn't work properly: space was only allocated for sizeof(type), but if we want to be able to put a type_alias instance there, we need sizeof(type_alias), but sizeof(type_alias) > sizeof(type) whenever type_alias has members. --- include/pybind11/pybind11.h | 2 +- tests/test_issues.cpp | 29 ++++++++++++++++++----------- tests/test_issues.py | 16 ++++++++-------- 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index dd04e9550..8f88d36c9 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -851,7 +851,7 @@ public: record.scope = scope; record.name = name; record.type = &typeid(type); - record.type_size = sizeof(type); + record.type_size = sizeof(detail::conditional_t); record.instance_size = sizeof(instance_type); record.init_holder = init_holder; record.dealloc = dealloc; diff --git a/tests/test_issues.cpp b/tests/test_issues.cpp index c4d89c104..c5314bcdc 100644 --- a/tests/test_issues.cpp +++ b/tests/test_issues.cpp @@ -192,34 +192,41 @@ void init_issues(py::module &m) { m2.def("get_moveissue1", [](int i) -> MoveIssue1 * { return new MoveIssue1(i); }, py::return_value_policy::move); m2.def("get_moveissue2", [](int i) { return MoveIssue2(i); }, py::return_value_policy::move); - // Issue 392: overridding reference-returning functions + // Issues 392/397: overridding reference-returning functions class OverrideTest { public: - struct A { int value = 99; }; - int v; + struct A { std::string value = "hi"; }; + std::string v; A a; - explicit OverrideTest(int v) : v{v} {} - virtual int int_value() { return v; } - virtual int &int_ref() { return v; } + explicit OverrideTest(const std::string &v) : v{v} {} + virtual std::string str_value() { return v; } + virtual std::string &str_ref() { return v; } virtual A A_value() { return a; } virtual A &A_ref() { return a; } }; class PyOverrideTest : public OverrideTest { public: using OverrideTest::OverrideTest; - int int_value() override { PYBIND11_OVERLOAD(int, OverrideTest, int_value); } + std::string str_value() override { PYBIND11_OVERLOAD(std::string, OverrideTest, str_value); } // Not allowed (uncommenting should hit a static_assert failure): we can't get a reference // to a python numeric value, since we only copy values in the numeric type caster: -// int &int_ref() override { PYBIND11_OVERLOAD(int &, OverrideTest, int_ref); } +// std::string &str_ref() override { PYBIND11_OVERLOAD(std::string &, OverrideTest, str_ref); } + // But we can work around it like this: + private: + std::string _tmp; + std::string str_ref_helper() { PYBIND11_OVERLOAD(std::string, OverrideTest, str_ref); } + public: + std::string &str_ref() override { return _tmp = str_ref_helper(); } + A A_value() override { PYBIND11_OVERLOAD(A, OverrideTest, A_value); } A &A_ref() override { PYBIND11_OVERLOAD(A &, OverrideTest, A_ref); } }; py::class_(m2, "OverrideTest_A") .def_readwrite("value", &OverrideTest::A::value); py::class_(m2, "OverrideTest") - .def(py::init()) - .def("int_value", &OverrideTest::int_value) -// .def("int_ref", &OverrideTest::int_ref) + .def(py::init()) + .def("str_value", &OverrideTest::str_value) +// .def("str_ref", &OverrideTest::str_ref) .def("A_value", &OverrideTest::A_value) .def("A_ref", &OverrideTest::A_ref); diff --git a/tests/test_issues.py b/tests/test_issues.py index 86bd6a513..2af6f1ce1 100644 --- a/tests/test_issues.py +++ b/tests/test_issues.py @@ -169,15 +169,15 @@ def test_move_fallback(): def test_override_ref(): from pybind11_tests.issues import OverrideTest - o = OverrideTest(42) + o = OverrideTest("asdf") # Not allowed (see associated .cpp comment) - #i = o.int_ref() - #assert o.int_ref() == 42 - assert o.int_value() == 42 + #i = o.str_ref() + #assert o.str_ref() == "asdf" + assert o.str_value() == "asdf" - assert o.A_value().value == 99 + assert o.A_value().value == "hi" a = o.A_ref() - assert a.value == 99 - a.value = 7 - assert a.value == 7 + assert a.value == "hi" + a.value = "bye" + assert a.value == "bye"