@@ -820,6 +820,34 @@ struct extract_first<Predicate, T, Ts...> {
820
820
>::type;
821
821
};
822
822
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
+
823
851
NAMESPACE_END (detail)
824
852
825
853
template <typename type_, typename... options>
@@ -828,7 +856,7 @@ class class_ : public detail::generic_type {
828
856
template <typename T> using is_subtype = std::is_base_of<type_, T>;
829
857
template <typename T> using is_supertype = std::is_base_of<T, type_>;
830
858
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 ;
832
860
833
861
public:
834
862
using type = type_;
@@ -844,9 +872,12 @@ class class_ : public detail::generic_type {
844
872
static_assert (0 == sizeof ...(options) -
845
873
(int ) has_alias -
846
874
(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,
848
876
" Unknown/invalid class_ template parameters provided" );
849
877
878
+ static_assert (std::tuple_size<extracted_bases>::value <= 1 ,
879
+ " Invalid class_ base types: multiple inheritance is not supported" );
880
+
850
881
PYBIND11_OBJECT (class_, detail::generic_type, PyType_Check)
851
882
852
883
template <typename ... Extra>
@@ -860,8 +891,7 @@ class class_ : public detail::generic_type {
860
891
record.init_holder = init_holder;
861
892
record.dealloc = dealloc;
862
893
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);
865
895
866
896
/* Process optional arguments, if any */
867
897
detail::process_attributes<Extra...>::init (extra..., &record);
0 commit comments