init.h 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
  2. /*
  3. pybind11/detail/init.h: init factory function implementation and support code.
  4. Copyright (c) 2017 Jason Rhinelander <jason@imaginary.ca>
  5. All rights reserved. Use of this source code is governed by a
  6. BSD-style license that can be found in the LICENSE file.
  7. */
  8. #pragma once
  9. #include "class.h"
  10. #include "using_smart_holder.h"
  11. PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
  12. PYBIND11_WARNING_DISABLE_MSVC(4127)
  13. PYBIND11_NAMESPACE_BEGIN(detail)
  14. template <>
  15. class type_caster<value_and_holder> {
  16. public:
  17. bool load(handle h, bool) {
  18. value = reinterpret_cast<value_and_holder *>(h.ptr());
  19. return true;
  20. }
  21. template <typename>
  22. using cast_op_type = value_and_holder &;
  23. explicit operator value_and_holder &() { return *value; }
  24. static constexpr auto name = const_name<value_and_holder>();
  25. private:
  26. value_and_holder *value = nullptr;
  27. };
  28. PYBIND11_NAMESPACE_BEGIN(initimpl)
  29. inline void no_nullptr(const void *ptr) {
  30. if (!ptr) {
  31. throw type_error("pybind11::init(): factory function returned nullptr");
  32. }
  33. }
  34. // Implementing functions for all forms of py::init<...> and py::init(...)
  35. template <typename Class>
  36. using Cpp = typename Class::type;
  37. template <typename Class>
  38. using Alias = typename Class::type_alias;
  39. template <typename Class>
  40. using Holder = typename Class::holder_type;
  41. template <typename Class>
  42. using is_alias_constructible = std::is_constructible<Alias<Class>, Cpp<Class> &&>;
  43. // Takes a Cpp pointer and returns true if it actually is a polymorphic Alias instance.
  44. template <typename Class, enable_if_t<Class::has_alias, int> = 0>
  45. bool is_alias(Cpp<Class> *ptr) {
  46. return dynamic_cast<Alias<Class> *>(ptr) != nullptr;
  47. }
  48. // Failing fallback version of the above for a no-alias class (always returns false)
  49. template <typename /*Class*/>
  50. constexpr bool is_alias(const void *) {
  51. return false;
  52. }
  53. // Constructs and returns a new object; if the given arguments don't map to a constructor, we fall
  54. // back to brace aggregate initialization so that for aggregate initialization can be used with
  55. // py::init, e.g. `py::init<int, int>` to initialize a `struct T { int a; int b; }`. For
  56. // non-aggregate types, we need to use an ordinary T(...) constructor (invoking as `T{...}` usually
  57. // works, but will not do the expected thing when `T` has an `initializer_list<T>` constructor).
  58. template <typename Class,
  59. typename... Args,
  60. detail::enable_if_t<std::is_constructible<Class, Args...>::value, int> = 0>
  61. inline Class *construct_or_initialize(Args &&...args) {
  62. return new Class(std::forward<Args>(args)...);
  63. }
  64. template <typename Class,
  65. typename... Args,
  66. detail::enable_if_t<!std::is_constructible<Class, Args...>::value, int> = 0>
  67. inline Class *construct_or_initialize(Args &&...args) {
  68. return new Class{std::forward<Args>(args)...};
  69. }
  70. // Attempts to constructs an alias using a `Alias(Cpp &&)` constructor. This allows types with
  71. // an alias to provide only a single Cpp factory function as long as the Alias can be
  72. // constructed from an rvalue reference of the base Cpp type. This means that Alias classes
  73. // can, when appropriate, simply define a `Alias(Cpp &&)` constructor rather than needing to
  74. // inherit all the base class constructors.
  75. template <typename Class>
  76. void construct_alias_from_cpp(std::true_type /*is_alias_constructible*/,
  77. value_and_holder &v_h,
  78. Cpp<Class> &&base) {
  79. v_h.value_ptr() = new Alias<Class>(std::move(base));
  80. }
  81. template <typename Class>
  82. [[noreturn]] void construct_alias_from_cpp(std::false_type /*!is_alias_constructible*/,
  83. value_and_holder &,
  84. Cpp<Class> &&) {
  85. throw type_error("pybind11::init(): unable to convert returned instance to required "
  86. "alias class: no `Alias<Class>(Class &&)` constructor available");
  87. }
  88. // Error-generating fallback for factories that don't match one of the below construction
  89. // mechanisms.
  90. template <typename Class>
  91. void construct(...) {
  92. static_assert(!std::is_same<Class, Class>::value /* always false */,
  93. "pybind11::init(): init function must return a compatible pointer, "
  94. "holder, or value");
  95. }
  96. // Pointer return v1: the factory function returns a class pointer for a registered class.
  97. // If we don't need an alias (because this class doesn't have one, or because the final type is
  98. // inherited on the Python side) we can simply take over ownership. Otherwise we need to try to
  99. // construct an Alias from the returned base instance.
  100. template <typename Class>
  101. void construct(value_and_holder &v_h, Cpp<Class> *ptr, bool need_alias) {
  102. PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(need_alias);
  103. no_nullptr(ptr);
  104. if (Class::has_alias && need_alias && !is_alias<Class>(ptr)) {
  105. // We're going to try to construct an alias by moving the cpp type. Whether or not
  106. // that succeeds, we still need to destroy the original cpp pointer (either the
  107. // moved away leftover, if the alias construction works, or the value itself if we
  108. // throw an error), but we can't just call `delete ptr`: it might have a special
  109. // deleter, or might be shared_from_this. So we construct a holder around it as if
  110. // it was a normal instance, then steal the holder away into a local variable; thus
  111. // the holder and destruction happens when we leave the C++ scope, and the holder
  112. // class gets to handle the destruction however it likes.
  113. v_h.value_ptr() = ptr;
  114. v_h.set_instance_registered(true); // Trick to prevent init_instance from registering it
  115. // DANGER ZONE BEGIN: exceptions will leave v_h in an invalid state.
  116. v_h.type->init_instance(v_h.inst, nullptr); // Set up the holder
  117. Holder<Class> temp_holder(std::move(v_h.holder<Holder<Class>>())); // Steal the holder
  118. v_h.type->dealloc(v_h); // Destroys the moved-out holder remains, resets value ptr to null
  119. v_h.set_instance_registered(false);
  120. // DANGER ZONE END.
  121. construct_alias_from_cpp<Class>(is_alias_constructible<Class>{}, v_h, std::move(*ptr));
  122. } else {
  123. // Otherwise the type isn't inherited, so we don't need an Alias
  124. v_h.value_ptr() = ptr;
  125. }
  126. }
  127. // Pointer return v2: a factory that always returns an alias instance ptr. We simply take over
  128. // ownership of the pointer.
  129. template <typename Class, enable_if_t<Class::has_alias, int> = 0>
  130. void construct(value_and_holder &v_h, Alias<Class> *alias_ptr, bool) {
  131. no_nullptr(alias_ptr);
  132. v_h.value_ptr() = static_cast<Cpp<Class> *>(alias_ptr);
  133. }
  134. // Holder return: copy its pointer, and move or copy the returned holder into the new instance's
  135. // holder. This also handles types like std::shared_ptr<T> and std::unique_ptr<T> where T is a
  136. // derived type (through those holder's implicit conversion from derived class holder
  137. // constructors).
  138. template <typename Class, detail::enable_if_t<!is_smart_holder<Holder<Class>>::value, int> = 0>
  139. void construct(value_and_holder &v_h, Holder<Class> holder, bool need_alias) {
  140. PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(need_alias);
  141. auto *ptr = holder_helper<Holder<Class>>::get(holder);
  142. no_nullptr(ptr);
  143. // If we need an alias, check that the held pointer is actually an alias instance
  144. if (Class::has_alias && need_alias && !is_alias<Class>(ptr)) {
  145. throw type_error("pybind11::init(): construction failed: returned holder-wrapped instance "
  146. "is not an alias instance");
  147. }
  148. // Cast away constness to store in void* storage.
  149. // The value_and_holder storage is fundamentally untyped (void**), so we lose
  150. // const-correctness here by design. The const qualifier will be restored
  151. // when the pointer is later retrieved and cast back to the original type.
  152. // This explicit const_cast makes the const-removal clearly visible.
  153. v_h.value_ptr() = const_cast<void *>(static_cast<const void *>(ptr));
  154. v_h.type->init_instance(v_h.inst, &holder);
  155. }
  156. // return-by-value version 1: returning a cpp class by value. If the class has an alias and an
  157. // alias is required the alias must have an `Alias(Cpp &&)` constructor so that we can construct
  158. // the alias from the base when needed (i.e. because of Python-side inheritance). When we don't
  159. // need it, we simply move-construct the cpp value into a new instance.
  160. template <typename Class>
  161. void construct(value_and_holder &v_h, Cpp<Class> &&result, bool need_alias) {
  162. PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(need_alias);
  163. static_assert(is_move_constructible<Cpp<Class>>::value,
  164. "pybind11::init() return-by-value factory function requires a movable class");
  165. if (Class::has_alias && need_alias) {
  166. construct_alias_from_cpp<Class>(is_alias_constructible<Class>{}, v_h, std::move(result));
  167. } else {
  168. v_h.value_ptr() = new Cpp<Class>(std::move(result));
  169. }
  170. }
  171. // return-by-value version 2: returning a value of the alias type itself. We move-construct an
  172. // Alias instance (even if no the python-side inheritance is involved). The is intended for
  173. // cases where Alias initialization is always desired.
  174. template <typename Class>
  175. void construct(value_and_holder &v_h, Alias<Class> &&result, bool) {
  176. static_assert(
  177. is_move_constructible<Alias<Class>>::value,
  178. "pybind11::init() return-by-alias-value factory function requires a movable alias class");
  179. v_h.value_ptr() = new Alias<Class>(std::move(result));
  180. }
  181. template <typename T, typename D>
  182. smart_holder init_smart_holder_from_unique_ptr(std::unique_ptr<T, D> &&unq_ptr,
  183. bool void_cast_raw_ptr) {
  184. void *void_ptr = void_cast_raw_ptr ? static_cast<void *>(unq_ptr.get()) : nullptr;
  185. return smart_holder::from_unique_ptr(std::move(unq_ptr), void_ptr);
  186. }
  187. template <typename Class,
  188. typename D = std::default_delete<Cpp<Class>>,
  189. detail::enable_if_t<is_smart_holder<Holder<Class>>::value, int> = 0>
  190. void construct(value_and_holder &v_h, std::unique_ptr<Cpp<Class>, D> &&unq_ptr, bool need_alias) {
  191. PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(need_alias);
  192. auto *ptr = unq_ptr.get();
  193. no_nullptr(ptr);
  194. if (Class::has_alias && need_alias && !is_alias<Class>(ptr)) {
  195. throw type_error("pybind11::init(): construction failed: returned std::unique_ptr pointee "
  196. "is not an alias instance");
  197. }
  198. // Here and below: if the new object is a trampoline, the shared_from_this mechanism needs
  199. // to be prevented from accessing the smart_holder vptr, because it does not keep the
  200. // trampoline Python object alive. For types that don't inherit from enable_shared_from_this
  201. // it does not matter if void_cast_raw_ptr is true or false, therefore it's not necessary
  202. // to also inspect the type.
  203. auto smhldr = init_smart_holder_from_unique_ptr(
  204. std::move(unq_ptr), /*void_cast_raw_ptr*/ Class::has_alias && is_alias<Class>(ptr));
  205. v_h.value_ptr() = ptr;
  206. v_h.type->init_instance(v_h.inst, &smhldr);
  207. }
  208. template <typename Class,
  209. typename D = std::default_delete<Alias<Class>>,
  210. detail::enable_if_t<is_smart_holder<Holder<Class>>::value, int> = 0>
  211. void construct(value_and_holder &v_h,
  212. std::unique_ptr<Alias<Class>, D> &&unq_ptr,
  213. bool /*need_alias*/) {
  214. auto *ptr = unq_ptr.get();
  215. no_nullptr(ptr);
  216. auto smhldr
  217. = init_smart_holder_from_unique_ptr(std::move(unq_ptr), /*void_cast_raw_ptr*/ true);
  218. v_h.value_ptr() = ptr;
  219. v_h.type->init_instance(v_h.inst, &smhldr);
  220. }
  221. template <typename PtrType, typename Class>
  222. void construct_from_shared_ptr(value_and_holder &v_h,
  223. std::shared_ptr<PtrType> &&shd_ptr,
  224. bool need_alias) {
  225. static_assert(std::is_same<PtrType, Cpp<Class>>::value
  226. || std::is_same<PtrType, const Cpp<Class>>::value,
  227. "Expected (const) Cpp<Class> as shared_ptr pointee");
  228. auto *ptr = shd_ptr.get();
  229. no_nullptr(ptr);
  230. if (Class::has_alias && need_alias && !is_alias<Class>(ptr)) {
  231. throw type_error("pybind11::init(): construction failed: returned std::shared_ptr pointee "
  232. "is not an alias instance");
  233. }
  234. // Cast to non-const if needed, consistent with internal design
  235. auto smhldr
  236. = smart_holder::from_shared_ptr(std::const_pointer_cast<Cpp<Class>>(std::move(shd_ptr)));
  237. v_h.value_ptr() = const_cast<Cpp<Class> *>(ptr);
  238. v_h.type->init_instance(v_h.inst, &smhldr);
  239. }
  240. template <typename Class, detail::enable_if_t<is_smart_holder<Holder<Class>>::value, int> = 0>
  241. void construct(value_and_holder &v_h, std::shared_ptr<Cpp<Class>> &&shd_ptr, bool need_alias) {
  242. construct_from_shared_ptr<Cpp<Class>, Class>(v_h, std::move(shd_ptr), need_alias);
  243. }
  244. template <typename Class, detail::enable_if_t<is_smart_holder<Holder<Class>>::value, int> = 0>
  245. void construct(value_and_holder &v_h,
  246. std::shared_ptr<const Cpp<Class>> &&shd_ptr,
  247. bool need_alias) {
  248. construct_from_shared_ptr<const Cpp<Class>, Class>(v_h, std::move(shd_ptr), need_alias);
  249. }
  250. template <typename Class, detail::enable_if_t<is_smart_holder<Holder<Class>>::value, int> = 0>
  251. void construct(value_and_holder &v_h,
  252. std::shared_ptr<Alias<Class>> &&shd_ptr,
  253. bool /*need_alias*/) {
  254. auto *ptr = shd_ptr.get();
  255. no_nullptr(ptr);
  256. auto smhldr = smart_holder::from_shared_ptr(shd_ptr);
  257. v_h.value_ptr() = ptr;
  258. v_h.type->init_instance(v_h.inst, &smhldr);
  259. }
  260. // Implementing class for py::init<...>()
  261. template <typename... Args>
  262. struct constructor {
  263. template <typename Class, typename... Extra, enable_if_t<!Class::has_alias, int> = 0>
  264. static void execute(Class &cl, const Extra &...extra) {
  265. cl.def(
  266. "__init__",
  267. [](value_and_holder &v_h,
  268. Args... args) { // NOLINT(performance-unnecessary-value-param)
  269. v_h.value_ptr() = construct_or_initialize<Cpp<Class>>(std::forward<Args>(args)...);
  270. },
  271. is_new_style_constructor(),
  272. extra...);
  273. }
  274. template <
  275. typename Class,
  276. typename... Extra,
  277. enable_if_t<Class::has_alias && std::is_constructible<Cpp<Class>, Args...>::value, int>
  278. = 0>
  279. static void execute(Class &cl, const Extra &...extra) {
  280. cl.def(
  281. "__init__",
  282. [](value_and_holder &v_h, Args... args) {
  283. if (Py_TYPE(v_h.inst) == v_h.type->type) {
  284. v_h.value_ptr()
  285. = construct_or_initialize<Cpp<Class>>(std::forward<Args>(args)...);
  286. } else {
  287. v_h.value_ptr()
  288. = construct_or_initialize<Alias<Class>>(std::forward<Args>(args)...);
  289. }
  290. },
  291. is_new_style_constructor(),
  292. extra...);
  293. }
  294. template <
  295. typename Class,
  296. typename... Extra,
  297. enable_if_t<Class::has_alias && !std::is_constructible<Cpp<Class>, Args...>::value, int>
  298. = 0>
  299. static void execute(Class &cl, const Extra &...extra) {
  300. cl.def(
  301. "__init__",
  302. [](value_and_holder &v_h, Args... args) {
  303. v_h.value_ptr()
  304. = construct_or_initialize<Alias<Class>>(std::forward<Args>(args)...);
  305. },
  306. is_new_style_constructor(),
  307. extra...);
  308. }
  309. };
  310. // Implementing class for py::init_alias<...>()
  311. template <typename... Args>
  312. struct alias_constructor {
  313. template <
  314. typename Class,
  315. typename... Extra,
  316. enable_if_t<Class::has_alias && std::is_constructible<Alias<Class>, Args...>::value, int>
  317. = 0>
  318. static void execute(Class &cl, const Extra &...extra) {
  319. cl.def(
  320. "__init__",
  321. [](value_and_holder &v_h, Args... args) {
  322. v_h.value_ptr()
  323. = construct_or_initialize<Alias<Class>>(std::forward<Args>(args)...);
  324. },
  325. is_new_style_constructor(),
  326. extra...);
  327. }
  328. };
  329. // Implementation class for py::init(Func) and py::init(Func, AliasFunc)
  330. template <typename CFunc,
  331. typename AFunc = void_type (*)(),
  332. typename = function_signature_t<CFunc>,
  333. typename = function_signature_t<AFunc>>
  334. struct factory;
  335. // Specialization for py::init(Func)
  336. template <typename Func, typename Return, typename... Args>
  337. struct factory<Func, void_type (*)(), Return(Args...)> {
  338. remove_reference_t<Func> class_factory;
  339. // NOLINTNEXTLINE(google-explicit-constructor)
  340. factory(Func &&f) : class_factory(std::forward<Func>(f)) {}
  341. // The given class either has no alias or has no separate alias factory;
  342. // this always constructs the class itself. If the class is registered with an alias
  343. // type and an alias instance is needed (i.e. because the final type is a Python class
  344. // inheriting from the C++ type) the returned value needs to either already be an alias
  345. // instance, or the alias needs to be constructible from a `Class &&` argument.
  346. template <typename Class, typename... Extra>
  347. void execute(Class &cl, const Extra &...extra) && {
  348. #if defined(PYBIND11_CPP14)
  349. cl.def(
  350. "__init__",
  351. [func = std::move(class_factory)]
  352. #else
  353. auto &func = class_factory;
  354. cl.def(
  355. "__init__",
  356. [func]
  357. #endif
  358. (value_and_holder &v_h, Args... args) {
  359. construct<Class>(
  360. v_h, func(std::forward<Args>(args)...), Py_TYPE(v_h.inst) != v_h.type->type);
  361. },
  362. is_new_style_constructor(),
  363. extra...);
  364. }
  365. };
  366. // Specialization for py::init(Func, AliasFunc)
  367. template <typename CFunc,
  368. typename AFunc,
  369. typename CReturn,
  370. typename... CArgs,
  371. typename AReturn,
  372. typename... AArgs>
  373. struct factory<CFunc, AFunc, CReturn(CArgs...), AReturn(AArgs...)> {
  374. static_assert(sizeof...(CArgs) == sizeof...(AArgs),
  375. "pybind11::init(class_factory, alias_factory): class and alias factories "
  376. "must have identical argument signatures");
  377. static_assert(all_of<std::is_same<CArgs, AArgs>...>::value,
  378. "pybind11::init(class_factory, alias_factory): class and alias factories "
  379. "must have identical argument signatures");
  380. remove_reference_t<CFunc> class_factory;
  381. remove_reference_t<AFunc> alias_factory;
  382. factory(CFunc &&c, AFunc &&a)
  383. : class_factory(std::forward<CFunc>(c)), alias_factory(std::forward<AFunc>(a)) {}
  384. // The class factory is called when the `self` type passed to `__init__` is the direct
  385. // class (i.e. not inherited), the alias factory when `self` is a Python-side subtype.
  386. template <typename Class, typename... Extra>
  387. void execute(Class &cl, const Extra &...extra) && {
  388. static_assert(Class::has_alias,
  389. "The two-argument version of `py::init()` can "
  390. "only be used if the class has an alias");
  391. #if defined(PYBIND11_CPP14)
  392. cl.def(
  393. "__init__",
  394. [class_func = std::move(class_factory), alias_func = std::move(alias_factory)]
  395. #else
  396. auto &class_func = class_factory;
  397. auto &alias_func = alias_factory;
  398. cl.def(
  399. "__init__",
  400. [class_func, alias_func]
  401. #endif
  402. (value_and_holder &v_h, CArgs... args) {
  403. if (Py_TYPE(v_h.inst) == v_h.type->type) {
  404. // If the instance type equals the registered type we don't have inheritance,
  405. // so don't need the alias and can construct using the class function:
  406. construct<Class>(v_h, class_func(std::forward<CArgs>(args)...), false);
  407. } else {
  408. construct<Class>(v_h, alias_func(std::forward<CArgs>(args)...), true);
  409. }
  410. },
  411. is_new_style_constructor(),
  412. extra...);
  413. }
  414. };
  415. /// Set just the C++ state. Same as `__init__`.
  416. template <typename Class, typename T>
  417. void setstate(value_and_holder &v_h, T &&result, bool need_alias) {
  418. construct<Class>(v_h, std::forward<T>(result), need_alias);
  419. }
  420. /// Set both the C++ and Python states
  421. template <typename Class,
  422. typename T,
  423. typename O,
  424. enable_if_t<std::is_convertible<O, handle>::value, int> = 0>
  425. void setstate(value_and_holder &v_h, std::pair<T, O> &&result, bool need_alias) {
  426. construct<Class>(v_h, std::move(result.first), need_alias);
  427. auto d = handle(result.second);
  428. if (PyDict_Check(d.ptr()) && PyDict_Size(d.ptr()) == 0) {
  429. // Skipping setattr below, to not force use of py::dynamic_attr() for Class unnecessarily.
  430. // See PR #2972 for details.
  431. return;
  432. }
  433. // Our tests never run into an unset dict, but being careful here for now (see #5658)
  434. auto dict = getattr((PyObject *) v_h.inst, "__dict__", none());
  435. if (dict.is_none()) {
  436. setattr((PyObject *) v_h.inst, "__dict__", d);
  437. } else {
  438. // Keep the original object dict and just update it
  439. if (PyDict_Update(dict.ptr(), d.ptr()) < 0) {
  440. throw error_already_set();
  441. }
  442. }
  443. }
  444. /// Implementation for py::pickle(GetState, SetState)
  445. template <typename Get,
  446. typename Set,
  447. typename = function_signature_t<Get>,
  448. typename = function_signature_t<Set>>
  449. struct pickle_factory;
  450. template <typename Get,
  451. typename Set,
  452. typename RetState,
  453. typename Self,
  454. typename NewInstance,
  455. typename ArgState>
  456. struct pickle_factory<Get, Set, RetState(Self), NewInstance(ArgState)> {
  457. static_assert(std::is_same<intrinsic_t<RetState>, intrinsic_t<ArgState>>::value,
  458. "The type returned by `__getstate__` must be the same "
  459. "as the argument accepted by `__setstate__`");
  460. remove_reference_t<Get> get;
  461. remove_reference_t<Set> set;
  462. pickle_factory(Get get, Set set) : get(std::forward<Get>(get)), set(std::forward<Set>(set)) {}
  463. template <typename Class, typename... Extra>
  464. void execute(Class &cl, const Extra &...extra) && {
  465. cl.def("__getstate__", std::move(get), pos_only());
  466. #if defined(PYBIND11_CPP14)
  467. cl.def(
  468. "__setstate__",
  469. [func = std::move(set)]
  470. #else
  471. auto &func = set;
  472. cl.def(
  473. "__setstate__",
  474. [func]
  475. #endif
  476. (value_and_holder &v_h, ArgState state) {
  477. setstate<Class>(
  478. v_h, func(std::forward<ArgState>(state)), Py_TYPE(v_h.inst) != v_h.type->type);
  479. },
  480. is_new_style_constructor(),
  481. extra...);
  482. }
  483. };
  484. PYBIND11_NAMESPACE_END(initimpl)
  485. PYBIND11_NAMESPACE_END(detail)
  486. PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
  487. #else
  488. #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
  489. #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)