Skip to content

Commit 2fb8c82

Browse files
committed
Merge branch 'smart_holder' into pywrapcc_merge_sh
2 parents dc020d8 + 6e81be2 commit 2fb8c82

File tree

7 files changed

+80
-6
lines changed

7 files changed

+80
-6
lines changed

include/pybind11/cast.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,7 +1126,7 @@ struct move_always<
11261126
enable_if_t<
11271127
all_of<move_is_plain_type<T>,
11281128
negation<is_copy_constructible<T>>,
1129-
std::is_move_constructible<T>,
1129+
is_move_constructible<T>,
11301130
std::is_same<decltype(std::declval<make_caster<T>>().operator T &()), T &>>::value>>
11311131
: std::true_type {};
11321132
template <typename T, typename SFINAE = void>
@@ -1137,7 +1137,7 @@ struct move_if_unreferenced<
11371137
enable_if_t<
11381138
all_of<move_is_plain_type<T>,
11391139
negation<move_always<T>>,
1140-
std::is_move_constructible<T>,
1140+
is_move_constructible<T>,
11411141
std::is_same<decltype(std::declval<make_caster<T>>().operator T &()), T &>>::value>>
11421142
: std::true_type {};
11431143
template <typename T>

include/pybind11/detail/init.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ void construct(value_and_holder &v_h, Holder<Class> holder, bool need_alias) {
181181
template <typename Class>
182182
void construct(value_and_holder &v_h, Cpp<Class> &&result, bool need_alias) {
183183
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(need_alias);
184-
static_assert(std::is_move_constructible<Cpp<Class>>::value,
184+
static_assert(is_move_constructible<Cpp<Class>>::value,
185185
"pybind11::init() return-by-value factory function requires a movable class");
186186
if (Class::has_alias && need_alias) {
187187
construct_alias_from_cpp<Class>(is_alias_constructible<Class>{}, v_h, std::move(result));
@@ -196,7 +196,7 @@ void construct(value_and_holder &v_h, Cpp<Class> &&result, bool need_alias) {
196196
template <typename Class>
197197
void construct(value_and_holder &v_h, Alias<Class> &&result, bool) {
198198
static_assert(
199-
std::is_move_constructible<Alias<Class>>::value,
199+
is_move_constructible<Alias<Class>>::value,
200200
"pybind11::init() return-by-alias-value factory function requires a movable alias class");
201201
v_h.value_ptr() = new Alias<Class>(std::move(result));
202202
}

include/pybind11/detail/smart_holder_type_casters.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -720,7 +720,7 @@ struct smart_holder_type_caster : smart_holder_type_caster_load<T>,
720720

721721
static handle cast(T &src, return_value_policy policy, handle parent) {
722722
if (policy == return_value_policy::_clif_automatic) {
723-
if (std::is_move_constructible<T>::value) {
723+
if (is_move_constructible<T>::value) {
724724
policy = return_value_policy::move;
725725
} else {
726726
policy = return_value_policy::automatic;

include/pybind11/detail/type_caster_base.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,9 @@ using movable_cast_op_type
831831
template <typename T, typename SFINAE = void>
832832
struct is_copy_constructible : std::is_copy_constructible<T> {};
833833

834+
template <typename T, typename SFINAE = void>
835+
struct is_move_constructible : std::is_move_constructible<T> {};
836+
834837
// Specialization for types that appear to be copy constructible but also look like stl containers
835838
// (we specifically check for: has `value_type` and `reference` with `reference = value_type&`): if
836839
// so, copy constructability depends on whether the value_type is copy constructible.
@@ -998,7 +1001,7 @@ class type_caster_base : public type_caster_generic {
9981001
return [](const void *arg) -> void * { return new T(*reinterpret_cast<const T *>(arg)); };
9991002
}
10001003

1001-
template <typename T, typename = enable_if_t<std::is_move_constructible<T>::value>>
1004+
template <typename T, typename = enable_if_t<is_move_constructible<T>::value>>
10021005
static auto make_move_constructor(const T *)
10031006
-> decltype(new T(std::declval<T &&>()), Constructor{}) {
10041007
return [](const void *arg) -> void * {

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ set(PYBIND11_TEST_FILES
183183
test_type_caster_pyobject_ptr
184184
test_type_caster_std_function_specializations
185185
test_union
186+
test_vector_unique_ptr_member
186187
test_virtual_functions)
187188

188189
# Invoking cmake with something like:
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#include "pybind11_tests.h"
2+
3+
#include <cstddef>
4+
#include <memory>
5+
#include <vector>
6+
7+
namespace pybind11_tests {
8+
namespace vector_unique_ptr_member {
9+
10+
struct DataType {};
11+
12+
// Reduced from a use case in the wild.
13+
struct VectorOwner {
14+
static std::unique_ptr<VectorOwner> Create(std::size_t num_elems) {
15+
return std::unique_ptr<VectorOwner>(
16+
new VectorOwner(std::vector<std::unique_ptr<DataType>>(num_elems)));
17+
}
18+
19+
std::size_t data_size() const { return data_.size(); }
20+
21+
private:
22+
explicit VectorOwner(std::vector<std::unique_ptr<DataType>> data) : data_(std::move(data)) {}
23+
24+
const std::vector<std::unique_ptr<DataType>> data_;
25+
};
26+
27+
} // namespace vector_unique_ptr_member
28+
} // namespace pybind11_tests
29+
30+
namespace pybind11 {
31+
namespace detail {
32+
33+
template <>
34+
struct is_copy_constructible<pybind11_tests::vector_unique_ptr_member::VectorOwner>
35+
: std::false_type {};
36+
37+
template <>
38+
struct is_move_constructible<pybind11_tests::vector_unique_ptr_member::VectorOwner>
39+
: std::false_type {};
40+
41+
} // namespace detail
42+
} // namespace pybind11
43+
44+
using namespace pybind11_tests::vector_unique_ptr_member;
45+
46+
py::object py_cast_VectorOwner_ptr(VectorOwner *ptr) { return py::cast(ptr); }
47+
48+
// PYBIND11_SMART_HOLDER_TYPE_CASTERS(VectorOwner)
49+
50+
TEST_SUBMODULE(vector_unique_ptr_member, m) {
51+
py::class_<VectorOwner>(m, "VectorOwner")
52+
.def_static("Create", &VectorOwner::Create)
53+
.def("data_size", &VectorOwner::data_size);
54+
55+
m.def("py_cast_VectorOwner_ptr", py_cast_VectorOwner_ptr);
56+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import pytest
2+
3+
from pybind11_tests import vector_unique_ptr_member as m
4+
5+
6+
@pytest.mark.parametrize("num_elems", range(3))
7+
def test_create(num_elems):
8+
vo = m.VectorOwner.Create(num_elems)
9+
assert vo.data_size() == num_elems
10+
11+
12+
def test_cast():
13+
vo = m.VectorOwner.Create(0)
14+
assert m.py_cast_VectorOwner_ptr(vo) is vo

0 commit comments

Comments
 (0)