@@ -44,8 +44,6 @@ NAMESPACE_BEGIN(pybind11)
44
44
45
45
// / Wraps an arbitrary C++ function/method/lambda function/.. into a callable Python object
46
46
class cpp_function : public function {
47
- private:
48
- template <typename Extra> using is_method_annotation = detail::is_instantiation<is_method, Extra>;
49
47
public:
50
48
cpp_function () { }
51
49
@@ -68,27 +66,42 @@ class cpp_function : public function {
68
66
(FuncType *) nullptr , extra...);
69
67
}
70
68
71
- // / Construct a cpp_function from a class method (non-const)
69
+ // / Construct a cpp_function from a class method (non-const); the exposed class argument type is
70
+ // / given by BindClass.
72
71
template <typename Return, typename Class, typename ... Arg, typename ... Extra>
73
72
cpp_function (Return (Class::*f)(Arg...), const Extra&... extra) {
74
- using ClassArg = typename detail::exactly_one_t <is_method_annotation, is_method<Class>, Extra...>
75
- ::template BindClass<Class>;
76
- initialize ([f](ClassArg *c, Arg... args) -> Return { return (c->*f)(args...); },
77
- (Return (*) (ClassArg *, Arg...)) nullptr , extra...);
73
+ initialize ([f](Class *c, Arg... args) -> Return { return (c->*f)(args...); },
74
+ (Return (*) (Class *, Arg...)) nullptr , extra...);
78
75
}
79
76
80
77
// / Construct a cpp_function from a class method (const)
81
78
template <typename Return, typename Class, typename ... Arg, typename ... Extra>
82
79
cpp_function (Return (Class::*f)(Arg...) const , const Extra&... extra) {
83
- using ClassArg = typename detail::exactly_one_t <is_method_annotation, is_method<Class>, Extra...>
84
- ::template BindClass<Class>;
85
- initialize ([f](const ClassArg *c, Arg... args) -> Return { return (c->*f)(args...); },
86
- (Return (*)(const ClassArg *, Arg ...)) nullptr , extra...);
80
+ initialize ([f](const Class *c, Arg... args) -> Return { return (c->*f)(args...); },
81
+ (Return (*)(const Class *, Arg ...)) nullptr , extra...);
87
82
}
88
83
89
84
// / Return the function name
90
85
object name () const { return attr (" __name__" ); }
91
86
87
+ // / Used to construct a cpp_function that might be a method of a base type; in such a case, this
88
+ // / wraps the method in a lambda accepting the given type (rather than the derived type) as the
89
+ // / `self` argument. Otherwise this simply forwards to the constructors above.
90
+ template <typename Derived, typename Func, typename ... Extra>
91
+ static cpp_function method (Func &&f, const Extra&... extra) {
92
+ return {std::forward<Func>(f), extra...};
93
+ }
94
+ template <typename Derived, typename Return, typename Class, typename ... Arg, typename ... Extra,
95
+ detail::enable_if_t <detail::is_strict_base_of<Class, Derived>::value, int > = 0 >
96
+ static cpp_function method (Return (Class::*f)(Arg...), const Extra&... extra) {
97
+ return {[f](Derived *c, Arg... args) -> Return { return (c->*f)(args...); }, extra...};
98
+ }
99
+ template <typename Derived, typename Return, typename Class, typename ... Arg, typename ... Extra,
100
+ detail::enable_if_t <detail::is_strict_base_of<Class, Derived>::value, int > = 0 >
101
+ static cpp_function method (Return (Class::*f)(Arg...) const , const Extra&... extra) {
102
+ return {[f](const Derived *c, Arg... args) -> Return { return (c->*f)(args...); }, extra...};
103
+ }
104
+
92
105
protected:
93
106
// / Space optimization: don't inline this frequently instantiated fragment
94
107
PYBIND11_NOINLINE detail::function_record *make_function_record () {
@@ -917,8 +930,8 @@ NAMESPACE_END(detail)
917
930
template <typename type_, typename... options>
918
931
class class_ : public detail::generic_type {
919
932
template <typename T> using is_holder = detail::is_holder_type<type_, T>;
920
- template <typename T> using is_subtype = detail::bool_constant<std::is_base_of< type_, T>::value && !std::is_same<T, type_>::value >;
921
- template <typename T> using is_base = detail::bool_constant<std::is_base_of< T, type_>::value && !std::is_same<T, type_>::value >;
933
+ template <typename T> using is_subtype = detail::is_strict_base_of< type_, T>;
934
+ template <typename T> using is_base = detail::is_strict_base_of< T, type_>;
922
935
// struct instead of using here to help MSVC:
923
936
template <typename T> struct is_valid_class_option :
924
937
detail::any_of<is_holder<T>, is_subtype<T>, is_base<T>> {};
@@ -984,8 +997,9 @@ class class_ : public detail::generic_type {
984
997
985
998
template <typename Func, typename ... Extra>
986
999
class_ &def (const char *name_, Func&& f, const Extra&... extra) {
987
- cpp_function cf (std::forward<Func>(f), name (name_), is_method<type>(*this ),
988
- sibling (getattr (*this , name_, none ())), extra...);
1000
+ auto cf = cpp_function::method<type>(
1001
+ std::forward<Func>(f), name (name_), is_method (*this ),
1002
+ sibling (getattr (*this , name_, none ())), extra...);
989
1003
attr (cf.name ()) = cf;
990
1004
return *this ;
991
1005
}
@@ -1048,18 +1062,18 @@ class class_ : public detail::generic_type {
1048
1062
1049
1063
template <typename C, typename D, typename ... Extra>
1050
1064
class_ &def_readwrite (const char *name, D C::*pm, const Extra&... extra) {
1051
- using BindC = typename is_method<type>::template BindClass<C>;
1052
- def_property (name,
1053
- [pm](const BindC &c) -> const D &{ return c.*pm; },
1054
- [pm](BindC &c, const D &value) { c.*pm = value; },
1055
- extra...);
1065
+ static_assert (std::is_base_of<C, type>::value, " def_readwrite() requires a class member (or base class member)" );
1066
+ cpp_function fget ([pm](const type &c) -> const D &{ return c.*pm; }, is_method (*this )),
1067
+ fset ([pm](type &c, const D &value) { c.*pm = value; }, is_method (*this ));
1068
+ def_property (name, fget, fset, return_value_policy::reference_internal, extra...);
1056
1069
return *this ;
1057
1070
}
1058
1071
1059
1072
template <typename C, typename D, typename ... Extra>
1060
1073
class_ &def_readonly (const char *name, const D C::*pm, const Extra& ...extra ) {
1061
- using BindC = typename is_method<type>::template BindClass<C>;
1062
- def_property_readonly (name, [pm](const BindC &c) -> const D &{ return c.*pm; }, extra...);
1074
+ static_assert (std::is_base_of<C, type>::value, " def_readonly() requires a class member (or base class member)" );
1075
+ cpp_function fget ([pm](const type &c) -> const D &{ return c.*pm; }, is_method (*this ));
1076
+ def_property_readonly (name, fget, return_value_policy::reference_internal, extra...);
1063
1077
return *this ;
1064
1078
}
1065
1079
@@ -1081,7 +1095,8 @@ class class_ : public detail::generic_type {
1081
1095
// / Uses return_value_policy::reference_internal by default
1082
1096
template <typename Getter, typename ... Extra>
1083
1097
class_ &def_property_readonly (const char *name, const Getter &fget, const Extra& ...extra ) {
1084
- return def_property_readonly (name, cpp_function (fget, is_method<type>(*this )), return_value_policy::reference_internal, extra...);
1098
+ return def_property_readonly (name, cpp_function::method<type>(fget),
1099
+ return_value_policy::reference_internal, extra...);
1085
1100
}
1086
1101
1087
1102
// / Uses cpp_function's return_value_policy by default
@@ -1105,21 +1120,17 @@ class class_ : public detail::generic_type {
1105
1120
// / Uses return_value_policy::reference_internal by default
1106
1121
template <typename Getter, typename Setter, typename ... Extra>
1107
1122
class_ &def_property (const char *name, const Getter &fget, const Setter &fset, const Extra& ...extra ) {
1108
- return def_property (name, fget,
1109
- cpp_function (fset, is_method<type>(*this ), return_value_policy::reference_internal),
1110
- extra...);
1123
+ return def_property (name, fget, cpp_function::method<type>(fset, return_value_policy::reference_internal), extra...);
1111
1124
}
1112
1125
template <typename Getter, typename ... Extra>
1113
1126
class_ &def_property (const char *name, const Getter &fget, const cpp_function &fset, const Extra& ...extra ) {
1114
- return def_property (name,
1115
- cpp_function (fget, is_method<type>(*this ), return_value_policy::reference_internal),
1116
- fset, extra...);
1127
+ return def_property (name, cpp_function::method<type>(fget), fset, return_value_policy::reference_internal, extra...);
1117
1128
}
1118
1129
1119
1130
// / Uses cpp_function's return_value_policy by default
1120
1131
template <typename ... Extra>
1121
1132
class_ &def_property (const char *name, const cpp_function &fget, const cpp_function &fset, const Extra& ...extra ) {
1122
- return def_property_static (name, fget, fset, is_method<type> (*this ), extra...);
1133
+ return def_property_static (name, fget, fset, is_method (*this ), extra...);
1123
1134
}
1124
1135
1125
1136
// / Uses return_value_policy::reference by default
0 commit comments