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.
This commit is contained in:
Jason Rhinelander 2016-09-08 11:03:08 -04:00
parent 5812d64ba2
commit 9c6859ee6e
3 changed files with 27 additions and 20 deletions

View File

@ -851,7 +851,7 @@ public:
record.scope = scope; record.scope = scope;
record.name = name; record.name = name;
record.type = &typeid(type); record.type = &typeid(type);
record.type_size = sizeof(type); record.type_size = sizeof(detail::conditional_t<has_alias, type_alias, type>);
record.instance_size = sizeof(instance_type); record.instance_size = sizeof(instance_type);
record.init_holder = init_holder; record.init_holder = init_holder;
record.dealloc = dealloc; record.dealloc = dealloc;

View File

@ -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_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); 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 { class OverrideTest {
public: public:
struct A { int value = 99; }; struct A { std::string value = "hi"; };
int v; std::string v;
A a; A a;
explicit OverrideTest(int v) : v{v} {} explicit OverrideTest(const std::string &v) : v{v} {}
virtual int int_value() { return v; } virtual std::string str_value() { return v; }
virtual int &int_ref() { return v; } virtual std::string &str_ref() { return v; }
virtual A A_value() { return a; } virtual A A_value() { return a; }
virtual A &A_ref() { return a; } virtual A &A_ref() { return a; }
}; };
class PyOverrideTest : public OverrideTest { class PyOverrideTest : public OverrideTest {
public: public:
using OverrideTest::OverrideTest; 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 // 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: // 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_value() override { PYBIND11_OVERLOAD(A, OverrideTest, A_value); }
A &A_ref() override { PYBIND11_OVERLOAD(A &, OverrideTest, A_ref); } A &A_ref() override { PYBIND11_OVERLOAD(A &, OverrideTest, A_ref); }
}; };
py::class_<OverrideTest::A>(m2, "OverrideTest_A") py::class_<OverrideTest::A>(m2, "OverrideTest_A")
.def_readwrite("value", &OverrideTest::A::value); .def_readwrite("value", &OverrideTest::A::value);
py::class_<OverrideTest, PyOverrideTest>(m2, "OverrideTest") py::class_<OverrideTest, PyOverrideTest>(m2, "OverrideTest")
.def(py::init<int>()) .def(py::init<const std::string &>())
.def("int_value", &OverrideTest::int_value) .def("str_value", &OverrideTest::str_value)
// .def("int_ref", &OverrideTest::int_ref) // .def("str_ref", &OverrideTest::str_ref)
.def("A_value", &OverrideTest::A_value) .def("A_value", &OverrideTest::A_value)
.def("A_ref", &OverrideTest::A_ref); .def("A_ref", &OverrideTest::A_ref);

View File

@ -169,15 +169,15 @@ def test_move_fallback():
def test_override_ref(): def test_override_ref():
from pybind11_tests.issues import OverrideTest from pybind11_tests.issues import OverrideTest
o = OverrideTest(42) o = OverrideTest("asdf")
# Not allowed (see associated .cpp comment) # Not allowed (see associated .cpp comment)
#i = o.int_ref() #i = o.str_ref()
#assert o.int_ref() == 42 #assert o.str_ref() == "asdf"
assert o.int_value() == 42 assert o.str_value() == "asdf"
assert o.A_value().value == 99 assert o.A_value().value == "hi"
a = o.A_ref() a = o.A_ref()
assert a.value == 99 assert a.value == "hi"
a.value = 7 a.value = "bye"
assert a.value == 7 assert a.value == "bye"