-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consider making the default policy for const T&
arguments more friendly for non-copyable classes in callbacks
#1241
Comments
return_value_policy::copy
more friendly for non-copyable non-movable classes in callbacksconst T&
arguments more friendly for non-copyable non-movable classes in callbacks
const T&
arguments more friendly for non-copyable non-movable classes in callbacksconst T&
arguments more friendly for non-copyable classes in callbacks
Some food for thought. Here's an implementation of 2, but I'll say in advance that I don't really like this (because it only works around the issue for this one particular case, rather than solving it more generally): In template <typename Arg> inline object functional_arg_cast(Arg &&arg) {
constexpr return_value_policy rvp = is_copy_constructible<remove_reference_t<Arg>>::value
? return_value_policy::automatic_reference
: return_value_policy::reference;
return cast(std::forward<Arg>(arg), rvp);
} then amend the Python function call in the object retval(func(std::forward<Args>(args)...)); to: object retval(func(functional_arg_cast(std::forward<Args>(args))...)); But in terms of addressing the core issue, the main problems (mainly just dumping my thoughts on it here) look to me like this: We need to be able to pass in an rvp to apply to each function argument in the lambda. This is trickier than it seems, partly because passing just one value won't do: a binding might have multiple m.def("foo", [](
std::function<void(const A &, const B &)> f1,
std::function<void(const C &, D *)> f2) { /* ... */ }) The nicest way I can think about to specify that is through the m.def("foo", [](
std::function<void(const A &, const B &)> f1,
std::function<void(const C &, const D &)> f2) { /* ... */ },
py::arg().arg_rvp({py::return_value_policy::reference, py::return_value_policy::copy}),
py::arg().arg_rvp({py::return_value_policy::reference, py::return_value_policy::take_ownership})
); (of course there's no reason you couldn't also name the argument, e.g. The issue is then how to get that into the [Edit: fixed bad C++ in |
Sorry for the late follow-up, but thank you for the follow-up! I may try to incorporate this in our fork. Do you have an issue tracking this feature already? From the looks of it, That, or ensure that the user has bound the appropriate method in the base class, and then in |
pybind11::cast_error: return_value_policy = copy, but the object is non-copyable! May be the same/related issue as described here: pybind#1241
See our See unittests on template metaprogramming stuff: |
pybind11::cast_error: return_value_policy = copy, but the object is non-copyable! May be the same/related issue as described here: pybind#1241 Adapted from: kefeimo/pybind11@338d615
Follow-up from #1240 (#1200).
We disable copying and moving (not that moving is relevant here) for a set of virtual classes, because we would like to have a compile-time guarantee that we are not slicing classes. This generally has no issue in
pybind
, until callbacks are used, in which case theconst T&
instance may not be registered, and thuspybind
tries to copy it, and then throws a runtime error.Potential solutions:
type_caster_base::cast(const T&)
to check forautomatic
and if the class is non-copyableand non-movable, default toreference
rather thancopy
.My workaround for the time being will be to wrap any callbacks (Python callbacks cast into
std::function<...>
) that haveconst T&
references to useconst T*
instead.The text was updated successfully, but these errors were encountered: