mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 05:05:11 +00:00
Fix py::cast from pytype rvalue to pytype (#3949)
* Fix py::cast from pytype rvalue to pytype Previously, py::cast blindly assumed that the destination type was a C++ type rather than a python type when the source type was an rvalue. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
48c7be4a56
commit
72eea20afd
@ -1009,6 +1009,8 @@ struct return_value_policy_override<
|
|||||||
// Basic python -> C++ casting; throws if casting fails
|
// Basic python -> C++ casting; throws if casting fails
|
||||||
template <typename T, typename SFINAE>
|
template <typename T, typename SFINAE>
|
||||||
type_caster<T, SFINAE> &load_type(type_caster<T, SFINAE> &conv, const handle &handle) {
|
type_caster<T, SFINAE> &load_type(type_caster<T, SFINAE> &conv, const handle &handle) {
|
||||||
|
static_assert(!detail::is_pyobject<T>::value,
|
||||||
|
"Internal error: type_caster should only be used for C++ types");
|
||||||
if (!conv.load(handle, true)) {
|
if (!conv.load(handle, true)) {
|
||||||
#if !defined(PYBIND11_DETAILED_ERROR_MESSAGES)
|
#if !defined(PYBIND11_DETAILED_ERROR_MESSAGES)
|
||||||
throw cast_error("Unable to cast Python instance to C++ type (#define "
|
throw cast_error("Unable to cast Python instance to C++ type (#define "
|
||||||
@ -1099,21 +1101,30 @@ detail::enable_if_t<!detail::move_never<T>::value, T> move(object &&obj) {
|
|||||||
// - If both movable and copyable, check ref count: if 1, move; otherwise copy
|
// - If both movable and copyable, check ref count: if 1, move; otherwise copy
|
||||||
// - Otherwise (not movable), copy.
|
// - Otherwise (not movable), copy.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
detail::enable_if_t<detail::move_always<T>::value, T> cast(object &&object) {
|
detail::enable_if_t<!detail::is_pyobject<T>::value && detail::move_always<T>::value, T>
|
||||||
|
cast(object &&object) {
|
||||||
return move<T>(std::move(object));
|
return move<T>(std::move(object));
|
||||||
}
|
}
|
||||||
template <typename T>
|
template <typename T>
|
||||||
detail::enable_if_t<detail::move_if_unreferenced<T>::value, T> cast(object &&object) {
|
detail::enable_if_t<!detail::is_pyobject<T>::value && detail::move_if_unreferenced<T>::value, T>
|
||||||
|
cast(object &&object) {
|
||||||
if (object.ref_count() > 1) {
|
if (object.ref_count() > 1) {
|
||||||
return cast<T>(object);
|
return cast<T>(object);
|
||||||
}
|
}
|
||||||
return move<T>(std::move(object));
|
return move<T>(std::move(object));
|
||||||
}
|
}
|
||||||
template <typename T>
|
template <typename T>
|
||||||
detail::enable_if_t<detail::move_never<T>::value, T> cast(object &&object) {
|
detail::enable_if_t<!detail::is_pyobject<T>::value && detail::move_never<T>::value, T>
|
||||||
|
cast(object &&object) {
|
||||||
return cast<T>(object);
|
return cast<T>(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pytype rvalue -> pytype (calls converting constructor)
|
||||||
|
template <typename T>
|
||||||
|
detail::enable_if_t<detail::is_pyobject<T>::value, T> cast(object &&object) {
|
||||||
|
return T(std::move(object));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T object::cast() const & {
|
T object::cast() const & {
|
||||||
return pybind11::cast<T>(*this);
|
return pybind11::cast<T>(*this);
|
||||||
|
@ -289,4 +289,7 @@ TEST_SUBMODULE(copy_move_policies, m) {
|
|||||||
py::return_value_policy::move);
|
py::return_value_policy::move);
|
||||||
m.def(
|
m.def(
|
||||||
"get_moveissue2", [](int i) { return MoveIssue2(i); }, py::return_value_policy::move);
|
"get_moveissue2", [](int i) { return MoveIssue2(i); }, py::return_value_policy::move);
|
||||||
|
|
||||||
|
// Make sure that cast from pytype rvalue to other pytype works
|
||||||
|
m.def("get_pytype_rvalue_castissue", [](double i) { return py::float_(i).cast<py::int_>(); });
|
||||||
}
|
}
|
||||||
|
@ -123,3 +123,10 @@ def test_move_fallback():
|
|||||||
assert m1.value == 1
|
assert m1.value == 1
|
||||||
m2 = m.get_moveissue2(2)
|
m2 = m.get_moveissue2(2)
|
||||||
assert m2.value == 2
|
assert m2.value == 2
|
||||||
|
|
||||||
|
|
||||||
|
def test_pytype_rvalue_cast():
|
||||||
|
"""Make sure that cast from pytype rvalue to other pytype works"""
|
||||||
|
|
||||||
|
value = m.get_pytype_rvalue_castissue(1.0)
|
||||||
|
assert value == 1
|
||||||
|
Loading…
Reference in New Issue
Block a user