Allow references to objects held by smart pointers (#533)

This commit is contained in:
Dean Moldovan
2016-12-07 02:36:44 +01:00
committed by Wenzel Jakob
parent 8c85a85747
commit ab90ec6ce9
5 changed files with 159 additions and 19 deletions

View File

@@ -860,20 +860,12 @@ public:
if (typeinfo->simple_type) { /* Case 1: no multiple inheritance etc. involved */
/* Check if we can safely perform a reinterpret-style cast */
if (PyType_IsSubtype(tobj, typeinfo->type)) {
auto inst = (instance<type, holder_type> *) src.ptr();
value = (void *) inst->value;
holder = inst->holder;
return true;
}
if (PyType_IsSubtype(tobj, typeinfo->type))
return load_value_and_holder(src);
} else { /* Case 2: multiple inheritance */
/* Check if we can safely perform a reinterpret-style cast */
if (tobj == typeinfo->type) {
auto inst = (instance<type, holder_type> *) src.ptr();
value = (void *) inst->value;
holder = inst->holder;
return true;
}
if (tobj == typeinfo->type)
return load_value_and_holder(src);
/* If this is a python class, also check the parents recursively */
auto const &type_dict = get_internals().registered_types_py;
@@ -902,6 +894,22 @@ public:
return false;
}
bool load_value_and_holder(handle src) {
auto inst = (instance<type, holder_type> *) src.ptr();
value = (void *) inst->value;
if (inst->holder_constructed) {
holder = inst->holder;
return true;
} else {
throw cast_error("Unable to cast from non-held to held instance (T& to Holder<T>) "
#if defined(NDEBUG)
"(compile in debug mode for type information)");
#else
"of type '" + type_id<holder_type>() + "''");
#endif
}
}
template <typename T = holder_type, detail::enable_if_t<!std::is_constructible<T, const T &, type*>::value, int> = 0>
bool try_implicit_casts(handle, bool) { return false; }

View File

@@ -1138,21 +1138,26 @@ private:
static void init_holder_helper(instance_type *inst, const holder_type * /* unused */, const std::enable_shared_from_this<T> * /* dummy */) {
try {
new (&inst->holder) holder_type(std::static_pointer_cast<typename holder_type::element_type>(inst->value->shared_from_this()));
inst->holder_constructed = true;
} catch (const std::bad_weak_ptr &) {
new (&inst->holder) holder_type(inst->value);
if (inst->owned) {
new (&inst->holder) holder_type(inst->value);
inst->holder_constructed = true;
}
}
inst->holder_constructed = true;
}
/// Initialize holder object, variant 2: try to construct from existing holder object, if possible
template <typename T = holder_type,
detail::enable_if_t<std::is_copy_constructible<T>::value, int> = 0>
static void init_holder_helper(instance_type *inst, const holder_type *holder_ptr, const void * /* dummy */) {
if (holder_ptr)
if (holder_ptr) {
new (&inst->holder) holder_type(*holder_ptr);
else
inst->holder_constructed = true;
} else if (inst->owned) {
new (&inst->holder) holder_type(inst->value);
inst->holder_constructed = true;
inst->holder_constructed = true;
}
}
/// Initialize holder object, variant 3: holder is not copy constructible (e.g. unique_ptr), always initialize from raw pointer