mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-21 20:55:11 +00:00
Introduce pybind11::detail::is_move_constructible
(#4631)
To support the use case captured in the new test_vector_unique_ptr_member.cpp
This commit is contained in:
parent
071f35ab85
commit
07725c28c0
@ -964,7 +964,7 @@ struct move_always<
|
||||
enable_if_t<
|
||||
all_of<move_is_plain_type<T>,
|
||||
negation<is_copy_constructible<T>>,
|
||||
std::is_move_constructible<T>,
|
||||
is_move_constructible<T>,
|
||||
std::is_same<decltype(std::declval<make_caster<T>>().operator T &()), T &>>::value>>
|
||||
: std::true_type {};
|
||||
template <typename T, typename SFINAE = void>
|
||||
@ -975,7 +975,7 @@ struct move_if_unreferenced<
|
||||
enable_if_t<
|
||||
all_of<move_is_plain_type<T>,
|
||||
negation<move_always<T>>,
|
||||
std::is_move_constructible<T>,
|
||||
is_move_constructible<T>,
|
||||
std::is_same<decltype(std::declval<make_caster<T>>().operator T &()), T &>>::value>>
|
||||
: std::true_type {};
|
||||
template <typename T>
|
||||
|
@ -175,7 +175,7 @@ void construct(value_and_holder &v_h, Holder<Class> holder, bool need_alias) {
|
||||
template <typename Class>
|
||||
void construct(value_and_holder &v_h, Cpp<Class> &&result, bool need_alias) {
|
||||
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(need_alias);
|
||||
static_assert(std::is_move_constructible<Cpp<Class>>::value,
|
||||
static_assert(is_move_constructible<Cpp<Class>>::value,
|
||||
"pybind11::init() return-by-value factory function requires a movable class");
|
||||
if (Class::has_alias && need_alias) {
|
||||
construct_alias_from_cpp<Class>(is_alias_constructible<Class>{}, v_h, std::move(result));
|
||||
@ -190,7 +190,7 @@ void construct(value_and_holder &v_h, Cpp<Class> &&result, bool need_alias) {
|
||||
template <typename Class>
|
||||
void construct(value_and_holder &v_h, Alias<Class> &&result, bool) {
|
||||
static_assert(
|
||||
std::is_move_constructible<Alias<Class>>::value,
|
||||
is_move_constructible<Alias<Class>>::value,
|
||||
"pybind11::init() return-by-alias-value factory function requires a movable alias class");
|
||||
v_h.value_ptr() = new Alias<Class>(std::move(result));
|
||||
}
|
||||
|
@ -827,6 +827,9 @@ using movable_cast_op_type
|
||||
template <typename T, typename SFINAE = void>
|
||||
struct is_copy_constructible : std::is_copy_constructible<T> {};
|
||||
|
||||
template <typename T, typename SFINAE = void>
|
||||
struct is_move_constructible : std::is_move_constructible<T> {};
|
||||
|
||||
// Specialization for types that appear to be copy constructible but also look like stl containers
|
||||
// (we specifically check for: has `value_type` and `reference` with `reference = value_type&`): if
|
||||
// so, copy constructability depends on whether the value_type is copy constructible.
|
||||
@ -994,7 +997,7 @@ protected:
|
||||
return [](const void *arg) -> void * { return new T(*reinterpret_cast<const T *>(arg)); };
|
||||
}
|
||||
|
||||
template <typename T, typename = enable_if_t<std::is_move_constructible<T>::value>>
|
||||
template <typename T, typename = enable_if_t<is_move_constructible<T>::value>>
|
||||
static auto make_move_constructor(const T *)
|
||||
-> decltype(new T(std::declval<T &&>()), Constructor{}) {
|
||||
return [](const void *arg) -> void * {
|
||||
|
@ -155,6 +155,7 @@ set(PYBIND11_TEST_FILES
|
||||
test_tagbased_polymorphic
|
||||
test_thread
|
||||
test_union
|
||||
test_vector_unique_ptr_member
|
||||
test_virtual_functions)
|
||||
|
||||
# Invoking cmake with something like:
|
||||
|
56
tests/test_vector_unique_ptr_member.cpp
Normal file
56
tests/test_vector_unique_ptr_member.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
#include "pybind11_tests.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace pybind11_tests {
|
||||
namespace vector_unique_ptr_member {
|
||||
|
||||
struct DataType {};
|
||||
|
||||
// Reduced from a use case in the wild.
|
||||
struct VectorOwner {
|
||||
static std::unique_ptr<VectorOwner> Create(std::size_t num_elems) {
|
||||
return std::unique_ptr<VectorOwner>(
|
||||
new VectorOwner(std::vector<std::unique_ptr<DataType>>(num_elems)));
|
||||
}
|
||||
|
||||
std::size_t data_size() const { return data_.size(); }
|
||||
|
||||
private:
|
||||
explicit VectorOwner(std::vector<std::unique_ptr<DataType>> data) : data_(std::move(data)) {}
|
||||
|
||||
const std::vector<std::unique_ptr<DataType>> data_;
|
||||
};
|
||||
|
||||
} // namespace vector_unique_ptr_member
|
||||
} // namespace pybind11_tests
|
||||
|
||||
namespace pybind11 {
|
||||
namespace detail {
|
||||
|
||||
template <>
|
||||
struct is_copy_constructible<pybind11_tests::vector_unique_ptr_member::VectorOwner>
|
||||
: std::false_type {};
|
||||
|
||||
template <>
|
||||
struct is_move_constructible<pybind11_tests::vector_unique_ptr_member::VectorOwner>
|
||||
: std::false_type {};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace pybind11
|
||||
|
||||
using namespace pybind11_tests::vector_unique_ptr_member;
|
||||
|
||||
py::object py_cast_VectorOwner_ptr(VectorOwner *ptr) { return py::cast(ptr); }
|
||||
|
||||
// PYBIND11_SMART_HOLDER_TYPE_CASTERS(VectorOwner)
|
||||
|
||||
TEST_SUBMODULE(vector_unique_ptr_member, m) {
|
||||
py::class_<VectorOwner>(m, "VectorOwner")
|
||||
.def_static("Create", &VectorOwner::Create)
|
||||
.def("data_size", &VectorOwner::data_size);
|
||||
|
||||
m.def("py_cast_VectorOwner_ptr", py_cast_VectorOwner_ptr);
|
||||
}
|
14
tests/test_vector_unique_ptr_member.py
Normal file
14
tests/test_vector_unique_ptr_member.py
Normal file
@ -0,0 +1,14 @@
|
||||
import pytest
|
||||
|
||||
from pybind11_tests import vector_unique_ptr_member as m
|
||||
|
||||
|
||||
@pytest.mark.parametrize("num_elems", range(3))
|
||||
def test_create(num_elems):
|
||||
vo = m.VectorOwner.Create(num_elems)
|
||||
assert vo.data_size() == num_elems
|
||||
|
||||
|
||||
def test_cast():
|
||||
vo = m.VectorOwner.Create(0)
|
||||
assert m.py_cast_VectorOwner_ptr(vo) is vo
|
Loading…
Reference in New Issue
Block a user