@@ -563,7 +563,7 @@ class module : public object {
563
563
NAMESPACE_BEGIN (detail)
564
564
// / Generic support for creating new Python heap types
565
565
class generic_type : public object {
566
- template <typename type, typename holder_type, typename type_alias > friend class class_ ;
566
+ template <typename ... > friend class class_ ;
567
567
public:
568
568
PYBIND11_OBJECT_DEFAULT (generic_type, object, PyType_Check)
569
569
protected:
@@ -802,12 +802,46 @@ class generic_type : public object {
802
802
803
803
static void releasebuffer (PyObject *, Py_buffer *view) { delete (buffer_info *) view->internal ; }
804
804
};
805
+
806
+ template <template <typename > class Predicate , typename ... BaseTypes> struct class_selector ;
807
+ template <template <typename > class Predicate , typename Base, typename ... Bases>
808
+ struct class_selector <Predicate, Base, Bases...> {
809
+ static inline void set_bases (detail::type_record &record) {
810
+ if (Predicate<Base>::value) record.base_type = &typeid (Base);
811
+ else class_selector<Predicate, Bases...>::set_bases (record);
812
+ }
813
+ };
814
+ template <template <typename > class Predicate >
815
+ struct class_selector <Predicate> {
816
+ static inline void set_bases (detail::type_record &) {}
817
+ };
818
+
805
819
NAMESPACE_END (detail)
806
820
807
- template <typename type , typename holder_type = std::unique_ptr<type>, typename type_alias = type >
821
+ template <typename type_ , typename... options >
808
822
class class_ : public detail::generic_type {
823
+ template <typename T> using is_holder = detail::is_holder_type<type_, T>;
824
+ template <typename T> using is_subtype = detail::bool_constant<std::is_base_of<type_, T>::value && !std::is_same<T, type_>::value>;
825
+ template <typename T> using is_base_class = detail::bool_constant<std::is_base_of<T, type_>::value && !std::is_same<T, type_>::value>;
826
+ template <typename T> using is_valid_class_option =
827
+ detail::bool_constant<
828
+ is_holder<T>::value ||
829
+ is_subtype<T>::value ||
830
+ is_base_class<T>::value
831
+ >;
832
+
809
833
public:
810
- typedef detail::instance<type, holder_type> instance_type;
834
+ using type = type_;
835
+ using type_alias = detail::first_of_t <is_subtype, void , options...>;
836
+ constexpr static bool has_alias = !std::is_void<type_alias>::value;
837
+ using holder_type = detail::first_of_t <is_holder, std::unique_ptr<type>, options...>;
838
+ using instance_type = detail::instance<type, holder_type>;
839
+
840
+ static_assert (detail::all_of_t <is_valid_class_option, options...>::value,
841
+ " Unknown/invalid class_ template parameters provided" );
842
+
843
+ static_assert (detail::count_t <is_base_class, options...>::value <= 1 ,
844
+ " Invalid class_ base types: multiple inheritance is not supported" );
811
845
812
846
PYBIND11_OBJECT (class_, detail::generic_type, PyType_Check)
813
847
@@ -822,12 +856,14 @@ class class_ : public detail::generic_type {
822
856
record.init_holder = init_holder;
823
857
record.dealloc = dealloc;
824
858
859
+ detail::class_selector<is_base_class, options...>::set_bases (record);
860
+
825
861
/* Process optional arguments, if any */
826
862
detail::process_attributes<Extra...>::init (extra..., &record);
827
863
828
864
detail::generic_type::initialize (&record);
829
865
830
- if (!std::is_same<type, type_alias>::value ) {
866
+ if (has_alias ) {
831
867
auto &instances = pybind11::detail::get_internals ().registered_types_cpp ;
832
868
instances[std::type_index (typeid (type_alias))] = instances[std::type_index (typeid (type))];
833
869
}
@@ -852,25 +888,25 @@ class class_ : public detail::generic_type {
852
888
853
889
template <detail::op_id id, detail::op_type ot, typename L, typename R, typename ... Extra>
854
890
class_ &def (const detail::op_<id, ot, L, R> &op, const Extra&... extra) {
855
- op.template execute <type> (*this , extra...);
891
+ op.execute (*this , extra...);
856
892
return *this ;
857
893
}
858
894
859
895
template <detail::op_id id, detail::op_type ot, typename L, typename R, typename ... Extra>
860
896
class_ & def_cast (const detail::op_<id, ot, L, R> &op, const Extra&... extra) {
861
- op.template execute_cast <type> (*this , extra...);
897
+ op.execute_cast (*this , extra...);
862
898
return *this ;
863
899
}
864
900
865
901
template <typename ... Args, typename ... Extra>
866
902
class_ &def (const detail::init<Args...> &init, const Extra&... extra) {
867
- init.template execute <type> (*this , extra...);
903
+ init.execute (*this , extra...);
868
904
return *this ;
869
905
}
870
906
871
907
template <typename ... Args, typename ... Extra>
872
908
class_ &def (const detail::init_alias<Args...> &init, const Extra&... extra) {
873
- init.template execute <type> (*this , extra...);
909
+ init.execute (*this , extra...);
874
910
return *this ;
875
911
}
876
912
@@ -1071,31 +1107,34 @@ template <typename Type> class enum_ : public class_<Type> {
1071
1107
1072
1108
NAMESPACE_BEGIN (detail)
1073
1109
template <typename... Args> struct init {
1074
- template <typename Base , typename Holder , typename Alias, typename ... Extra,
1075
- typename std::enable_if<std::is_same<Base, Alias>::value, int >::type = 0 >
1076
- void execute (pybind11::class_<Base, Holder, Alias> &class_, const Extra&... extra) const {
1110
+ template <typename Class , typename ... Extra , typename std::enable_if<!Class::has_alias, int >::type = 0 >
1111
+ void execute (Class &cl, const Extra&... extra) const {
1112
+ using Base = typename Class::type;
1077
1113
// / Function which calls a specific C++ in-place constructor
1078
- class_ .def (" __init__" , [](Base *self_, Args... args) { new (self_) Base (args...); }, extra...);
1114
+ cl .def (" __init__" , [](Base *self_, Args... args) { new (self_) Base (args...); }, extra...);
1079
1115
}
1080
1116
1081
- template <typename Base, typename Holder, typename Alias, typename ... Extra,
1082
- typename std::enable_if<!std::is_same<Base, Alias>::value &&
1083
- std::is_constructible<Base, Args...>::value, int >::type = 0 >
1084
- void execute (pybind11::class_<Base, Holder, Alias> &class_, const Extra&... extra) const {
1085
- handle cl_type = class_;
1086
- class_.def (" __init__" , [cl_type](handle self_, Args... args) {
1117
+ template <typename Class, typename ... Extra,
1118
+ typename std::enable_if<Class::has_alias &&
1119
+ std::is_constructible<typename Class::type, Args...>::value, int >::type = 0 >
1120
+ void execute (Class &cl, const Extra&... extra) const {
1121
+ using Base = typename Class::type;
1122
+ using Alias = typename Class::type_alias;
1123
+ handle cl_type = cl;
1124
+ cl.def (" __init__" , [cl_type](handle self_, Args... args) {
1087
1125
if (self_.get_type () == cl_type)
1088
1126
new (self_.cast <Base *>()) Base (args...);
1089
1127
else
1090
1128
new (self_.cast <Alias *>()) Alias (args...);
1091
1129
}, extra...);
1092
1130
}
1093
1131
1094
- template <typename Base, typename Holder, typename Alias, typename ... Extra,
1095
- typename std::enable_if<!std::is_same<Base, Alias>::value &&
1096
- !std::is_constructible<Base, Args...>::value, int >::type = 0 >
1097
- void execute (pybind11::class_<Base, Holder, Alias> &class_, const Extra&... extra) const {
1098
- class_.def (" __init__" , [](Alias *self_, Args... args) { new (self_) Alias (args...); }, extra...);
1132
+ template <typename Class, typename ... Extra,
1133
+ typename std::enable_if<Class::has_alias &&
1134
+ !std::is_constructible<typename Class::type, Args...>::value, int >::type = 0 >
1135
+ void execute (Class &cl, const Extra&... extra) const {
1136
+ using Alias = typename Class::type_alias;
1137
+ cl.def (" __init__" , [](Alias *self_, Args... args) { new (self_) Alias (args...); }, extra...);
1099
1138
}
1100
1139
};
1101
1140
0 commit comments