-
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
Revising the design of type_caster<T>::load() #864
Comments
A few comments (for now):
but it would be very nifty to be able to get something like:
With |
+1 for making type casters "public", I've written a fair share of custom type casters and it always feels a bit wrong to specialize things in A bit of bikeshedding: static maybe<U> load(handle src, bool convert) {
if (auto maybe_value = make_caster<T>::load(src, convert))
return maybe_value.extract<T>();
return {};
} could even be static maybe<U> load(handle src, bool convert) {
return make_caster<T>::load(src, convert).try_extract<T>();
} if it's a common pattern; or something like that (also
And an additional disadvantage of being potentially slower, depending on the exception model... |
One thing that #916 exposes is that a |
This is a sensible proposal, and I'm open to a significant departure from the current API (which works, but is by no means elegant). One important aspect that hasn't been mentioned above is that the new interface and |
Another couple of things to think about on this topic:
|
Currently, type casters defined using
PYBIND11_TYPE_CASTER
require that the C++ type is default-constructible and copy/move-assignable. Apart from the fact that not all types fulfill these requirements, doing default init + assign is less efficient than directly constructing an object (both binary size and runtime overhead). There are also possible complications as in the case of #850 where an additional helper struct and specialization are required but could be avoided with a differentload()
design.The proposal
The idea is to make
type_caster<T>::load()
a static function which returns an optional-like container. Looking only at the load-specific parts, a type caster currently looks like this:This proposal changes it to:
Where
maybe<T, ExtractionPolicy>
is an optional-like container with some simplifications and specializations for the purpose of pybind11's casters (namedmaybe
to avoid confusion with the standardoptional
). Here, theExtractionPolicy
template parameter takes on the job ofcast_op_type
and the cast operators. The default policy is the same as defined byPYBIND11_TYPE_CASTER
which makesmaybe<T>
the only thing needed for user-defined casters. This also drastically reduces the footprint of thePYBIND11_TYPE_CASTER
macro.This would also simplify usage:
The behavior of
maybe::extract<T>()
is determined by theExtractionPolicy
. Given that these containers have a very special purpose and are only used once, the default policy could move whenT
is a value or rvalue ref (to simplify caster code).Backward compatibility
Existing user-defined casters would still function either by inserting a compatibility layer into
PYBIND11_TYPE_CASTER
or by using SFINAE in pybind11 internals (only if compatibility is required for user-defined casters which do not use thePYBIND11_TYPE_CASTER
macro).If this whole proposal sounds good, this might also be a good time to consider moving user-defined casters out of the
detail
namespace.PR
I have a rough working prototype and I can turn this into a PR if the proposal sounds acceptable. I think that reducing the footprint of the
PYBIND11_TYPE_CASTER
macro and lifting the default constructor + assignment requirements would be a nice improvement.The text was updated successfully, but these errors were encountered: