Skip to content

Commit fd8265e

Browse files
authored
Fix smart_holder multiple inheritance tests (#3635)
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.
1 parent b2f0b09 commit fd8265e

File tree

1 file changed

+9
-5
lines changed

1 file changed

+9
-5
lines changed

include/pybind11/detail/smart_holder_type_casters.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,9 @@ class modified_type_caster_generic_load_impl {
9999
}
100100
loaded_v_h = sub_caster.loaded_v_h;
101101
loaded_v_h_cpptype = cast.first;
102-
implicit_cast = cast.second;
102+
// the sub_caster is being discarded, so steal its vector
103+
implicit_casts = std::move(sub_caster.implicit_casts);
104+
implicit_casts.emplace_back(cast.second);
103105
return true;
104106
}
105107
}
@@ -180,7 +182,7 @@ class modified_type_caster_generic_load_impl {
180182
}
181183
loaded_v_h = foreign_loader->loaded_v_h;
182184
loaded_v_h_cpptype = foreign_loader->loaded_v_h_cpptype;
183-
implicit_cast = foreign_loader->implicit_cast;
185+
implicit_casts = foreign_loader->implicit_casts; // SMART_HOLDER_WIP: should this be a copy or move?
184186
return true;
185187
}
186188
return false;
@@ -286,7 +288,7 @@ class modified_type_caster_generic_load_impl {
286288
void *unowned_void_ptr_from_direct_conversion = nullptr;
287289
void *unowned_void_ptr_from_void_ptr_capsule = nullptr;
288290
const std::type_info *loaded_v_h_cpptype = nullptr;
289-
void *(*implicit_cast)(void *) = nullptr;
291+
std::vector<void *(*)(void *)> implicit_casts;
290292
value_and_holder loaded_v_h;
291293
bool reinterpret_cast_deemed_ok = false;
292294
// Magic number intentionally hard-coded, to guard against class_ holder mixups.
@@ -567,8 +569,10 @@ struct smart_holder_type_caster_load {
567569

568570
T *convert_type(void *void_ptr) const {
569571
if (void_ptr != nullptr && load_impl.loaded_v_h_cpptype != nullptr
570-
&& !load_impl.reinterpret_cast_deemed_ok && load_impl.implicit_cast != nullptr) {
571-
void_ptr = load_impl.implicit_cast(void_ptr);
572+
&& !load_impl.reinterpret_cast_deemed_ok && !load_impl.implicit_casts.empty()) {
573+
for (auto implicit_cast: load_impl.implicit_casts) {
574+
void_ptr = implicit_cast(void_ptr);
575+
}
572576
}
573577
return static_cast<T *>(void_ptr);
574578
}

0 commit comments

Comments
 (0)