Skip to content

Commit a4c2400

Browse files
committed
unique_ptr or shared_ptr return
1 parent 2e4022d commit a4c2400

File tree

2 files changed

+73
-16
lines changed

2 files changed

+73
-16
lines changed

tests/test_unique_ptr_member.cpp

+47-10
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,23 @@
11
#include "pybind11_tests.h"
22

3+
#include <iostream>
34
#include <memory>
45

56
namespace pybind11_tests {
67
namespace unique_ptr_member {
78

9+
inline void to_cout(std::string text) { std::cout << text << std::endl; }
10+
811
class pointee { // NOT copyable.
912
public:
1013
pointee() = default;
1114

12-
int get_int() const { return 213; }
15+
int get_int() const {
16+
to_cout("pointee::get_int()");
17+
return 213;
18+
}
19+
20+
~pointee() { to_cout("~pointee()"); }
1321

1422
private:
1523
pointee(const pointee &) = delete;
@@ -18,35 +26,64 @@ class pointee { // NOT copyable.
1826
pointee &operator=(pointee &&) = delete;
1927
};
2028

29+
inline std::unique_ptr<pointee> make_unique_pointee() {
30+
return std::unique_ptr<pointee>(new pointee);
31+
}
32+
2133
class ptr_owner {
2234
public:
2335
explicit ptr_owner(std::unique_ptr<pointee> ptr) : ptr_(std::move(ptr)) {}
2436

37+
bool is_owner() const { return bool(ptr_); }
38+
39+
std::unique_ptr<pointee> give_up_ownership_via_unique_ptr() {
40+
return std::move(ptr_);
41+
}
42+
std::shared_ptr<pointee> give_up_ownership_via_shared_ptr() {
43+
return std::move(ptr_);
44+
}
45+
2546
private:
2647
std::unique_ptr<pointee> ptr_;
2748
};
2849

2950
// Just to have a minimal example of a typical C++ pattern.
3051
inline int cpp_pattern() {
31-
auto obj = std::unique_ptr<pointee>(new pointee);
32-
int result = (obj ? 10 : 0);
52+
auto obj = make_unique_pointee();
53+
int result = (obj ? 1 : 8);
54+
obj->get_int();
3355
ptr_owner owner(std::move(obj));
34-
result += (obj ? 1 : 0);
56+
result = result * 10 + (obj ? 8 : 1);
57+
result = result * 10 + (owner.is_owner() ? 1 : 8);
58+
to_cout("before give up");
59+
auto reclaimed = owner.give_up_ownership_via_shared_ptr();
60+
to_cout("after give up");
61+
result = result * 10 + (owner.is_owner() ? 8 : 1);
62+
result = result * 10 + (reclaimed ? 1 : 8);
63+
reclaimed.reset();
64+
to_cout("after del");
65+
result = result * 10 + (reclaimed ? 8 : 1);
3566
return result;
3667
}
3768

3869
TEST_SUBMODULE(unique_ptr_member, m) {
39-
m.def("cpp_pattern", cpp_pattern);
70+
m.def("to_cout", to_cout);
4071

41-
py::class_<pointee>(m, "pointee")
72+
py::class_<pointee, std::shared_ptr<pointee>>(m, "pointee")
4273
.def(py::init<>())
4374
.def("get_int", &pointee::get_int);
4475

76+
m.def("make_unique_pointee", make_unique_pointee);
77+
4578
py::class_<ptr_owner>(m, "ptr_owner")
46-
#ifdef FEAT_UNIQUE_PTR_ARG
47-
.def(py::init<std::unique_ptr<pointee>>(), py::arg("ptr"))
48-
#endif
49-
;
79+
//.def(py::init<std::unique_ptr<pointee>>(), py::arg("ptr"))
80+
.def("is_owner", &ptr_owner::is_owner)
81+
.def("give_up_ownership_via_unique_ptr",
82+
&ptr_owner::give_up_ownership_via_unique_ptr)
83+
.def("give_up_ownership_via_shared_ptr",
84+
&ptr_owner::give_up_ownership_via_shared_ptr);
85+
86+
m.def("cpp_pattern", cpp_pattern);
5087
}
5188

5289
} // namespace unique_ptr_member

tests/test_unique_ptr_member.py

+26-6
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,35 @@
44
from pybind11_tests import unique_ptr_member as m
55

66

7-
def test_cpp_pattern():
8-
res = m.cpp_pattern()
9-
assert res == 10
7+
def test_make_unique_pointee():
8+
m.to_cout("")
9+
obj = m.make_unique_pointee()
10+
assert obj.get_int() == 213
11+
m.to_cout("")
1012

1113

1214
def test_pointee_and_ptr_owner():
15+
m.to_cout("")
1316
obj = m.pointee()
1417
assert obj.get_int() == 213
15-
m.ptr_owner(obj)
16-
with pytest.raises(ValueError) as exc_info:
18+
owner = m.ptr_owner(obj)
19+
with pytest.raises(RuntimeError) as exc_info:
1720
obj.get_int()
18-
assert str(exc_info.value).startswith("Missing value for wrapped C++ type ")
21+
assert str(exc_info.value) == "Invalid object instance"
22+
assert owner.is_owner()
23+
m.to_cout("before give up")
24+
reclaimed = owner.give_up_ownership_via_shared_ptr()
25+
m.to_cout("after give up")
26+
assert not owner.is_owner()
27+
# assert reclaimed.get_int() == 213
28+
del reclaimed
29+
m.to_cout("after del")
30+
m.to_cout("3")
31+
m.to_cout("")
32+
33+
34+
def test_cpp_pattern():
35+
m.to_cout("")
36+
res = m.cpp_pattern()
37+
assert res == 111111
38+
m.to_cout("")

0 commit comments

Comments
 (0)