fix bogus return value policy fallbacks (fixes #389)

This commit is contained in:
Wenzel Jakob 2016-09-07 00:47:17 +09:00
parent a3dbdc67f5
commit c84b37b577
3 changed files with 34 additions and 5 deletions

View File

@ -220,14 +220,16 @@ public:
policy = return_value_policy::reference; policy = return_value_policy::reference;
if (policy == return_value_policy::copy) { if (policy == return_value_policy::copy) {
wrapper->value = copy_constructor(wrapper->value); if (copy_constructor)
if (wrapper->value == nullptr) wrapper->value = copy_constructor(wrapper->value);
else
throw cast_error("return_value_policy = copy, but the object is non-copyable!"); throw cast_error("return_value_policy = copy, but the object is non-copyable!");
} else if (policy == return_value_policy::move) { } else if (policy == return_value_policy::move) {
wrapper->value = move_constructor(wrapper->value); if (move_constructor)
if (wrapper->value == nullptr) wrapper->value = move_constructor(wrapper->value);
else if (copy_constructor)
wrapper->value = copy_constructor(wrapper->value); wrapper->value = copy_constructor(wrapper->value);
if (wrapper->value == nullptr) else
throw cast_error("return_value_policy = move, but the object is neither movable nor copyable!"); throw cast_error("return_value_policy = move, but the object is neither movable nor copyable!");
} else if (policy == return_value_policy::reference) { } else if (policy == return_value_policy::reference) {
wrapper->owned = false; wrapper->owned = false;

View File

@ -172,6 +172,25 @@ void init_issues(py::module &m) {
m2.def("get_NestA", [](const NestA &a) { return a.value; }); m2.def("get_NestA", [](const NestA &a) { return a.value; });
m2.def("get_NestB", [](const NestB &b) { return b.value; }); m2.def("get_NestB", [](const NestB &b) { return b.value; });
m2.def("get_NestC", [](const NestC &c) { return c.value; }); m2.def("get_NestC", [](const NestC &c) { return c.value; });
// Issue 389: r_v_p::move should fall-through to copy on non-movable objects
class MoveIssue1 {
public:
MoveIssue1(int v) : v{v} {}
MoveIssue1(const MoveIssue1 &c) { std::cerr << "copy ctor\n"; v=c.v; }
MoveIssue1(MoveIssue1 &&) = delete;
int v;
};
class MoveIssue2 {
public:
MoveIssue2(int v) : v{v} {}
MoveIssue2(MoveIssue2 &&) = default;
int v;
};
py::class_<MoveIssue1>(m2, "MoveIssue1").def(py::init<int>()).def_readwrite("value", &MoveIssue1::v);
py::class_<MoveIssue2>(m2, "MoveIssue2").def(py::init<int>()).def_readwrite("value", &MoveIssue2::v);
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);
} }
// MSVC workaround: trying to use a lambda here crashes MSCV // MSVC workaround: trying to use a lambda here crashes MSCV

View File

@ -158,3 +158,11 @@ def test_nested():
assert abase.value == 42 assert abase.value == 42
del abase, b del abase, b
gc.collect() gc.collect()
def test_move_fallback():
from pybind11_tests.issues import get_moveissue1, get_moveissue2
m2 = get_moveissue2(2)
assert m2.value == 2
m1 = get_moveissue1(1)
assert m1.value == 1