1 | /* |
2 | pybind11/attr.h: Infrastructure for processing custom |
3 | type and function attributes |
4 | |
5 | Copyright (c) 2016 Wenzel Jakob <[email protected]> |
6 | |
7 | All rights reserved. Use of this source code is governed by a |
8 | BSD-style license that can be found in the LICENSE file. |
9 | */ |
10 | |
11 | #pragma once |
12 | |
13 | #include "detail/common.h" |
14 | #include "cast.h" |
15 | |
16 | #include <functional> |
17 | |
18 | PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) |
19 | |
20 | /// \addtogroup annotations |
21 | /// @{ |
22 | |
23 | /// Annotation for methods |
24 | struct is_method { |
25 | handle class_; |
26 | explicit is_method(const handle &c) : class_(c) {} |
27 | }; |
28 | |
29 | /// Annotation for operators |
30 | struct is_operator {}; |
31 | |
32 | /// Annotation for classes that cannot be subclassed |
33 | struct is_final {}; |
34 | |
35 | /// Annotation for parent scope |
36 | struct scope { |
37 | handle value; |
38 | explicit scope(const handle &s) : value(s) {} |
39 | }; |
40 | |
41 | /// Annotation for documentation |
42 | struct doc { |
43 | const char *value; |
44 | explicit doc(const char *value) : value(value) {} |
45 | }; |
46 | |
47 | /// Annotation for function names |
48 | struct name { |
49 | const char *value; |
50 | explicit name(const char *value) : value(value) {} |
51 | }; |
52 | |
53 | /// Annotation indicating that a function is an overload associated with a given "sibling" |
54 | struct sibling { |
55 | handle value; |
56 | explicit sibling(const handle &value) : value(value.ptr()) {} |
57 | }; |
58 | |
59 | /// Annotation indicating that a class derives from another given type |
60 | template <typename T> |
61 | struct base { |
62 | |
63 | PYBIND11_DEPRECATED( |
64 | "base<T>() was deprecated in favor of specifying 'T' as a template argument to class_" ) |
65 | base() = default; |
66 | }; |
67 | |
68 | /// Keep patient alive while nurse lives |
69 | template <size_t Nurse, size_t Patient> |
70 | struct keep_alive {}; |
71 | |
72 | /// Annotation indicating that a class is involved in a multiple inheritance relationship |
73 | struct multiple_inheritance {}; |
74 | |
75 | /// Annotation which enables dynamic attributes, i.e. adds `__dict__` to a class |
76 | struct dynamic_attr {}; |
77 | |
78 | /// Annotation which enables the buffer protocol for a type |
79 | struct buffer_protocol {}; |
80 | |
81 | /// Annotation which requests that a special metaclass is created for a type |
82 | struct metaclass { |
83 | handle value; |
84 | |
85 | PYBIND11_DEPRECATED("py::metaclass() is no longer required. It's turned on by default now." ) |
86 | metaclass() = default; |
87 | |
88 | /// Override pybind11's default metaclass |
89 | explicit metaclass(handle value) : value(value) {} |
90 | }; |
91 | |
92 | /// Specifies a custom callback with signature `void (PyHeapTypeObject*)` that |
93 | /// may be used to customize the Python type. |
94 | /// |
95 | /// The callback is invoked immediately before `PyType_Ready`. |
96 | /// |
97 | /// Note: This is an advanced interface, and uses of it may require changes to |
98 | /// work with later versions of pybind11. You may wish to consult the |
99 | /// implementation of `make_new_python_type` in `detail/classes.h` to understand |
100 | /// the context in which the callback will be run. |
101 | struct custom_type_setup { |
102 | using callback = std::function<void(PyHeapTypeObject *heap_type)>; |
103 | |
104 | explicit custom_type_setup(callback value) : value(std::move(value)) {} |
105 | |
106 | callback value; |
107 | }; |
108 | |
109 | /// Annotation that marks a class as local to the module: |
110 | struct module_local { |
111 | const bool value; |
112 | constexpr explicit module_local(bool v = true) : value(v) {} |
113 | }; |
114 | |
115 | /// Annotation to mark enums as an arithmetic type |
116 | struct arithmetic {}; |
117 | |
118 | /// Mark a function for addition at the beginning of the existing overload chain instead of the end |
119 | struct prepend {}; |
120 | |
121 | /** \rst |
122 | A call policy which places one or more guard variables (``Ts...``) around the function call. |
123 | |
124 | For example, this definition: |
125 | |
126 | .. code-block:: cpp |
127 | |
128 | m.def("foo", foo, py::call_guard<T>()); |
129 | |
130 | is equivalent to the following pseudocode: |
131 | |
132 | .. code-block:: cpp |
133 | |
134 | m.def("foo", [](args...) { |
135 | T scope_guard; |
136 | return foo(args...); // forwarded arguments |
137 | }); |
138 | \endrst */ |
139 | template <typename... Ts> |
140 | struct call_guard; |
141 | |
142 | template <> |
143 | struct call_guard<> { |
144 | using type = detail::void_type; |
145 | }; |
146 | |
147 | template <typename T> |
148 | struct call_guard<T> { |
149 | static_assert(std::is_default_constructible<T>::value, |
150 | "The guard type must be default constructible" ); |
151 | |
152 | using type = T; |
153 | }; |
154 | |
155 | template <typename T, typename... Ts> |
156 | struct call_guard<T, Ts...> { |
157 | struct type { |
158 | T guard{}; // Compose multiple guard types with left-to-right default-constructor order |
159 | typename call_guard<Ts...>::type next{}; |
160 | }; |
161 | }; |
162 | |
163 | /// @} annotations |
164 | |
165 | PYBIND11_NAMESPACE_BEGIN(detail) |
166 | /* Forward declarations */ |
167 | enum op_id : int; |
168 | enum op_type : int; |
169 | struct undefined_t; |
170 | template <op_id id, op_type ot, typename L = undefined_t, typename R = undefined_t> |
171 | struct op_; |
172 | void keep_alive_impl(size_t Nurse, size_t Patient, function_call &call, handle ret); |
173 | |
174 | /// Internal data structure which holds metadata about a keyword argument |
175 | struct argument_record { |
176 | const char *name; ///< Argument name |
177 | const char *descr; ///< Human-readable version of the argument value |
178 | handle value; ///< Associated Python object |
179 | bool convert : 1; ///< True if the argument is allowed to convert when loading |
180 | bool none : 1; ///< True if None is allowed when loading |
181 | |
182 | argument_record(const char *name, const char *descr, handle value, bool convert, bool none) |
183 | : name(name), descr(descr), value(value), convert(convert), none(none) {} |
184 | }; |
185 | |
186 | /// Internal data structure which holds metadata about a bound function (signature, overloads, |
187 | /// etc.) |
188 | struct function_record { |
189 | function_record() |
190 | : is_constructor(false), is_new_style_constructor(false), is_stateless(false), |
191 | is_operator(false), is_method(false), has_args(false), has_kwargs(false), |
192 | prepend(false) {} |
193 | |
194 | /// Function name |
195 | char *name = nullptr; /* why no C++ strings? They generate heavier code.. */ |
196 | |
197 | // User-specified documentation string |
198 | char *doc = nullptr; |
199 | |
200 | /// Human-readable version of the function signature |
201 | char *signature = nullptr; |
202 | |
203 | /// List of registered keyword arguments |
204 | std::vector<argument_record> args; |
205 | |
206 | /// Pointer to lambda function which converts arguments and performs the actual call |
207 | handle (*impl)(function_call &) = nullptr; |
208 | |
209 | /// Storage for the wrapped function pointer and captured data, if any |
210 | void *data[3] = {}; |
211 | |
212 | /// Pointer to custom destructor for 'data' (if needed) |
213 | void (*free_data)(function_record *ptr) = nullptr; |
214 | |
215 | /// Return value policy associated with this function |
216 | return_value_policy policy = return_value_policy::automatic; |
217 | |
218 | /// True if name == '__init__' |
219 | bool is_constructor : 1; |
220 | |
221 | /// True if this is a new-style `__init__` defined in `detail/init.h` |
222 | bool is_new_style_constructor : 1; |
223 | |
224 | /// True if this is a stateless function pointer |
225 | bool is_stateless : 1; |
226 | |
227 | /// True if this is an operator (__add__), etc. |
228 | bool is_operator : 1; |
229 | |
230 | /// True if this is a method |
231 | bool is_method : 1; |
232 | |
233 | /// True if the function has a '*args' argument |
234 | bool has_args : 1; |
235 | |
236 | /// True if the function has a '**kwargs' argument |
237 | bool has_kwargs : 1; |
238 | |
239 | /// True if this function is to be inserted at the beginning of the overload resolution chain |
240 | bool prepend : 1; |
241 | |
242 | /// Number of arguments (including py::args and/or py::kwargs, if present) |
243 | std::uint16_t nargs; |
244 | |
245 | /// Number of leading positional arguments, which are terminated by a py::args or py::kwargs |
246 | /// argument or by a py::kw_only annotation. |
247 | std::uint16_t nargs_pos = 0; |
248 | |
249 | /// Number of leading arguments (counted in `nargs`) that are positional-only |
250 | std::uint16_t nargs_pos_only = 0; |
251 | |
252 | /// Python method object |
253 | PyMethodDef *def = nullptr; |
254 | |
255 | /// Python handle to the parent scope (a class or a module) |
256 | handle scope; |
257 | |
258 | /// Python handle to the sibling function representing an overload chain |
259 | handle sibling; |
260 | |
261 | /// Pointer to next overload |
262 | function_record *next = nullptr; |
263 | }; |
264 | |
265 | /// Special data structure which (temporarily) holds metadata about a bound class |
266 | struct type_record { |
267 | PYBIND11_NOINLINE type_record() |
268 | : multiple_inheritance(false), dynamic_attr(false), buffer_protocol(false), |
269 | default_holder(true), module_local(false), is_final(false) {} |
270 | |
271 | /// Handle to the parent scope |
272 | handle scope; |
273 | |
274 | /// Name of the class |
275 | const char *name = nullptr; |
276 | |
277 | // Pointer to RTTI type_info data structure |
278 | const std::type_info *type = nullptr; |
279 | |
280 | /// How large is the underlying C++ type? |
281 | size_t type_size = 0; |
282 | |
283 | /// What is the alignment of the underlying C++ type? |
284 | size_t type_align = 0; |
285 | |
286 | /// How large is the type's holder? |
287 | size_t holder_size = 0; |
288 | |
289 | /// The global operator new can be overridden with a class-specific variant |
290 | void *(*operator_new)(size_t) = nullptr; |
291 | |
292 | /// Function pointer to class_<..>::init_instance |
293 | void (*init_instance)(instance *, const void *) = nullptr; |
294 | |
295 | /// Function pointer to class_<..>::dealloc |
296 | void (*dealloc)(detail::value_and_holder &) = nullptr; |
297 | |
298 | /// List of base classes of the newly created type |
299 | list bases; |
300 | |
301 | /// Optional docstring |
302 | const char *doc = nullptr; |
303 | |
304 | /// Custom metaclass (optional) |
305 | handle metaclass; |
306 | |
307 | /// Custom type setup. |
308 | custom_type_setup::callback custom_type_setup_callback; |
309 | |
310 | /// Multiple inheritance marker |
311 | bool multiple_inheritance : 1; |
312 | |
313 | /// Does the class manage a __dict__? |
314 | bool dynamic_attr : 1; |
315 | |
316 | /// Does the class implement the buffer protocol? |
317 | bool buffer_protocol : 1; |
318 | |
319 | /// Is the default (unique_ptr) holder type used? |
320 | bool default_holder : 1; |
321 | |
322 | /// Is the class definition local to the module shared object? |
323 | bool module_local : 1; |
324 | |
325 | /// Is the class inheritable from python classes? |
326 | bool is_final : 1; |
327 | |
328 | PYBIND11_NOINLINE void add_base(const std::type_info &base, void *(*caster)(void *) ) { |
329 | auto *base_info = detail::get_type_info(base, false); |
330 | if (!base_info) { |
331 | std::string tname(base.name()); |
332 | detail::clean_type_id(tname); |
333 | pybind11_fail("generic_type: type \"" + std::string(name) |
334 | + "\" referenced unknown base type \"" + tname + "\"" ); |
335 | } |
336 | |
337 | if (default_holder != base_info->default_holder) { |
338 | std::string tname(base.name()); |
339 | detail::clean_type_id(tname); |
340 | pybind11_fail("generic_type: type \"" + std::string(name) + "\" " |
341 | + (default_holder ? "does not have" : "has" ) |
342 | + " a non-default holder type while its base \"" + tname + "\" " |
343 | + (base_info->default_holder ? "does not" : "does" )); |
344 | } |
345 | |
346 | bases.append((PyObject *) base_info->type); |
347 | |
348 | #if PY_VERSION_HEX < 0x030B0000 |
349 | dynamic_attr |= base_info->type->tp_dictoffset != 0; |
350 | #else |
351 | dynamic_attr |= (base_info->type->tp_flags & Py_TPFLAGS_MANAGED_DICT) != 0; |
352 | #endif |
353 | |
354 | if (caster) { |
355 | base_info->implicit_casts.emplace_back(type, caster); |
356 | } |
357 | } |
358 | }; |
359 | |
360 | inline function_call::function_call(const function_record &f, handle p) : func(f), parent(p) { |
361 | args.reserve(f.nargs); |
362 | args_convert.reserve(f.nargs); |
363 | } |
364 | |
365 | /// Tag for a new-style `__init__` defined in `detail/init.h` |
366 | struct is_new_style_constructor {}; |
367 | |
368 | /** |
369 | * Partial template specializations to process custom attributes provided to |
370 | * cpp_function_ and class_. These are either used to initialize the respective |
371 | * fields in the type_record and function_record data structures or executed at |
372 | * runtime to deal with custom call policies (e.g. keep_alive). |
373 | */ |
374 | template <typename T, typename SFINAE = void> |
375 | struct process_attribute; |
376 | |
377 | template <typename T> |
378 | struct process_attribute_default { |
379 | /// Default implementation: do nothing |
380 | static void init(const T &, function_record *) {} |
381 | static void init(const T &, type_record *) {} |
382 | static void precall(function_call &) {} |
383 | static void postcall(function_call &, handle) {} |
384 | }; |
385 | |
386 | /// Process an attribute specifying the function's name |
387 | template <> |
388 | struct process_attribute<name> : process_attribute_default<name> { |
389 | static void init(const name &n, function_record *r) { r->name = const_cast<char *>(n.value); } |
390 | }; |
391 | |
392 | /// Process an attribute specifying the function's docstring |
393 | template <> |
394 | struct process_attribute<doc> : process_attribute_default<doc> { |
395 | static void init(const doc &n, function_record *r) { r->doc = const_cast<char *>(n.value); } |
396 | }; |
397 | |
398 | /// Process an attribute specifying the function's docstring (provided as a C-style string) |
399 | template <> |
400 | struct process_attribute<const char *> : process_attribute_default<const char *> { |
401 | static void init(const char *d, function_record *r) { r->doc = const_cast<char *>(d); } |
402 | static void init(const char *d, type_record *r) { r->doc = const_cast<char *>(d); } |
403 | }; |
404 | template <> |
405 | struct process_attribute<char *> : process_attribute<const char *> {}; |
406 | |
407 | /// Process an attribute indicating the function's return value policy |
408 | template <> |
409 | struct process_attribute<return_value_policy> : process_attribute_default<return_value_policy> { |
410 | static void init(const return_value_policy &p, function_record *r) { r->policy = p; } |
411 | }; |
412 | |
413 | /// Process an attribute which indicates that this is an overloaded function associated with a |
414 | /// given sibling |
415 | template <> |
416 | struct process_attribute<sibling> : process_attribute_default<sibling> { |
417 | static void init(const sibling &s, function_record *r) { r->sibling = s.value; } |
418 | }; |
419 | |
420 | /// Process an attribute which indicates that this function is a method |
421 | template <> |
422 | struct process_attribute<is_method> : process_attribute_default<is_method> { |
423 | static void init(const is_method &s, function_record *r) { |
424 | r->is_method = true; |
425 | r->scope = s.class_; |
426 | } |
427 | }; |
428 | |
429 | /// Process an attribute which indicates the parent scope of a method |
430 | template <> |
431 | struct process_attribute<scope> : process_attribute_default<scope> { |
432 | static void init(const scope &s, function_record *r) { r->scope = s.value; } |
433 | }; |
434 | |
435 | /// Process an attribute which indicates that this function is an operator |
436 | template <> |
437 | struct process_attribute<is_operator> : process_attribute_default<is_operator> { |
438 | static void init(const is_operator &, function_record *r) { r->is_operator = true; } |
439 | }; |
440 | |
441 | template <> |
442 | struct process_attribute<is_new_style_constructor> |
443 | : process_attribute_default<is_new_style_constructor> { |
444 | static void init(const is_new_style_constructor &, function_record *r) { |
445 | r->is_new_style_constructor = true; |
446 | } |
447 | }; |
448 | |
449 | inline void check_kw_only_arg(const arg &a, function_record *r) { |
450 | if (r->args.size() > r->nargs_pos && (!a.name || a.name[0] == '\0')) { |
451 | pybind11_fail("arg(): cannot specify an unnamed argument after a kw_only() annotation or " |
452 | "args() argument" ); |
453 | } |
454 | } |
455 | |
456 | inline void append_self_arg_if_needed(function_record *r) { |
457 | if (r->is_method && r->args.empty()) { |
458 | r->args.emplace_back("self" , nullptr, handle(), /*convert=*/true, /*none=*/false); |
459 | } |
460 | } |
461 | |
462 | /// Process a keyword argument attribute (*without* a default value) |
463 | template <> |
464 | struct process_attribute<arg> : process_attribute_default<arg> { |
465 | static void init(const arg &a, function_record *r) { |
466 | append_self_arg_if_needed(r); |
467 | r->args.emplace_back(a.name, nullptr, handle(), !a.flag_noconvert, a.flag_none); |
468 | |
469 | check_kw_only_arg(a, r); |
470 | } |
471 | }; |
472 | |
473 | /// Process a keyword argument attribute (*with* a default value) |
474 | template <> |
475 | struct process_attribute<arg_v> : process_attribute_default<arg_v> { |
476 | static void init(const arg_v &a, function_record *r) { |
477 | if (r->is_method && r->args.empty()) { |
478 | r->args.emplace_back( |
479 | "self" , /*descr=*/nullptr, /*parent=*/handle(), /*convert=*/true, /*none=*/false); |
480 | } |
481 | |
482 | if (!a.value) { |
483 | #if defined(PYBIND11_DETAILED_ERROR_MESSAGES) |
484 | std::string descr("'" ); |
485 | if (a.name) { |
486 | descr += std::string(a.name) + ": " ; |
487 | } |
488 | descr += a.type + "'" ; |
489 | if (r->is_method) { |
490 | if (r->name) { |
491 | descr += " in method '" + (std::string) str(r->scope) + "." |
492 | + (std::string) r->name + "'" ; |
493 | } else { |
494 | descr += " in method of '" + (std::string) str(r->scope) + "'" ; |
495 | } |
496 | } else if (r->name) { |
497 | descr += " in function '" + (std::string) r->name + "'" ; |
498 | } |
499 | pybind11_fail("arg(): could not convert default argument " + descr |
500 | + " into a Python object (type not registered yet?)" ); |
501 | #else |
502 | pybind11_fail("arg(): could not convert default argument " |
503 | "into a Python object (type not registered yet?). " |
504 | "#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for " |
505 | "more information." ); |
506 | #endif |
507 | } |
508 | r->args.emplace_back(a.name, a.descr, a.value.inc_ref(), !a.flag_noconvert, a.flag_none); |
509 | |
510 | check_kw_only_arg(a, r); |
511 | } |
512 | }; |
513 | |
514 | /// Process a keyword-only-arguments-follow pseudo argument |
515 | template <> |
516 | struct process_attribute<kw_only> : process_attribute_default<kw_only> { |
517 | static void init(const kw_only &, function_record *r) { |
518 | append_self_arg_if_needed(r); |
519 | if (r->has_args && r->nargs_pos != static_cast<std::uint16_t>(r->args.size())) { |
520 | pybind11_fail("Mismatched args() and kw_only(): they must occur at the same relative " |
521 | "argument location (or omit kw_only() entirely)" ); |
522 | } |
523 | r->nargs_pos = static_cast<std::uint16_t>(r->args.size()); |
524 | } |
525 | }; |
526 | |
527 | /// Process a positional-only-argument maker |
528 | template <> |
529 | struct process_attribute<pos_only> : process_attribute_default<pos_only> { |
530 | static void init(const pos_only &, function_record *r) { |
531 | append_self_arg_if_needed(r); |
532 | r->nargs_pos_only = static_cast<std::uint16_t>(r->args.size()); |
533 | if (r->nargs_pos_only > r->nargs_pos) { |
534 | pybind11_fail("pos_only(): cannot follow a py::args() argument" ); |
535 | } |
536 | // It also can't follow a kw_only, but a static_assert in pybind11.h checks that |
537 | } |
538 | }; |
539 | |
540 | /// Process a parent class attribute. Single inheritance only (class_ itself already guarantees |
541 | /// that) |
542 | template <typename T> |
543 | struct process_attribute<T, enable_if_t<is_pyobject<T>::value>> |
544 | : process_attribute_default<handle> { |
545 | static void init(const handle &h, type_record *r) { r->bases.append(h); } |
546 | }; |
547 | |
548 | /// Process a parent class attribute (deprecated, does not support multiple inheritance) |
549 | template <typename T> |
550 | struct process_attribute<base<T>> : process_attribute_default<base<T>> { |
551 | static void init(const base<T> &, type_record *r) { r->add_base(typeid(T), nullptr); } |
552 | }; |
553 | |
554 | /// Process a multiple inheritance attribute |
555 | template <> |
556 | struct process_attribute<multiple_inheritance> : process_attribute_default<multiple_inheritance> { |
557 | static void init(const multiple_inheritance &, type_record *r) { |
558 | r->multiple_inheritance = true; |
559 | } |
560 | }; |
561 | |
562 | template <> |
563 | struct process_attribute<dynamic_attr> : process_attribute_default<dynamic_attr> { |
564 | static void init(const dynamic_attr &, type_record *r) { r->dynamic_attr = true; } |
565 | }; |
566 | |
567 | template <> |
568 | struct process_attribute<custom_type_setup> { |
569 | static void init(const custom_type_setup &value, type_record *r) { |
570 | r->custom_type_setup_callback = value.value; |
571 | } |
572 | }; |
573 | |
574 | template <> |
575 | struct process_attribute<is_final> : process_attribute_default<is_final> { |
576 | static void init(const is_final &, type_record *r) { r->is_final = true; } |
577 | }; |
578 | |
579 | template <> |
580 | struct process_attribute<buffer_protocol> : process_attribute_default<buffer_protocol> { |
581 | static void init(const buffer_protocol &, type_record *r) { r->buffer_protocol = true; } |
582 | }; |
583 | |
584 | template <> |
585 | struct process_attribute<metaclass> : process_attribute_default<metaclass> { |
586 | static void init(const metaclass &m, type_record *r) { r->metaclass = m.value; } |
587 | }; |
588 | |
589 | template <> |
590 | struct process_attribute<module_local> : process_attribute_default<module_local> { |
591 | static void init(const module_local &l, type_record *r) { r->module_local = l.value; } |
592 | }; |
593 | |
594 | /// Process a 'prepend' attribute, putting this at the beginning of the overload chain |
595 | template <> |
596 | struct process_attribute<prepend> : process_attribute_default<prepend> { |
597 | static void init(const prepend &, function_record *r) { r->prepend = true; } |
598 | }; |
599 | |
600 | /// Process an 'arithmetic' attribute for enums (does nothing here) |
601 | template <> |
602 | struct process_attribute<arithmetic> : process_attribute_default<arithmetic> {}; |
603 | |
604 | template <typename... Ts> |
605 | struct process_attribute<call_guard<Ts...>> : process_attribute_default<call_guard<Ts...>> {}; |
606 | |
607 | /** |
608 | * Process a keep_alive call policy -- invokes keep_alive_impl during the |
609 | * pre-call handler if both Nurse, Patient != 0 and use the post-call handler |
610 | * otherwise |
611 | */ |
612 | template <size_t Nurse, size_t Patient> |
613 | struct process_attribute<keep_alive<Nurse, Patient>> |
614 | : public process_attribute_default<keep_alive<Nurse, Patient>> { |
615 | template <size_t N = Nurse, size_t P = Patient, enable_if_t<N != 0 && P != 0, int> = 0> |
616 | static void precall(function_call &call) { |
617 | keep_alive_impl(Nurse, Patient, call, handle()); |
618 | } |
619 | template <size_t N = Nurse, size_t P = Patient, enable_if_t<N != 0 && P != 0, int> = 0> |
620 | static void postcall(function_call &, handle) {} |
621 | template <size_t N = Nurse, size_t P = Patient, enable_if_t<N == 0 || P == 0, int> = 0> |
622 | static void precall(function_call &) {} |
623 | template <size_t N = Nurse, size_t P = Patient, enable_if_t<N == 0 || P == 0, int> = 0> |
624 | static void postcall(function_call &call, handle ret) { |
625 | keep_alive_impl(Nurse, Patient, call, ret); |
626 | } |
627 | }; |
628 | |
629 | /// Recursively iterate over variadic template arguments |
630 | template <typename... Args> |
631 | struct process_attributes { |
632 | static void init(const Args &...args, function_record *r) { |
633 | PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(r); |
634 | PYBIND11_WORKAROUND_INCORRECT_GCC_UNUSED_BUT_SET_PARAMETER(r); |
635 | using expander = int[]; |
636 | (void) expander{ |
637 | 0, ((void) process_attribute<typename std::decay<Args>::type>::init(args, r), 0)...}; |
638 | } |
639 | static void init(const Args &...args, type_record *r) { |
640 | PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(r); |
641 | PYBIND11_WORKAROUND_INCORRECT_GCC_UNUSED_BUT_SET_PARAMETER(r); |
642 | using expander = int[]; |
643 | (void) expander{0, |
644 | (process_attribute<typename std::decay<Args>::type>::init(args, r), 0)...}; |
645 | } |
646 | static void precall(function_call &call) { |
647 | PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(call); |
648 | using expander = int[]; |
649 | (void) expander{0, |
650 | (process_attribute<typename std::decay<Args>::type>::precall(call), 0)...}; |
651 | } |
652 | static void postcall(function_call &call, handle fn_ret) { |
653 | PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(call, fn_ret); |
654 | PYBIND11_WORKAROUND_INCORRECT_GCC_UNUSED_BUT_SET_PARAMETER(fn_ret); |
655 | using expander = int[]; |
656 | (void) expander{ |
657 | 0, (process_attribute<typename std::decay<Args>::type>::postcall(call, fn_ret), 0)...}; |
658 | } |
659 | }; |
660 | |
661 | template <typename T> |
662 | using is_call_guard = is_instantiation<call_guard, T>; |
663 | |
664 | /// Extract the ``type`` from the first `call_guard` in `Extras...` (or `void_type` if none found) |
665 | template <typename... Extra> |
666 | using = typename exactly_one_t<is_call_guard, call_guard<>, Extra...>::type; |
667 | |
668 | /// Check the number of named arguments at compile time |
669 | template <typename... Extra, |
670 | size_t named = constexpr_sum(std::is_base_of<arg, Extra>::value...), |
671 | size_t self = constexpr_sum(std::is_same<is_method, Extra>::value...)> |
672 | constexpr bool expected_num_args(size_t nargs, bool has_args, bool has_kwargs) { |
673 | PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(nargs, has_args, has_kwargs); |
674 | return named == 0 || (self + named + size_t(has_args) + size_t(has_kwargs)) == nargs; |
675 | } |
676 | |
677 | PYBIND11_NAMESPACE_END(detail) |
678 | PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE) |
679 | |