Skip to content

Commit

Permalink
Fix smart_holder multiple inheritance tests
Browse files Browse the repository at this point in the history
The original pybind11 holder supported multiple inheritance by recursively creating
type casters until it finds one for the source type, then converting each
value in turn to the next type via typeinfo->implicit_cast

The smart_holder only stored the last implicit_cast, which was incorrect.

This commit changes it to create a list of implicit_cast functions that are
appended to during the recursive type caster creation, and when the time comes
to cast to the destination type, it calls all of them in the correct order.
  • Loading branch information
virtuald committed Jan 27, 2022
1 parent 152bb10 commit a6c47cc
Showing 1 changed file with 9 additions and 5 deletions.
14 changes: 9 additions & 5 deletions include/pybind11/detail/smart_holder_type_casters.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ class modified_type_caster_generic_load_impl {
}
loaded_v_h = sub_caster.loaded_v_h;
loaded_v_h_cpptype = cast.first;
implicit_cast = cast.second;
// the sub_caster is being discarded, so steal its vector
implicit_casts = std::move(sub_caster.implicit_casts);
implicit_casts.emplace_back(cast.second);
return true;
}
}
Expand Down Expand Up @@ -149,7 +151,7 @@ class modified_type_caster_generic_load_impl {
}
loaded_v_h = foreign_loader->loaded_v_h;
loaded_v_h_cpptype = foreign_loader->loaded_v_h_cpptype;
implicit_cast = foreign_loader->implicit_cast;
implicit_casts = foreign_loader->implicit_casts; // SMART_HOLDER_WIP: should this be a copy or move?
return true;
}
return false;
Expand Down Expand Up @@ -251,7 +253,7 @@ class modified_type_caster_generic_load_impl {
const std::type_info *cpptype = nullptr;
void *unowned_void_ptr_from_direct_conversion = nullptr;
const std::type_info *loaded_v_h_cpptype = nullptr;
void *(*implicit_cast)(void *) = nullptr;
std::vector<void *(*)(void *)> implicit_casts;
value_and_holder loaded_v_h;
bool reinterpret_cast_deemed_ok = false;
// Magic number intentionally hard-coded, to guard against class_ holder mixups.
Expand Down Expand Up @@ -521,8 +523,10 @@ struct smart_holder_type_caster_load {

T *convert_type(void *void_ptr) const {
if (void_ptr != nullptr && load_impl.loaded_v_h_cpptype != nullptr
&& !load_impl.reinterpret_cast_deemed_ok && load_impl.implicit_cast != nullptr) {
void_ptr = load_impl.implicit_cast(void_ptr);
&& !load_impl.reinterpret_cast_deemed_ok && !load_impl.implicit_casts.empty()) {
for (auto implicit_cast: load_impl.implicit_casts) {
void_ptr = implicit_cast(void_ptr);
}
}
return static_cast<T *>(void_ptr);
}
Expand Down

0 comments on commit a6c47cc

Please sign in to comment.