Skip to content

Commit 5d21d8a

Browse files
committed
Tracing CpCtor, MvCtor, removing smart-pointer casters, renaming, more comments.
1 parent 96086c0 commit 5d21d8a

File tree

2 files changed

+87
-181
lines changed

2 files changed

+87
-181
lines changed

tests/test_type_caster_bare_interface.cpp

Lines changed: 56 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,40 @@
22
// direction of an integration test, to ensure multiple components of pybind11 work together
33
// correctly. It is also useful to show the type_caster<> interface virtually clutter-free.
44

5+
// The entire type_caster load logic is intentionally omitted. The only purpose of this test is to
6+
// trace the behavior of the `static handle cast()` functions and the type_caster `operator`s.
7+
// Variable names are intentionally terse, to not distract from the more important function
8+
// signatures: valu(e), ref(erence), ptr (pointer), r = rvalue, m = mutable, c = const.
9+
510
#include "pybind11_tests.h"
611

7-
#include <memory>
12+
#include <string>
813

914
namespace pybind11_tests {
1015
namespace type_caster_bare_interface {
1116

12-
struct mpty {};
17+
struct atyp { // Short for "any type".
18+
std::string trace;
19+
atyp() : trace("default") {}
20+
atyp(atyp const &other) { trace = other.trace + "_CpCtor"; }
21+
atyp(atyp &&other) { trace = other.trace + "_MvCtor"; }
22+
};
1323

1424
// clang-format off
1525

16-
mpty rtrn_valu() { mpty obj; return obj; }
17-
mpty&& rtrn_rref() { static mpty obj; return std::move(obj); }
18-
mpty const& rtrn_cref() { static mpty obj; return obj; }
19-
mpty& rtrn_mref() { static mpty obj; return obj; }
20-
mpty const* rtrn_cptr() { return new mpty; }
21-
mpty* rtrn_mptr() { return new mpty; }
22-
23-
const char* pass_valu(mpty) { return "load_valu"; }
24-
const char* pass_rref(mpty&&) { return "load_rref"; }
25-
const char* pass_cref(mpty const&) { return "load_cref"; }
26-
const char* pass_mref(mpty&) { return "load_mref"; }
27-
const char* pass_cptr(mpty const*) { return "load_cptr"; }
28-
const char* pass_mptr(mpty*) { return "load_mptr"; }
29-
30-
std::shared_ptr<mpty> rtrn_shmp() { return std::shared_ptr<mpty >(new mpty); }
31-
std::shared_ptr<mpty const> rtrn_shcp() { return std::shared_ptr<mpty const>(new mpty); }
26+
atyp rtrn_valu() { static atyp obj; obj.trace = "valu"; return obj; }
27+
atyp&& rtrn_rref() { static atyp obj; obj.trace = "rref"; return std::move(obj); }
28+
atyp const& rtrn_cref() { static atyp obj; obj.trace = "cref"; return obj; }
29+
atyp& rtrn_mref() { static atyp obj; obj.trace = "mref"; return obj; }
30+
atyp const* rtrn_cptr() { static atyp obj; obj.trace = "cptr"; return &obj; }
31+
atyp* rtrn_mptr() { static atyp obj; obj.trace = "mptr"; return &obj; }
3232

33-
const char* pass_shmp(std::shared_ptr<mpty>) { return "load_shmp"; }
34-
const char* pass_shcp(std::shared_ptr<mpty const>) { return "load_shcp"; }
35-
36-
std::unique_ptr<mpty> rtrn_uqmp() { return std::unique_ptr<mpty >(new mpty); }
37-
std::unique_ptr<mpty const> rtrn_uqcp() { return std::unique_ptr<mpty const>(new mpty); }
38-
39-
const char* pass_uqmp(std::unique_ptr<mpty>) { return "load_uqmp"; }
40-
const char* pass_uqcp(std::unique_ptr<mpty const>) { return "load_uqcp"; }
33+
std::string pass_valu(atyp obj) { return "pass_valu:" + obj.trace; }
34+
std::string pass_rref(atyp&& obj) { return "pass_rref:" + obj.trace; }
35+
std::string pass_cref(atyp const& obj) { return "pass_cref:" + obj.trace; }
36+
std::string pass_mref(atyp& obj) { return "pass_mref:" + obj.trace; }
37+
std::string pass_cptr(atyp const* obj) { return "pass_cptr:" + obj->trace; }
38+
std::string pass_mptr(atyp* obj) { return "pass_mptr:" + obj->trace; }
4139

4240
// clang-format on
4341

@@ -50,140 +48,68 @@ namespace detail {
5048
using namespace pybind11_tests::type_caster_bare_interface;
5149

5250
template <>
53-
struct type_caster<mpty> {
54-
static constexpr auto name = _<mpty>();
51+
struct type_caster<atyp> {
52+
static constexpr auto name = _<atyp>();
5553

56-
// static handle cast(mpty, ...)
54+
// static handle cast(atyp, ...)
5755
// is redundant (leads to ambiguous overloads).
5856

59-
static handle cast(mpty && /*src*/, return_value_policy /*policy*/, handle /*parent*/) {
60-
return str("cast_rref").release();
57+
static handle cast(atyp &&src, return_value_policy /*policy*/, handle /*parent*/) {
58+
return str("cast_rref:" + src.trace).release();
6159
}
6260

63-
static handle cast(mpty const & /*src*/, return_value_policy /*policy*/, handle /*parent*/) {
64-
return str("cast_cref").release();
61+
static handle cast(atyp const &src, return_value_policy /*policy*/, handle /*parent*/) {
62+
return str("cast_cref:" + src.trace).release();
6563
}
6664

67-
static handle cast(mpty & /*src*/, return_value_policy /*policy*/, handle /*parent*/) {
68-
return str("cast_mref").release();
65+
static handle cast(atyp &src, return_value_policy /*policy*/, handle /*parent*/) {
66+
return str("cast_mref:" + src.trace).release();
6967
}
7068

71-
static handle cast(mpty const *src, return_value_policy /*policy*/, handle /*parent*/) {
72-
delete src;
73-
return str("cast_cptr").release();
69+
static handle cast(atyp const *src, return_value_policy /*policy*/, handle /*parent*/) {
70+
return str("cast_cptr:" + src->trace).release();
7471
}
7572

76-
static handle cast(mpty *src, return_value_policy /*policy*/, handle /*parent*/) {
77-
delete src;
78-
return str("cast_mptr").release();
73+
static handle cast(atyp *src, return_value_policy /*policy*/, handle /*parent*/) {
74+
return str("cast_mptr:" + src->trace).release();
7975
}
8076

8177
template <typename T_>
8278
using cast_op_type = conditional_t<
83-
std::is_same<remove_reference_t<T_>, mpty const *>::value,
84-
mpty const *,
79+
std::is_same<remove_reference_t<T_>, atyp const *>::value,
80+
atyp const *,
8581
conditional_t<
86-
std::is_same<remove_reference_t<T_>, mpty *>::value,
87-
mpty *,
82+
std::is_same<remove_reference_t<T_>, atyp *>::value,
83+
atyp *,
8884
conditional_t<
89-
std::is_same<T_, mpty const &>::value,
90-
mpty const &,
91-
conditional_t<std::is_same<T_, mpty &>::value,
92-
mpty &,
93-
conditional_t<std::is_same<T_, mpty &&>::value, mpty &&, mpty>>>>>;
85+
std::is_same<T_, atyp const &>::value,
86+
atyp const &,
87+
conditional_t<std::is_same<T_, atyp &>::value,
88+
atyp &,
89+
conditional_t<std::is_same<T_, atyp &&>::value, atyp &&, atyp>>>>>;
9490

9591
// clang-format off
9692

97-
operator mpty() { return rtrn_valu(); }
98-
operator mpty&&() && { return rtrn_rref(); }
99-
operator mpty const&() { return rtrn_cref(); }
100-
operator mpty&() { return rtrn_mref(); }
101-
operator mpty const*() { static mpty obj; return &obj; }
102-
operator mpty*() { static mpty obj; return &obj; }
93+
operator atyp() { static atyp obj; obj.trace = "valu"; return obj; }
94+
operator atyp&&() { static atyp obj; obj.trace = "rref"; return std::move(obj); }
95+
operator atyp const&() { static atyp obj; obj.trace = "cref"; return obj; }
96+
operator atyp&() { static atyp obj; obj.trace = "mref"; return obj; }
97+
operator atyp const*() { static atyp obj; obj.trace = "cptr"; return &obj; }
98+
operator atyp*() { static atyp obj; obj.trace = "mptr"; return &obj; }
10399

104100
// clang-format on
105101

106-
bool load(handle /*src*/, bool /*convert*/) { return true; }
107-
};
108-
109-
template <>
110-
struct type_caster<std::shared_ptr<mpty>> {
111-
static constexpr auto name = _<std::shared_ptr<mpty>>();
112-
113-
static handle cast(const std::shared_ptr<mpty> & /*src*/,
114-
return_value_policy /*policy*/,
115-
handle /*parent*/) {
116-
return str("cast_shmp").release();
117-
}
118-
119-
template <typename>
120-
using cast_op_type = std::shared_ptr<mpty>;
121-
122-
operator std::shared_ptr<mpty>() { return rtrn_shmp(); }
123-
124-
bool load(handle /*src*/, bool /*convert*/) { return true; }
125-
};
126-
127-
template <>
128-
struct type_caster<std::shared_ptr<mpty const>> {
129-
static constexpr auto name = _<std::shared_ptr<mpty const>>();
130-
131-
static handle cast(const std::shared_ptr<mpty const> & /*src*/,
132-
return_value_policy /*policy*/,
133-
handle /*parent*/) {
134-
return str("cast_shcp").release();
135-
}
136-
137-
template <typename>
138-
using cast_op_type = std::shared_ptr<mpty const>;
139-
140-
operator std::shared_ptr<mpty const>() { return rtrn_shcp(); }
141-
142-
bool load(handle /*src*/, bool /*convert*/) { return true; }
143-
};
144-
145-
template <>
146-
struct type_caster<std::unique_ptr<mpty>> {
147-
static constexpr auto name = _<std::unique_ptr<mpty>>();
148-
149-
static handle
150-
cast(std::unique_ptr<mpty> && /*src*/, return_value_policy /*policy*/, handle /*parent*/) {
151-
return str("cast_uqmp").release();
152-
}
153-
154-
template <typename>
155-
using cast_op_type = std::unique_ptr<mpty>;
156-
157-
operator std::unique_ptr<mpty>() { return rtrn_uqmp(); }
158-
159-
bool load(handle /*src*/, bool /*convert*/) { return true; }
160-
};
161-
162-
template <>
163-
struct type_caster<std::unique_ptr<mpty const>> {
164-
static constexpr auto name = _<std::unique_ptr<mpty const>>();
165-
166-
static handle cast(std::unique_ptr<mpty const> && /*src*/,
167-
return_value_policy /*policy*/,
168-
handle /*parent*/) {
169-
return str("cast_uqcp").release();
170-
}
171-
172-
template <typename>
173-
using cast_op_type = std::unique_ptr<mpty const>;
174-
175-
operator std::unique_ptr<mpty const>() { return rtrn_uqcp(); }
176-
102+
// The entire load logic is intentionally omitted.
177103
bool load(handle /*src*/, bool /*convert*/) { return true; }
178104
};
179105

180106
} // namespace detail
181107
} // namespace pybind11
182108

183-
namespace pybind11_tests {
184-
namespace type_caster_bare_interface {
185-
186109
TEST_SUBMODULE(type_caster_bare_interface, m) {
110+
namespace py = pybind11;
111+
using namespace pybind11_tests::type_caster_bare_interface;
112+
187113
m.def("rtrn_valu", rtrn_valu);
188114
m.def("rtrn_rref", rtrn_rref);
189115
m.def("rtrn_cref", rtrn_cref);
@@ -197,19 +123,4 @@ TEST_SUBMODULE(type_caster_bare_interface, m) {
197123
m.def("pass_mref", pass_mref);
198124
m.def("pass_cptr", pass_cptr);
199125
m.def("pass_mptr", pass_mptr);
200-
201-
m.def("rtrn_shmp", rtrn_shmp);
202-
m.def("rtrn_shcp", rtrn_shcp);
203-
204-
m.def("pass_shmp", pass_shmp);
205-
m.def("pass_shcp", pass_shcp);
206-
207-
m.def("rtrn_uqmp", rtrn_uqmp);
208-
m.def("rtrn_uqcp", rtrn_uqcp);
209-
210-
m.def("pass_uqmp", pass_uqmp);
211-
m.def("pass_uqcp", pass_uqcp);
212126
}
213-
214-
} // namespace type_caster_bare_interface
215-
} // namespace pybind11_tests
Lines changed: 31 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,36 @@
11
# -*- coding: utf-8 -*-
2+
import re
23

3-
from pybind11_tests import type_caster_bare_interface as m
4-
5-
6-
def test_cast():
7-
assert m.rtrn_valu() == "cast_rref"
8-
assert m.rtrn_rref() == "cast_rref"
9-
assert m.rtrn_cref() == "cast_cref"
10-
assert m.rtrn_mref() == "cast_mref"
11-
assert m.rtrn_cptr() == "cast_cptr"
12-
assert m.rtrn_mptr() == "cast_mptr"
13-
14-
15-
def test_load():
16-
assert m.pass_valu(None) == "load_valu"
17-
assert m.pass_rref(None) == "load_rref"
18-
assert m.pass_cref(None) == "load_cref"
19-
assert m.pass_mref(None) == "load_mref"
20-
assert m.pass_cptr(None) == "load_cptr"
21-
assert m.pass_mptr(None) == "load_mptr"
22-
4+
import pytest
235

24-
def test_cast_shared_ptr():
25-
assert m.rtrn_shmp() == "cast_shmp"
26-
assert m.rtrn_shcp() == "cast_shcp"
27-
28-
29-
def test_load_shared_ptr():
30-
assert m.pass_shmp(None) == "load_shmp"
31-
assert m.pass_shcp(None) == "load_shcp"
32-
33-
34-
def test_cast_unique_ptr():
35-
assert m.rtrn_uqmp() == "cast_uqmp"
36-
assert m.rtrn_uqcp() == "cast_uqcp"
6+
from pybind11_tests import type_caster_bare_interface as m
377

388

39-
def test_load_unique_ptr():
40-
assert m.pass_uqmp(None) == "load_uqmp"
41-
assert m.pass_uqcp(None) == "load_uqcp"
9+
@pytest.mark.parametrize(
10+
"rtrn_f, expected",
11+
[
12+
(m.rtrn_valu, "cast_rref:valu_CpCtor"),
13+
(m.rtrn_rref, "cast_rref:rref"),
14+
(m.rtrn_cref, "cast_cref:cref"),
15+
(m.rtrn_mref, "cast_mref:mref"),
16+
(m.rtrn_cptr, "cast_cptr:cptr"),
17+
(m.rtrn_mptr, "cast_mptr:mptr"),
18+
],
19+
)
20+
def test_cast(rtrn_f, expected):
21+
assert re.match(expected, rtrn_f())
22+
23+
24+
@pytest.mark.parametrize(
25+
"pass_f, expected",
26+
[
27+
(m.pass_valu, "pass_valu:rref_MvCtor"),
28+
(m.pass_rref, "pass_rref:rref"),
29+
(m.pass_cref, "pass_cref:cref"),
30+
(m.pass_mref, "pass_mref:mref"),
31+
(m.pass_cptr, "pass_cptr:cptr"),
32+
(m.pass_mptr, "pass_mptr:mptr"),
33+
],
34+
)
35+
def test_operator(pass_f, expected):
36+
assert re.match(expected, pass_f(None))

0 commit comments

Comments
 (0)