Skip to content

fixed regression in STL type caster RVPs (fixes #1561) #1603

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ image:
- Visual Studio 2017
- Visual Studio 2015
test: off
skip_branch_with_pr: true
build:
parallel: true
platform:
Expand Down
5 changes: 3 additions & 2 deletions include/pybind11/cast.h
Original file line number Diff line number Diff line change
Expand Up @@ -1614,8 +1614,9 @@ template <typename Return, typename SFINAE = void> struct return_value_policy_ov
template <typename Return> struct return_value_policy_override<Return,
detail::enable_if_t<std::is_base_of<type_caster_generic, make_caster<Return>>::value, void>> {
static return_value_policy policy(return_value_policy p) {
return !std::is_lvalue_reference<Return>::value && !std::is_pointer<Return>::value
? return_value_policy::move : p;
return !std::is_lvalue_reference<Return>::value &&
!std::is_pointer<Return>::value
? return_value_policy::move : p;
}
};

Expand Down
14 changes: 10 additions & 4 deletions include/pybind11/stl.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ template <typename Type, typename Key> struct set_caster {

template <typename T>
static handle cast(T &&src, return_value_policy policy, handle parent) {
policy = return_value_policy_override<Key>::policy(policy);
if (!std::is_lvalue_reference<T>::value)
policy = return_value_policy_override<Key>::policy(policy);
pybind11::set s;
for (auto &&value : src) {
auto value_ = reinterpret_steal<object>(key_conv::cast(forward_like<T>(value), policy, parent));
Expand Down Expand Up @@ -119,8 +120,12 @@ template <typename Type, typename Key, typename Value> struct map_caster {
template <typename T>
static handle cast(T &&src, return_value_policy policy, handle parent) {
dict d;
return_value_policy policy_key = return_value_policy_override<Key>::policy(policy);
return_value_policy policy_value = return_value_policy_override<Value>::policy(policy);
return_value_policy policy_key = policy;
return_value_policy policy_value = policy;
if (!std::is_lvalue_reference<T>::value) {
policy_key = return_value_policy_override<Key>::policy(policy_key);
policy_value = return_value_policy_override<Value>::policy(policy_value);
}
for (auto &&kv : src) {
auto key = reinterpret_steal<object>(key_conv::cast(forward_like<T>(kv.first), policy_key, parent));
auto value = reinterpret_steal<object>(value_conv::cast(forward_like<T>(kv.second), policy_value, parent));
Expand Down Expand Up @@ -161,7 +166,8 @@ template <typename Type, typename Value> struct list_caster {
public:
template <typename T>
static handle cast(T &&src, return_value_policy policy, handle parent) {
policy = return_value_policy_override<Value>::policy(policy);
if (!std::is_lvalue_reference<T>::value)
policy = return_value_policy_override<Value>::policy(policy);
list l(src.size());
size_t index = 0;
for (auto &&value : src) {
Expand Down
12 changes: 12 additions & 0 deletions tests/test_stl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,4 +265,16 @@ TEST_SUBMODULE(stl, m) {
py::return_value_policy::take_ownership);

m.def("array_cast_sequence", [](std::array<int, 3> x) { return x; });

/// test_issue_1561
struct Issue1561Inner { std::string data; };
struct Issue1561Outer { std::vector<Issue1561Inner> list; };

py::class_<Issue1561Inner>(m, "Issue1561Inner")
.def(py::init<std::string>())
.def_readwrite("data", &Issue1561Inner::data);

py::class_<Issue1561Outer>(m, "Issue1561Outer")
.def(py::init<>())
.def_readwrite("list", &Issue1561Outer::list);
}
8 changes: 8 additions & 0 deletions tests/test_stl.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,3 +220,11 @@ def test_stl_ownership():

def test_array_cast_sequence():
assert m.array_cast_sequence((1, 2, 3)) == [1, 2, 3]


def test_issue_1561():
""" check fix for issue #1561 """
bar = m.Issue1561Outer()
bar.list = [m.Issue1561Inner('bar')]
bar.list
assert bar.list[0].data == 'bar'