Skip to content

Commit f64db3e

Browse files
committed
new test_variant_unique_shared with vptr_holder prototype
1 parent a4c2400 commit f64db3e

File tree

2 files changed

+151
-0
lines changed

2 files changed

+151
-0
lines changed

tests/test_variant_unique_shared.cpp

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#include <memory>
2+
#include <variant>
3+
4+
#include "pybind11_tests.h"
5+
6+
namespace pybind11_tests {
7+
8+
// Could this be a holder for a `class_`-like `vclass`?
9+
// To enable passing of unique_ptr as in pure C++.
10+
template <typename T> class vptr_holder {
11+
public:
12+
explicit vptr_holder(T *ptr = nullptr) : vptr_{std::unique_ptr<T>(ptr)} {}
13+
explicit vptr_holder(std::unique_ptr<T> u) : vptr_{std::move(u)} {}
14+
explicit vptr_holder(std::shared_ptr<T> s) : vptr_{s} {}
15+
16+
int ownership_type() const {
17+
if (std::get_if<0>(&vptr_)) {
18+
return 0;
19+
}
20+
if (std::get_if<1>(&vptr_)) {
21+
return 1;
22+
}
23+
return -1;
24+
}
25+
26+
T *get() {
27+
auto u = std::get_if<0>(&vptr_);
28+
if (u) {
29+
return u->get();
30+
}
31+
auto s = std::get_if<1>(&vptr_);
32+
if (s) {
33+
return s->get();
34+
}
35+
return nullptr;
36+
}
37+
38+
std::unique_ptr<T> get_unique() {
39+
auto u = std::get_if<0>(&vptr_);
40+
if (u) {
41+
return std::move(*u);
42+
}
43+
throw std::runtime_error("get_unique failure.");
44+
}
45+
46+
std::shared_ptr<T> get_shared() {
47+
auto s = std::get_if<1>(&vptr_);
48+
if (s) {
49+
return *s;
50+
}
51+
auto u = std::get_if<0>(&vptr_);
52+
if (u) {
53+
auto result = std::shared_ptr<T>(std::move(*u));
54+
vptr_ = result;
55+
return result;
56+
}
57+
throw std::runtime_error("get_shared failure.");
58+
}
59+
60+
private:
61+
std::variant<std::unique_ptr<T>, std::shared_ptr<T>> vptr_;
62+
};
63+
64+
vptr_holder<double> from_raw() { return vptr_holder<double>{new double{3}}; }
65+
66+
vptr_holder<double> from_unique() {
67+
return vptr_holder<double>{std::unique_ptr<double>(new double{5})};
68+
}
69+
70+
vptr_holder<double> from_shared() {
71+
return vptr_holder<double>{std::shared_ptr<double>(new double{7})};
72+
}
73+
74+
TEST_SUBMODULE(variant_unique_shared, m) {
75+
76+
m.def("from_raw", from_raw);
77+
m.def("from_unique", from_unique);
78+
m.def("from_shared", from_shared);
79+
80+
py::class_<vptr_holder<double>>(m, "vptr_holder_double")
81+
.def(py::init<>())
82+
.def("ownership_type", &vptr_holder<double>::ownership_type)
83+
.def("get_value",
84+
[](vptr_holder<double> &v) {
85+
auto p = v.get();
86+
if (p)
87+
return *p;
88+
return -1.;
89+
})
90+
.def("get_unique",
91+
[](vptr_holder<double> &v) {
92+
v.get_unique();
93+
return;
94+
})
95+
.def("get_shared", [](vptr_holder<double> &v) {
96+
v.get_shared();
97+
return;
98+
});
99+
}
100+
101+
} // namespace pybind11_tests

tests/test_variant_unique_shared.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# -*- coding: utf-8 -*-
2+
import pytest
3+
4+
from pybind11_tests import variant_unique_shared as m
5+
6+
7+
def test_default_constructed():
8+
v = m.vptr_holder_double()
9+
assert v.ownership_type() == 0
10+
assert v.get_value() == -1
11+
12+
13+
def test_from_raw():
14+
v = m.from_raw()
15+
assert v.ownership_type() == 0
16+
assert v.get_value() == 3
17+
18+
19+
def test_from_unique():
20+
v = m.from_unique()
21+
assert v.ownership_type() == 0
22+
assert v.get_value() == 5
23+
24+
25+
def test_from_shared():
26+
v = m.from_shared()
27+
assert v.ownership_type() == 1
28+
assert v.get_value() == 7
29+
30+
31+
def test_promotion_to_shared():
32+
v = m.from_raw()
33+
v.get_unique()
34+
assert v.ownership_type() == 0
35+
v.get_shared() # Promotion to shared_ptr.
36+
assert v.ownership_type() == 1
37+
v.get_shared() # Existing shared_ptr.
38+
with pytest.raises(RuntimeError) as exc_info:
39+
v.get_unique()
40+
assert str(exc_info.value) == "get_unique failure."
41+
v.get_shared() # Still works.
42+
43+
44+
def test_shared_from_birth():
45+
v = m.from_shared()
46+
assert v.ownership_type() == 1
47+
with pytest.raises(RuntimeError) as exc_info:
48+
v.get_unique()
49+
assert str(exc_info.value) == "get_unique failure."
50+
v.get_shared() # Still works.

0 commit comments

Comments
 (0)