Skip to content
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

Priority overload #1131

Merged
merged 6 commits into from
Oct 6, 2020
Merged

Priority overload #1131

merged 6 commits into from
Oct 6, 2020

Conversation

henryiii
Copy link
Collaborator

@henryiii henryiii commented Oct 9, 2017

Adds py::prepend() as an optional tag when defining a function, which causes an added function to be prepended to the beginning of the overload chain. This can be used to override a default constructor that was provided earlier, for example. When combined with #1122, this will allow the default string (or the old int) constructors for enums to be replaced by users.

No performance penalty, it just prepends instead of appends to the call chain. Provides a possible solution to, and docs for, so closes #2537, so targeting 2.6.0 (related to the original use case, actually :) )

Also adds get_pointer/set_pointer for py::capsule.

@wjakob
Copy link
Member

wjakob commented Oct 9, 2017

Although I understand the motivation, I'm not in favor of this modification, which further increases the runtime cost and complexity of an already very complex dispatch routine. I think that we ought to make this part of pybind11 shorter and faster, not the other way.

@henryiii
Copy link
Collaborator Author

henryiii commented Oct 9, 2017

Does this increase the runtime? All it does is allow someone to attach a function at the beginning of the overload chain instead of the end, but the overload chain is the same length either way. It doesn't even increase the size of the struct, since there's one bit left over for alignment. So in the setup (runtime) phase, it adds one if statement.

This functionality seems useful in a more general case, where a user needs to pre-insert a call. But up to you.

@wjakob
Copy link
Member

wjakob commented Oct 9, 2017

Aha -- I misread the patch in that case. I was assuming that the priority tag was handled in the method dispatch function, but I see now that it is in the part of the code that creates Python function overloads.

I've recently heard from users who found that Boost.Python dispatches methods faster than pybind11 (!?!?), which still has me a bit concerned that we are piling on too much stuff.

@wjakob
Copy link
Member

wjakob commented Oct 9, 2017

One naming suggestion: how about calling it py::prepend or py::prepend_overload instead of priority_overload, which is IMO a bit more clear in terms of what happens (preventing question s like: "what does it mean to have two priority overloads?").

@henryiii
Copy link
Collaborator Author

I took the name from the original comment from @jagerman, I don't think he meant it to be final. I like py::prepend.

Unrelated: Any numbers or profile code for the boost Python comparison?

@jagerman
Copy link
Member

prepend sounds fine to me. priority_overload was just a spur-of-the-moment name.

@henryiii henryiii changed the title Priority overload WIP: Priority overload Oct 10, 2017
@wjakob
Copy link
Member

wjakob commented Oct 11, 2017

Unrelated: Any numbers or profile code for the boost Python comparison?

Unfortunately we don't currently have a good way of tracking performance over time, which is a bit of a concern. It would be nice to have a CI to catch performance regressions similarly to how we catch bugs with Travis and friends. I played around with Unladen Swallow at some point but haven't had enough free clock cycles to turn it into something useful.

@jagerman
Copy link
Member

I've pushed a commit to your branch that ought to get this working (a86451d). Basically the start of the chain was only being half-updated: it also needed to be updated inside the capsule rec_capsule that gets bound as the self argument for dispatcher because dispatcher starts from that pointer, not the local chain_start variable (which only gets used to regenerate the docstring).

@henryiii
Copy link
Collaborator Author

henryiii commented Nov 1, 2017

FYI, I'll polish off the tests as soon as I get a chance, hopefully around this weekend.

@henryiii henryiii changed the title WIP: Priority overload Priority overload Apr 4, 2018
@henryiii
Copy link
Collaborator Author

henryiii commented Apr 4, 2018

@jagerman That was a very long weekend, but it should be ready for review finally!

Copy link
Member

@jagerman jagerman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two very minor comments, aside from those it looks good to me.

include/pybind11/attr.h Outdated Show resolved Hide resolved
tests/test_methods_and_attributes.cpp Outdated Show resolved Hide resolved
@henryiii
Copy link
Collaborator Author

Could this be useful in 2.3.0?

@henryiii henryiii added this to the v2.6.0 milestone Oct 2, 2020
@henryiii
Copy link
Collaborator Author

henryiii commented Oct 2, 2020

Maybe we could also add a mention in the upgrade guide that __str__ on enums is now defined, so you need to use py::prepend() to override?

Copy link
Collaborator

@rwgk rwgk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! I have just some minor naming suggestions.

include/pybind11/attr.h Outdated Show resolved Hide resolved
include/pybind11/attr.h Outdated Show resolved Hide resolved
docs/classes.rst Outdated Show resolved Hide resolved
Copy link
Collaborator

@YannickJadoul YannickJadoul left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be rather painless, I think, yes :-)

include/pybind11/pybind11.h Show resolved Hide resolved
include/pybind11/pybind11.h Show resolved Hide resolved
Copy link
Collaborator

@rwgk rwgk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR was included in Google-global testing: no issues found.

Copy link
Member

@wjakob wjakob left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation looks all good to me, but documentation could be improved IMO.

docs/classes.rst Outdated Show resolved Hide resolved
include/pybind11/attr.h Outdated Show resolved Hide resolved
@wjakob
Copy link
Member

wjakob commented Oct 5, 2020

(Really sorry that this has been stuck here in 2017. The flurry of recent activity has been wonderful -- thank you for all of your help! @henryiii @YannickJadoul @bstaletic @rwgk @EricCousineau-TRI and @ax3l)

@wjakob
Copy link
Member

wjakob commented Oct 5, 2020

My vote would also go for set_pointer btw, it promotes clarity.

I feel less strongly about the following: For consistency, we could also have a get_pointer. We will need to continue to provide the operator-based getter, but it could be implemented in terms of this new get_pointer function.

@henryiii
Copy link
Collaborator Author

henryiii commented Oct 5, 2020

FWIW, I would be in favor of adding a .get_pointer() too, for consistency, and I think it's a bit more discoverable (ie, Xcode would show it in a completion list while conversions don't show up).

@henryiii henryiii force-pushed the priority_overload branch 2 times, most recently from d34a67a to 92268fd Compare October 5, 2020 20:45
@henryiii henryiii merged commit 9a0c96d into pybind:master Oct 6, 2020
@henryiii henryiii deleted the priority_overload branch October 6, 2020 02:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[BUG] Allow for __str__ to be usable with enums (again)
5 participants