-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
Improve custom holder support #607
Conversation
@@ -206,6 +214,18 @@ struct SharedFromThisRef { | |||
std::shared_ptr<B> shared = std::make_shared<B>(); | |||
}; | |||
|
|||
template <typename T> | |||
class UniquePtr { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would give this a different name to make explicit that one doesn't want to do this for std::unique_ptr
. E.g. CustomUniquePtr
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. I'll rename it.
static void init_holder_from_existing(instance_type *inst, const holder_type *holder_ptr, | ||
std::false_type /*is_copy_constructible*/) { | ||
new (&inst->holder) holder_type(std::move(*const_cast<holder_type *>(holder_ptr))); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps add a two argument version to dispatch?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I follow. Two argument version of what?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean adding static void init_holder_from_existing(instance_type *inst, const holder_type *holder_ptr)
to dispatch between the two options.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think another layer of abstraction is needed here since this is all implementation detail and the intent should be clear from init_holder_helper
right below.
This PR also fixes #608. The issue there was that |
Custom holder types which don't have `.get()` can select the correct function to call by specializing `holder_traits`.
This looks great, thank you! |
This PR resolves issues #585 and #605.
Adds a helper struct to abstract away the holder's
.get()
function as suggested by @aldanor in Working with a homebrewed shared pointer type that does not implement .get() #585. This is only required for type's with a renamed.get()
.An alternative solution would be to use just a function instead of the struct, but in that case, the user-provided overload would need to be placed either in the global namespace or in the same namespace as the custom holder (ADL rules) which could possibly conflict with existing functions.
Support for custom move-only holders. It seems that so far only
std::unique_ptr
worked properly. For move-only typesinit_holder_helper
would create a new holder from a raw pointer. This works forstd::unique_ptr
because itstype_caster
specialization would call.release()
. However, custom move-only holders were handled usingtype_caster_holder
which does not call.release()
leading to the issue reported in Custom owning pointer #605.This PR renames
type_caster_holder
tocopyable_holder_caster
and adds amove_only_holder_caster
. Thetype_caster<std::unique_ptr<type, deleter>>
is removed in favor ofmove_only_holder_caster
which does the same job but accepts any move-only holder. Instead of calling.release()
on the moved-out pointer, this is now handled by the move constructor ininit_holder_helper
. This is a more portable solution since the custom holder type might not have a.release()
function.An alternative solution would be to handle all holders using one
type_caster_holder
, but this would require some ugly SFINAE to disable.load()
for move-only holders and forcast()
to accept copyable holders only byconst holder_type &
and move-only byholder_type &&
.