13
13
14
14
NAMESPACE_BEGIN (PYBIND11_NAMESPACE)
15
15
NAMESPACE_BEGIN(detail)
16
- NAMESPACE_BEGIN(initimpl)
17
16
18
- inline void no_nullptr(void *ptr) {
19
- if (!ptr) throw type_error (" pybind11::init(): factory function returned nullptr" );
20
- }
17
+ template <>
18
+ class type_caster<value_and_holder> {
19
+ public:
20
+ bool load (handle h, bool ) {
21
+ value = reinterpret_cast <value_and_holder *>(h.ptr ());
22
+ return true ;
23
+ }
21
24
22
- // Makes sure the `value` for the given value_and_holder is not preallocated (e.g. by a previous
23
- // old-style placement new `__init__` that requires a preallocated, uninitialized value). If
24
- // preallocated, deallocate. Returns the (null) value pointer reference ready for allocation.
25
- inline void *&deallocate (value_and_holder &v_h) {
26
- if (v_h) v_h.type ->dealloc (v_h);
27
- return v_h.value_ptr ();
28
- }
25
+ template <typename > using cast_op_type = value_and_holder &;
26
+ operator value_and_holder &() { return *value; }
27
+ static PYBIND11_DESCR name () { return type_descr (_<value_and_holder>()); }
29
28
30
- PYBIND11_NOINLINE inline value_and_holder load_v_h (handle self_, type_info *tinfo) {
31
- if (!self_ || !tinfo)
32
- throw type_error ( " __init__(self, ...) called with invalid `self` argument " ) ;
29
+ private:
30
+ value_and_holder *value = nullptr ;
31
+ } ;
33
32
34
- auto *inst = reinterpret_cast <instance *>(self_.ptr ());
35
- auto result = inst->get_value_and_holder (tinfo, false );
36
- if (!result.inst )
37
- throw type_error (" __init__(self, ...) called with invalid `self` argument" );
33
+ NAMESPACE_BEGIN (initimpl)
38
34
39
- return result;
35
+ inline void no_nullptr(void *ptr) {
36
+ if (!ptr) throw type_error (" pybind11::init(): factory function returned nullptr" );
40
37
}
41
38
42
-
43
39
// Implementing functions for all forms of py::init<...> and py::init(...)
44
40
template <typename Class> using Cpp = typename Class::type;
45
41
template <typename Class> using Alias = typename Class::type_alias;
@@ -64,7 +60,7 @@ constexpr bool is_alias(void *) { return false; }
64
60
template <typename Class>
65
61
void construct_alias_from_cpp (std::true_type /* is_alias_constructible*/ ,
66
62
value_and_holder &v_h, Cpp<Class> &&base) {
67
- deallocate ( v_h) = new Alias<Class>(std::move (base));
63
+ v_h. value_ptr ( ) = new Alias<Class>(std::move (base));
68
64
}
69
65
template <typename Class>
70
66
[[noreturn]] void construct_alias_from_cpp (std::false_type /* !is_alias_constructible*/ ,
@@ -98,19 +94,17 @@ void construct(value_and_holder &v_h, Cpp<Class> *ptr, bool need_alias) {
98
94
// it was a normal instance, then steal the holder away into a local variable; thus
99
95
// the holder and destruction happens when we leave the C++ scope, and the holder
100
96
// class gets to handle the destruction however it likes.
101
- deallocate ( v_h) = ptr;
97
+ v_h. value_ptr ( ) = ptr;
102
98
v_h.set_instance_registered (true ); // To prevent init_instance from registering it
103
99
v_h.type ->init_instance (v_h.inst , nullptr ); // Set up the holder
104
100
Holder<Class> temp_holder (std::move (v_h.holder <Holder<Class>>())); // Steal the holder
105
101
v_h.type ->dealloc (v_h); // Destroys the moved-out holder remains, resets value ptr to null
106
102
v_h.set_instance_registered (false );
107
103
108
104
construct_alias_from_cpp<Class>(is_alias_constructible<Class>{}, v_h, std::move (*ptr));
109
- }
110
- else {
111
- // Otherwise the type isn't inherited, so we don't need an Alias and can just store the Cpp
112
- // pointer directory:
113
- deallocate (v_h) = ptr;
105
+ } else {
106
+ // Otherwise the type isn't inherited, so we don't need an Alias
107
+ v_h.value_ptr () = ptr;
114
108
}
115
109
}
116
110
@@ -119,7 +113,7 @@ void construct(value_and_holder &v_h, Cpp<Class> *ptr, bool need_alias) {
119
113
template <typename Class, enable_if_t <Class::has_alias, int > = 0 >
120
114
void construct (value_and_holder &v_h, Alias<Class> *alias_ptr, bool ) {
121
115
no_nullptr (alias_ptr);
122
- deallocate ( v_h) = static_cast <Cpp<Class> *>(alias_ptr);
116
+ v_h. value_ptr ( ) = static_cast <Cpp<Class> *>(alias_ptr);
123
117
}
124
118
125
119
// Holder return: copy its pointer, and move or copy the returned holder into the new instance's
@@ -133,7 +127,7 @@ void construct(value_and_holder &v_h, Holder<Class> holder, bool need_alias) {
133
127
throw type_error (" pybind11::init(): construction failed: returned holder-wrapped instance "
134
128
" is not an alias instance" );
135
129
136
- deallocate ( v_h) = ptr;
130
+ v_h. value_ptr ( ) = ptr;
137
131
v_h.type ->init_instance (v_h.inst , &holder);
138
132
}
139
133
@@ -148,7 +142,7 @@ void construct(value_and_holder &v_h, Cpp<Class> &&result, bool need_alias) {
148
142
if (Class::has_alias && need_alias)
149
143
construct_alias_from_cpp<Class>(is_alias_constructible<Class>{}, v_h, std::move (result));
150
144
else
151
- deallocate ( v_h) = new Cpp<Class>(std::move (result));
145
+ v_h. value_ptr ( ) = new Cpp<Class>(std::move (result));
152
146
}
153
147
154
148
// return-by-value version 2: returning a value of the alias type itself. We move-construct an
@@ -158,48 +152,38 @@ template <typename Class>
158
152
void construct (value_and_holder &v_h, Alias<Class> &&result, bool ) {
159
153
static_assert (std::is_move_constructible<Alias<Class>>::value,
160
154
" pybind11::init() return-by-alias-value factory function requires a movable alias class" );
161
- deallocate ( v_h) = new Alias<Class>(std::move (result));
155
+ v_h. value_ptr ( ) = new Alias<Class>(std::move (result));
162
156
}
163
157
164
158
// Implementing class for py::init<...>()
165
- template <typename ... Args> struct constructor {
159
+ template <typename ... Args>
160
+ struct constructor {
166
161
template <typename Class, typename ... Extra, enable_if_t <!Class::has_alias, int > = 0 >
167
162
static void execute (Class &cl, const Extra&... extra) {
168
- auto *cl_type = get_type_info (typeid (Cpp<Class>));
169
- cl.def (" __init__" , [cl_type](handle self_, Args... args) {
170
- auto v_h = load_v_h (self_, cl_type);
171
- if (v_h.instance_registered ()) return ; // Ignore duplicate __init__ calls (see above)
172
-
173
- construct<Class>(v_h, new Cpp<Class>(std::forward<Args>(args)...), false );
174
- }, extra...);
163
+ cl.def (" __init__" , [](value_and_holder &v_h, Args... args) {
164
+ v_h.value_ptr () = new Cpp<Class>(std::forward<Args>(args)...);
165
+ }, is_new_style_constructor (), extra...);
175
166
}
176
167
177
168
template <typename Class, typename ... Extra,
178
169
enable_if_t <Class::has_alias &&
179
170
std::is_constructible<Cpp<Class>, Args...>::value, int > = 0 >
180
171
static void execute (Class &cl, const Extra&... extra) {
181
- auto *cl_type = get_type_info (typeid (Cpp<Class>));
182
- cl.def (" __init__" , [cl_type](handle self_, Args... args) {
183
- auto v_h = load_v_h (self_, cl_type);
184
- if (v_h.instance_registered ()) return ; // Ignore duplicate __init__ calls (see above)
185
-
186
- if (Py_TYPE (v_h.inst ) == cl_type->type )
187
- construct<Class>(v_h, new Cpp<Class>(std::forward<Args>(args)...), false );
172
+ cl.def (" __init__" , [](value_and_holder &v_h, Args... args) {
173
+ if (Py_TYPE (v_h.inst ) == v_h.type ->type )
174
+ v_h.value_ptr () = new Cpp<Class>(std::forward<Args>(args)...);
188
175
else
189
- construct<Class>( v_h, new Alias<Class>(std::forward<Args>(args)...), true );
190
- }, extra...);
176
+ v_h. value_ptr () = new Alias<Class>(std::forward<Args>(args)...);
177
+ }, is_new_style_constructor (), extra...);
191
178
}
192
179
193
180
template <typename Class, typename ... Extra,
194
181
enable_if_t <Class::has_alias &&
195
182
!std::is_constructible<Cpp<Class>, Args...>::value, int > = 0 >
196
183
static void execute (Class &cl, const Extra&... extra) {
197
- auto *cl_type = get_type_info (typeid (Cpp<Class>));
198
- cl.def (" __init__" , [cl_type](handle self_, Args... args) {
199
- auto v_h = load_v_h (self_, cl_type);
200
- if (v_h.instance_registered ()) return ; // Ignore duplicate __init__ calls (see above)
201
- construct<Class>(v_h, new Alias<Class>(std::forward<Args>(args)...), true );
202
- }, extra...);
184
+ cl.def (" __init__" , [](value_and_holder &v_h, Args... args) {
185
+ v_h.value_ptr () = new Alias<Class>(std::forward<Args>(args)...);
186
+ }, is_new_style_constructor (), extra...);
203
187
}
204
188
};
205
189
@@ -208,17 +192,15 @@ template <typename... Args> struct alias_constructor {
208
192
template <typename Class, typename ... Extra,
209
193
enable_if_t <Class::has_alias && std::is_constructible<Alias<Class>, Args...>::value, int > = 0 >
210
194
static void execute (Class &cl, const Extra&... extra) {
211
- auto *cl_type = get_type_info (typeid (Cpp<Class>));
212
- cl.def (" __init__" , [cl_type](handle self_, Args... args) {
213
- auto v_h = load_v_h (self_, cl_type);
214
- if (v_h.instance_registered ()) return ; // Ignore duplicate __init__ calls (see above)
215
- construct<Class>(v_h, new Alias<Class>(std::forward<Args>(args)...), true );
216
- }, extra...);
195
+ cl.def (" __init__" , [](value_and_holder &v_h, Args... args) {
196
+ v_h.value_ptr () = new Alias<Class>(std::forward<Args>(args)...);
197
+ }, is_new_style_constructor (), extra...);
217
198
}
218
199
};
219
200
220
201
// Implementation class for py::init(Func) and py::init(Func, AliasFunc)
221
- template <typename CFunc, typename AFuncIn, typename ... Args> struct factory {
202
+ template <typename CFunc, typename AFuncIn, typename ... Args>
203
+ struct factory {
222
204
private:
223
205
using CFuncType = typename std::remove_reference<CFunc>::type;
224
206
using AFunc = conditional_t <std::is_void<AFuncIn>::value, void_type, AFuncIn>;
@@ -246,21 +228,16 @@ template <typename CFunc, typename AFuncIn, typename... Args> struct factory {
246
228
template <typename Class, typename ... Extra,
247
229
enable_if_t <!Class::has_alias || std::is_void<AFuncIn>::value, int > = 0 >
248
230
void execute (Class &cl, const Extra&... extra) && {
249
- auto *cl_type = get_type_info (typeid (Cpp<Class>));
250
231
#if defined(PYBIND11_CPP14)
251
- cl.def (" __init__" , [cl_type, func = std::move (class_factory)]
232
+ cl.def (" __init__" , [func = std::move (class_factory)]
252
233
#else
253
234
CFuncType &func = class_factory;
254
- cl.def (" __init__" , [cl_type, func]
235
+ cl.def (" __init__" , [func]
255
236
#endif
256
- (handle self_, Args... args) {
257
- auto v_h = load_v_h (self_, cl_type);
258
- // If this value is already registered it must mean __init__ is invoked multiple times;
259
- // we really can't support that in C++, so just ignore the second __init__.
260
- if (v_h.instance_registered ()) return ;
261
-
262
- construct<Class>(v_h, func (std::forward<Args>(args)...), Py_TYPE (v_h.inst ) != cl_type->type );
263
- }, extra...);
237
+ (value_and_holder &v_h, Args... args) {
238
+ construct<Class>(v_h, func (std::forward<Args>(args)...),
239
+ Py_TYPE (v_h.inst ) != v_h.type ->type );
240
+ }, is_new_style_constructor (), extra...);
264
241
}
265
242
266
243
// Add __init__ definition for a class with an alias *and* distinct alias factory; the former is
@@ -269,26 +246,21 @@ template <typename CFunc, typename AFuncIn, typename... Args> struct factory {
269
246
template <typename Class, typename ... Extra,
270
247
enable_if_t <Class::has_alias && !std::is_void<AFuncIn>::value, int > = 0 >
271
248
void execute (Class &cl, const Extra&... extra) && {
272
- auto *cl_type = get_type_info (typeid (Cpp<Class>));
273
-
274
249
#if defined(PYBIND11_CPP14)
275
- cl.def (" __init__" , [cl_type, class_func = std::move (class_factory), alias_func = std::move (alias_factory)]
250
+ cl.def (" __init__" , [class_func = std::move (class_factory), alias_func = std::move (alias_factory)]
276
251
#else
277
252
CFuncType &class_func = class_factory;
278
253
AFuncType &alias_func = alias_factory;
279
- cl.def (" __init__" , [cl_type, class_func, alias_func]
254
+ cl.def (" __init__" , [class_func, alias_func]
280
255
#endif
281
- (handle self_, Args... args) {
282
- auto v_h = load_v_h (self_, cl_type);
283
- if (v_h.instance_registered ()) return ; // (see comment above)
284
-
285
- if (Py_TYPE (v_h.inst ) == cl_type->type )
256
+ (value_and_holder &v_h, Args... args) {
257
+ if (Py_TYPE (v_h.inst ) == v_h.type ->type )
286
258
// If the instance type equals the registered type we don't have inheritance, so
287
259
// don't need the alias and can construct using the class function:
288
260
construct<Class>(v_h, class_func (std::forward<Args>(args)...), false );
289
261
else
290
262
construct<Class>(v_h, alias_func (std::forward<Args>(args)...), true );
291
- }, extra...);
263
+ }, is_new_style_constructor (), extra...);
292
264
}
293
265
};
294
266
0 commit comments