Skip to content

Commit 8449c76

Browse files
committed
Better? implementation for previous commit
This avoids the introduction of a new return_value_policy. And it enforces copying of const pointers/references to ensure constness.
1 parent 7f4d872 commit 8449c76

File tree

6 files changed

+15
-27
lines changed

6 files changed

+15
-27
lines changed

include/pybind11/detail/common.h

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -434,14 +434,7 @@ 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,
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
437+
reference_internal
445438
};
446439

447440
PYBIND11_NAMESPACE_BEGIN(detail)

include/pybind11/detail/smart_holder_type_casters.h

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -473,13 +473,7 @@ struct smart_holder_type_caster : smart_holder_type_caster_load<T>,
473473

474474
static handle cast(T const &src, return_value_policy policy, handle parent) {
475475
// type_caster_base BEGIN
476-
// clang-format off
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
481-
// clang-format on
482-
return cast(&src, policy, parent);
476+
return cast(&src, policy, parent); // copy ensures constness
483477
// type_caster_base END
484478
}
485479

@@ -494,6 +488,14 @@ struct smart_holder_type_caster : smart_holder_type_caster_load<T>,
494488
}
495489

496490
static handle cast(T const *src, return_value_policy policy, handle parent) {
491+
// enforce constness by using policy return_value_policy::copy
492+
// The only exception is reference_internal, which can be used to ignore constness
493+
if (policy != return_value_policy::reference_internal)
494+
policy = return_value_policy::copy;
495+
return cast(const_cast<T *>(src), policy, parent);
496+
}
497+
498+
static handle cast(T *src, return_value_policy policy, handle parent) {
497499
auto st = type_caster_base<T>::src_and_type(src);
498500
return cast_const_raw_ptr( // Originally type_caster_generic::cast.
499501
st.first,
@@ -504,10 +506,6 @@ struct smart_holder_type_caster : smart_holder_type_caster_load<T>,
504506
make_constructor::make_move_constructor(src));
505507
}
506508

507-
static handle cast(T *src, return_value_policy policy, handle parent) {
508-
return cast(const_cast<T const *>(src), policy, parent); // Mutbl2Const
509-
}
510-
511509
#if defined(_MSC_VER) && _MSC_VER < 1910
512510
// Working around MSVC 2015 bug. const-correctness is lost.
513511
// SMART_HOLDER_WIP: IMPROVABLE: make common code work with MSVC 2015.
@@ -567,7 +565,6 @@ struct smart_holder_type_caster : smart_holder_type_caster_load<T>,
567565

568566
case return_value_policy::automatic_reference:
569567
case return_value_policy::reference:
570-
case return_value_policy::reference_override:
571568
valueptr = src;
572569
wrapper->owned = false;
573570
break;
@@ -732,8 +729,8 @@ struct smart_holder_type_caster<std::unique_ptr<T, D>> : smart_holder_type_caste
732729
return none().release();
733730
if (policy == return_value_policy::automatic)
734731
policy = return_value_policy::reference_internal;
735-
else if (policy == return_value_policy::reference_override)
736-
policy = return_value_policy::reference;
732+
// allow reference only for overridden method calls (parent is None)
733+
else if (policy == return_value_policy::reference && !parent);
737734
else if (policy != return_value_policy::reference_internal)
738735
throw cast_error("Invalid return_value_policy for unique_ptr&");
739736
return smart_holder_type_caster<T>::cast(src.get(), policy, parent);

include/pybind11/detail/type_caster_base.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,6 @@ 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:
531530
valueptr = src;
532531
wrapper->owned = false;
533532
break;

include/pybind11/eigen.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,6 @@ 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:
307306
return eigen_ref_array<props>(*src);
308307
case return_value_policy::reference_internal:
309308
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_override, typename... Args>
108+
template <return_value_policy policy = return_value_policy::reference, typename... Args>
109109
object operator()(Args &&...args) const;
110-
template <return_value_policy policy = return_value_policy::reference_override, typename... Args>
110+
template <return_value_policy policy = return_value_policy::reference, typename... Args>
111111
PYBIND11_DEPRECATED("call(...) was deprecated in favor of operator()(...)")
112112
object call(Args&&... args) const;
113113

tests/test_class_sh_basic.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def check_regex(expected, actual):
2929
(m.rtrn_rref, "rtrn_rref(_MvCtor){1}"),
3030
(m.rtrn_cref, "rtrn_cref_CpCtor"),
3131
(m.rtrn_mref, "rtrn_mref"),
32-
(m.rtrn_cptr, "rtrn_cptr"),
32+
(m.rtrn_cptr, "rtrn_cptr_CpCtor"),
3333
(m.rtrn_mptr, "rtrn_mptr"),
3434
(m.rtrn_shmp, "rtrn_shmp"),
3535
(m.rtrn_shcp, "rtrn_shcp"),

0 commit comments

Comments
 (0)