@@ -820,6 +820,34 @@ struct extract_first<Predicate, T, Ts...> {
820820 >::type;
821821};
822822
823+
824+ template <template <class > class Predicate , class ... Ts>
825+ struct extract_all ;
826+
827+ template <template <class > class Predicate >
828+ struct extract_all <Predicate> {
829+ using tuple = std::tuple<>;
830+ };
831+
832+ template <template <class > class Predicate , class T , class ... Ts>
833+ struct extract_all <Predicate, T, Ts...> {
834+ using tuple = typename std::conditional<
835+ Predicate<T>::value,
836+ decltype (std::tuple_cat(std::declval<std::tuple<T>>(), std::declval<typename extract_all<Predicate, Ts...>::tuple>())),
837+ typename extract_all<Predicate, Ts...>::tuple
838+ >::type;
839+ };
840+
841+ template <typename ... BaseTypes> struct class_bases ;
842+ // Multiple inheritance support, if eventually supported, would use this specialization:
843+ // template <typename Base1, typename Base2, typename... Bases> struct class_bases<Base1, Base2, Bases...> {
844+ // static inline void add_to(detail::type_record &) {}
845+ // };
846+ template <typename Base> struct class_bases <Base> { static inline void add_to (detail::type_record &record) { record.base_type = &typeid (Base); } };
847+ template <> struct class_bases <> { static inline void add_to (detail::type_record &) {} };
848+
849+ template <typename ... BaseTypes> struct class_bases <std::tuple<BaseTypes...>> : class_bases<BaseTypes...> {};
850+
823851NAMESPACE_END (detail)
824852
825853template <typename type_, typename... options>
@@ -828,7 +856,7 @@ class class_ : public detail::generic_type {
828856 template <typename T> using is_subtype = std::is_base_of<type_, T>;
829857 template <typename T> using is_supertype = std::is_base_of<T, type_>;
830858 using extracted_holder = detail::extract_first<is_holder, options...>;
831- using extracted_base = detail::extract_first <is_supertype, options...>;
859+ using extracted_bases = typename detail::extract_all <is_supertype, options...>::tuple ;
832860
833861public:
834862 using type = type_;
@@ -844,9 +872,12 @@ class class_ : public detail::generic_type {
844872 static_assert (0 == sizeof ...(options) -
845873 (int ) has_alias -
846874 (int ) !std::is_void<typename extracted_holder::type>::value -
847- (int ) ! std::is_void< typename extracted_base::type >::value,
875+ (int ) std::tuple_size<extracted_bases >::value,
848876 " Unknown/invalid class_ template parameters provided" );
849877
878+ static_assert (std::tuple_size<extracted_bases>::value <= 1 ,
879+ " Invalid class_ base types: multiple inheritance is not supported" );
880+
850881 PYBIND11_OBJECT (class_, detail::generic_type, PyType_Check)
851882
852883 template <typename ... Extra>
@@ -860,8 +891,7 @@ class class_ : public detail::generic_type {
860891 record.init_holder = init_holder;
861892 record.dealloc = dealloc;
862893
863- if (!std::is_void<typename extracted_base::type>::value)
864- record.base_type = &typeid (typename extracted_base::type);
894+ detail::class_bases<extracted_bases>::add_to (record);
865895
866896 /* Process optional arguments, if any */
867897 detail::process_attributes<Extra...>::init (extra..., &record);
0 commit comments