Skip to content

Commit 12c38af

Browse files
committed
Fix remaining issues
To ensure constness of reference arguments passed to overridden functions, these should be copied instead of referenced. However, this doesn't apply to const unique_ptr&, which should be referenced in any case. To this end, introduce a new return_value_policy: reference_override
1 parent d0c3b16 commit 12c38af

File tree

5 files changed

+28
-8
lines changed

5 files changed

+28
-8
lines changed

include/pybind11/detail/common.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,14 @@ enum class return_value_policy : uint8_t {
434434
collected while Python is still using the child. More advanced
435435
variations of this scheme are also possible using combinations of
436436
return_value_policy::reference and the keep_alive call policy */
437-
reference_internal
437+
reference_internal,
438+
439+
/** This internally used policy only applies to C++ arguments passed
440+
to virtual methods overridden in Python. This effectively will result
441+
in the return_value_policy::reference policy usually.
442+
It is needed to suppress copying of const unique_ptr, which is
443+
otherwise applied to const refererences to ensure constness. */
444+
reference_override
438445
};
439446

440447
PYBIND11_NAMESPACE_BEGIN(detail)

include/pybind11/detail/smart_holder_type_casters.h

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -474,15 +474,23 @@ struct smart_holder_type_caster : smart_holder_type_caster_load<T>,
474474
static handle cast(T const &src, return_value_policy policy, handle parent) {
475475
// type_caster_base BEGIN
476476
// clang-format off
477-
if (policy == return_value_policy::automatic || policy == return_value_policy::automatic_reference)
478-
policy = return_value_policy::copy;
479-
return cast(&src, policy, parent);
477+
if (policy == return_value_policy::automatic ||
478+
policy == return_value_policy::automatic_reference ||
479+
policy == return_value_policy::reference_override)
480+
policy = return_value_policy::copy; // copy ensures constness
480481
// clang-format on
482+
return cast(&src, policy, parent);
481483
// type_caster_base END
482484
}
483485

484486
static handle cast(T &src, return_value_policy policy, handle parent) {
485-
return cast(const_cast<T const &>(src), policy, parent); // Mutbl2Const
487+
// type_caster_base BEGIN
488+
// clang-format off
489+
if (policy == return_value_policy::automatic || policy == return_value_policy::automatic_reference)
490+
policy = return_value_policy::reference;
491+
return cast(&src, policy, parent);
492+
// clang-format on
493+
// type_caster_base END
486494
}
487495

488496
static handle cast(T const *src, return_value_policy policy, handle parent) {
@@ -559,6 +567,7 @@ struct smart_holder_type_caster : smart_holder_type_caster_load<T>,
559567

560568
case return_value_policy::automatic_reference:
561569
case return_value_policy::reference:
570+
case return_value_policy::reference_override:
562571
valueptr = src;
563572
wrapper->owned = false;
564573
break;
@@ -723,7 +732,9 @@ struct smart_holder_type_caster<std::unique_ptr<T, D>> : smart_holder_type_caste
723732
return none().release();
724733
if (policy == return_value_policy::automatic)
725734
policy = return_value_policy::reference_internal;
726-
if (policy != return_value_policy::reference_internal)
735+
else if (policy == return_value_policy::reference_override)
736+
policy = return_value_policy::reference;
737+
else if (policy != return_value_policy::reference_internal)
727738
throw cast_error("Invalid return_value_policy for unique_ptr&");
728739
return smart_holder_type_caster<T>::cast(src.get(), policy, parent);
729740
}

include/pybind11/detail/type_caster_base.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,7 @@ class type_caster_generic {
527527

528528
case return_value_policy::automatic_reference:
529529
case return_value_policy::reference:
530+
case return_value_policy::reference_override:
530531
valueptr = src;
531532
wrapper->owned = false;
532533
break;

include/pybind11/eigen.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ struct type_caster<Type, enable_if_t<is_eigen_dense_plain<Type>::value>> {
303303
return eigen_array_cast<props>(*src);
304304
case return_value_policy::reference:
305305
case return_value_policy::automatic_reference:
306+
case return_value_policy::reference_override:
306307
return eigen_ref_array<props>(*src);
307308
case return_value_policy::reference_internal:
308309
return eigen_ref_array<props>(*src, parent);

include/pybind11/pytypes.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,9 @@ class object_api : public pyobject_tag {
105105
function will throw a `cast_error` exception. When the Python function
106106
call fails, a `error_already_set` exception is thrown.
107107
\endrst */
108-
template <return_value_policy policy = return_value_policy::reference, typename... Args>
108+
template <return_value_policy policy = return_value_policy::reference_override, typename... Args>
109109
object operator()(Args &&...args) const;
110-
template <return_value_policy policy = return_value_policy::reference, typename... Args>
110+
template <return_value_policy policy = return_value_policy::reference_override, typename... Args>
111111
PYBIND11_DEPRECATED("call(...) was deprecated in favor of operator()(...)")
112112
object call(Args&&... args) const;
113113

0 commit comments

Comments
 (0)