| 2315 | |
| 2316 | template <typename... Extra> |
| 2317 | class_(handle scope, const char *name, const Extra &...extra) { |
| 2318 | using namespace detail; |
| 2319 | |
| 2320 | // MI can only be specified via class_ template options, not constructor parameters |
| 2321 | static_assert( |
| 2322 | none_of<is_pyobject<Extra>...>::value || // no base class arguments, or: |
| 2323 | (constexpr_sum(is_pyobject<Extra>::value...) == 1 && // Exactly one base |
| 2324 | constexpr_sum(is_base<options>::value...) == 0 && // no template option bases |
| 2325 | // no multiple_inheritance attr |
| 2326 | none_of<std::is_same<multiple_inheritance, Extra>...>::value), |
| 2327 | "Error: multiple inheritance bases must be specified via class_ template options"); |
| 2328 | |
| 2329 | type_record record; |
| 2330 | record.scope = scope; |
| 2331 | record.name = name; |
| 2332 | record.type = &typeid(type); |
| 2333 | record.type_size = sizeof(conditional_t<has_alias, type_alias, type>); |
| 2334 | record.type_align = alignof(conditional_t<has_alias, type_alias, type> &); |
| 2335 | record.holder_size = sizeof(holder_type); |
| 2336 | record.init_instance = init_instance; |
| 2337 | |
| 2338 | if (detail::is_instantiation<std::unique_ptr, holder_type>::value) { |
| 2339 | record.holder_enum_v = detail::holder_enum_t::std_unique_ptr; |
| 2340 | } else if (detail::is_instantiation<std::shared_ptr, holder_type>::value) { |
| 2341 | record.holder_enum_v = detail::holder_enum_t::std_shared_ptr; |
| 2342 | } else if (std::is_same<holder_type, smart_holder>::value) { |
| 2343 | record.holder_enum_v = detail::holder_enum_t::smart_holder; |
| 2344 | } else { |
| 2345 | record.holder_enum_v = detail::holder_enum_t::custom_holder; |
| 2346 | } |
| 2347 | |
| 2348 | set_operator_new<type>(&record); |
| 2349 | |
| 2350 | /* Register base classes specified via template arguments to class_, if any */ |
| 2351 | PYBIND11_EXPAND_SIDE_EFFECTS(add_base<options>(record)); |
| 2352 | |
| 2353 | /* Process optional arguments, if any */ |
| 2354 | process_attributes<Extra...>::init(extra..., &record); |
| 2355 | |
| 2356 | if (record.release_gil_before_calling_cpp_dtor) { |
| 2357 | record.dealloc = dealloc_release_gil_before_calling_cpp_dtor; |
| 2358 | } else { |
| 2359 | record.dealloc = dealloc_without_manipulating_gil; |
| 2360 | } |
| 2361 | |
| 2362 | if (std::is_base_of<trampoline_self_life_support, type_alias>::value) { |
| 2363 | // Store a cross-DSO-safe getter. |
| 2364 | // This lambda is defined in the same DSO that instantiates |
| 2365 | // class_<type, alias_type>, but it can be called safely from any other DSO. |
| 2366 | record.get_trampoline_self_life_support = [](void *type_ptr) { |
| 2367 | return dynamic_raw_ptr_cast_if_possible<trampoline_self_life_support>( |
| 2368 | static_cast<type *>(type_ptr)); |
| 2369 | }; |
| 2370 | } |
| 2371 | |
| 2372 | generic_type::initialize(record); |
| 2373 | |
| 2374 | if (has_alias) { |
nothing calls this directly
no test coverage detected