-
Notifications
You must be signed in to change notification settings - Fork 70
Add more return value policy support #329
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
base: master
Are you sure you want to change the base?
Add more return value policy support #329
Conversation
- Add RVP defaults for free functions. - Add RVP default for assignment operators. - Add RVP customization per function. - Add test case and documentation for all of the above. - Add some new headings and refinements to config doc. - Add checks for correct +/- in config token parsing.
Before, there was a problematic edge case: a function with a custom rv policy set in the config for the unspecific function name, which has overloads where one returns some reference type, and hence needs an rv policy, but another overload that returns a non-reference type, would receive an rv policy in the bindings for both overloads. Now, the overload that does not require an rv policy to be set does not get one in the bindings.
|
Sure, done in #330. I cannot take this commit out of here though. If you want that, I'd have to start a new PR altogether. Do you want me to do that? In that case I think the new PR will have to be merged first though, as I think otherwise it might result in merge conflicts if I tried to apply the changes here to the main branch without the formatting first. |
|
Hey Sergey, just added another bit of quality-of-life here: RV policy specification for a whole class, as a convenient middle ground between whole-project defaults and having to specify policies for each function. Hope you like it :-) Cheers |
|
I have given this a bit more thought and here is a few idea/thoughts:
-- could you please elaborate on this? Ie in my view static function is effectively a free function that live in different namespace. Right now my vote will be to not add this one. -- re choosing reference_internal default_member_assignment_operator_return_value_policy: I am not sure about this, |
|
re default_member_assignment_operator_return_value_policy: the more I think about it then more it looks like this is highly depended on case-by-case basis. Could you please provide a justification why this category should have a separate config option? EDIT: and why just heaving " RVP customization per function" is not enough? |
Almost. Except for the static member functions, none of this should break existing Binder configs. Only if any of the new tokens are specified will they be used.
Well, they are not the same as far as C++ is concerned. Separating them gives a bit more flexibility, and is clearer. It was rather confusing to me to figure out that the RV policy setting for free functions is the "static" one... However, as mentioned, if I recall correctly, it might however not be backwards compatible, so that might need some tweaking if you want to fully maintain backwards compatible...
Assignment operators return an lvalue reference to
That feature allows to do this as well of course. But assignment operators are so common that I thought it might be worth defaulting all of them at once to a reasonable RV policy. |
|
Want to revisit this, re:
-- well, what else can Python do besides copy at this point? I mean this seems to be the only safe choice for default, would you agree? |
This PR adds more support for return value policies (RVP):
The RVPs for assignment operators (
operator=, but also all theoperator+=etc, see here) are an interesting case: When they are defaulted (implemented as= default;), they implicitly end withreturn *this;, returning the called instance itself. Thus, the pybind RVPautomaticis not the best choice for them, as it usescopyfor lvalue references. Instead,reference_internalis a better fit. Hence this addition, to separate those special functions from others.However, to not break backwards compatibility with previous Binder versions, I have implemented this such that
default_member_assignment_operator_return_value_policyis empty by default and not used unless explicitly set in the Binder config by the user. This is the least disruptive for existing bindings - although I'd argue that introducing a breaking change here and defaulting this toreference_internalmight be a good choice in terms of "least surprise" for users. It would probably not break any bindings code to go fromcopytoreference_internalfor assignment operators, as likely no one in Python will use the return value of an assignment anyway... But still it felt like the right thing to do. @lyskov, let me know what you think.While at it, I also refined some other parts:
I hope that was okay to mix this in here - @lyskov, let me know if you prefer that in a different PR instead.
Lastly, while playing around with this, I noticed that there are defaults for the return value policies of rvalue references, but Binder never actually emits bindings for such functions... I kept everything as it was (and even added rvalue references for free functions for completeness), but I was wondering if it's worth having those around. Or am I missing something and functions returning rvalue references can indeed be bound by Binder? If so, how?
Cheers and looking forward to hearing your thoughts
Lucas