112391Sjason@lowepower.com/* 212391Sjason@lowepower.com pybind11/detail/init.h: init factory function implementation and support code. 312391Sjason@lowepower.com 412391Sjason@lowepower.com Copyright (c) 2017 Jason Rhinelander <jason@imaginary.ca> 512391Sjason@lowepower.com 612391Sjason@lowepower.com All rights reserved. Use of this source code is governed by a 712391Sjason@lowepower.com BSD-style license that can be found in the LICENSE file. 812391Sjason@lowepower.com*/ 912391Sjason@lowepower.com 1012391Sjason@lowepower.com#pragma once 1112391Sjason@lowepower.com 1212391Sjason@lowepower.com#include "class.h" 1312391Sjason@lowepower.com 1412391Sjason@lowepower.comNAMESPACE_BEGIN(PYBIND11_NAMESPACE) 1512391Sjason@lowepower.comNAMESPACE_BEGIN(detail) 1612391Sjason@lowepower.com 1712391Sjason@lowepower.comtemplate <> 1812391Sjason@lowepower.comclass type_caster<value_and_holder> { 1912391Sjason@lowepower.compublic: 2012391Sjason@lowepower.com bool load(handle h, bool) { 2112391Sjason@lowepower.com value = reinterpret_cast<value_and_holder *>(h.ptr()); 2212391Sjason@lowepower.com return true; 2312391Sjason@lowepower.com } 2412391Sjason@lowepower.com 2512391Sjason@lowepower.com template <typename> using cast_op_type = value_and_holder &; 2612391Sjason@lowepower.com operator value_and_holder &() { return *value; } 2714299Sbbruce@ucdavis.edu static constexpr auto name = _<value_and_holder>(); 2812391Sjason@lowepower.com 2912391Sjason@lowepower.comprivate: 3012391Sjason@lowepower.com value_and_holder *value = nullptr; 3112391Sjason@lowepower.com}; 3212391Sjason@lowepower.com 3312391Sjason@lowepower.comNAMESPACE_BEGIN(initimpl) 3412391Sjason@lowepower.com 3512391Sjason@lowepower.cominline void no_nullptr(void *ptr) { 3612391Sjason@lowepower.com if (!ptr) throw type_error("pybind11::init(): factory function returned nullptr"); 3712391Sjason@lowepower.com} 3812391Sjason@lowepower.com 3912391Sjason@lowepower.com// Implementing functions for all forms of py::init<...> and py::init(...) 4012391Sjason@lowepower.comtemplate <typename Class> using Cpp = typename Class::type; 4112391Sjason@lowepower.comtemplate <typename Class> using Alias = typename Class::type_alias; 4212391Sjason@lowepower.comtemplate <typename Class> using Holder = typename Class::holder_type; 4312391Sjason@lowepower.com 4412391Sjason@lowepower.comtemplate <typename Class> using is_alias_constructible = std::is_constructible<Alias<Class>, Cpp<Class> &&>; 4512391Sjason@lowepower.com 4612391Sjason@lowepower.com// Takes a Cpp pointer and returns true if it actually is a polymorphic Alias instance. 4712391Sjason@lowepower.comtemplate <typename Class, enable_if_t<Class::has_alias, int> = 0> 4812391Sjason@lowepower.combool is_alias(Cpp<Class> *ptr) { 4912391Sjason@lowepower.com return dynamic_cast<Alias<Class> *>(ptr) != nullptr; 5012391Sjason@lowepower.com} 5112391Sjason@lowepower.com// Failing fallback version of the above for a no-alias class (always returns false) 5212391Sjason@lowepower.comtemplate <typename /*Class*/> 5312391Sjason@lowepower.comconstexpr bool is_alias(void *) { return false; } 5412391Sjason@lowepower.com 5514299Sbbruce@ucdavis.edu// Constructs and returns a new object; if the given arguments don't map to a constructor, we fall 5614299Sbbruce@ucdavis.edu// back to brace aggregate initiailization so that for aggregate initialization can be used with 5714299Sbbruce@ucdavis.edu// py::init, e.g. `py::init<int, int>` to initialize a `struct T { int a; int b; }`. For 5814299Sbbruce@ucdavis.edu// non-aggregate types, we need to use an ordinary T(...) constructor (invoking as `T{...}` usually 5914299Sbbruce@ucdavis.edu// works, but will not do the expected thing when `T` has an `initializer_list<T>` constructor). 6014299Sbbruce@ucdavis.edutemplate <typename Class, typename... Args, detail::enable_if_t<std::is_constructible<Class, Args...>::value, int> = 0> 6114299Sbbruce@ucdavis.eduinline Class *construct_or_initialize(Args &&...args) { return new Class(std::forward<Args>(args)...); } 6214299Sbbruce@ucdavis.edutemplate <typename Class, typename... Args, detail::enable_if_t<!std::is_constructible<Class, Args...>::value, int> = 0> 6314299Sbbruce@ucdavis.eduinline Class *construct_or_initialize(Args &&...args) { return new Class{std::forward<Args>(args)...}; } 6414299Sbbruce@ucdavis.edu 6512391Sjason@lowepower.com// Attempts to constructs an alias using a `Alias(Cpp &&)` constructor. This allows types with 6612391Sjason@lowepower.com// an alias to provide only a single Cpp factory function as long as the Alias can be 6712391Sjason@lowepower.com// constructed from an rvalue reference of the base Cpp type. This means that Alias classes 6812391Sjason@lowepower.com// can, when appropriate, simply define a `Alias(Cpp &&)` constructor rather than needing to 6912391Sjason@lowepower.com// inherit all the base class constructors. 7012391Sjason@lowepower.comtemplate <typename Class> 7112391Sjason@lowepower.comvoid construct_alias_from_cpp(std::true_type /*is_alias_constructible*/, 7212391Sjason@lowepower.com value_and_holder &v_h, Cpp<Class> &&base) { 7312391Sjason@lowepower.com v_h.value_ptr() = new Alias<Class>(std::move(base)); 7412391Sjason@lowepower.com} 7512391Sjason@lowepower.comtemplate <typename Class> 7612391Sjason@lowepower.com[[noreturn]] void construct_alias_from_cpp(std::false_type /*!is_alias_constructible*/, 7712391Sjason@lowepower.com value_and_holder &, Cpp<Class> &&) { 7812391Sjason@lowepower.com throw type_error("pybind11::init(): unable to convert returned instance to required " 7912391Sjason@lowepower.com "alias class: no `Alias<Class>(Class &&)` constructor available"); 8012391Sjason@lowepower.com} 8112391Sjason@lowepower.com 8212391Sjason@lowepower.com// Error-generating fallback for factories that don't match one of the below construction 8312391Sjason@lowepower.com// mechanisms. 8412391Sjason@lowepower.comtemplate <typename Class> 8512391Sjason@lowepower.comvoid construct(...) { 8612391Sjason@lowepower.com static_assert(!std::is_same<Class, Class>::value /* always false */, 8712391Sjason@lowepower.com "pybind11::init(): init function must return a compatible pointer, " 8812391Sjason@lowepower.com "holder, or value"); 8912391Sjason@lowepower.com} 9012391Sjason@lowepower.com 9112391Sjason@lowepower.com// Pointer return v1: the factory function returns a class pointer for a registered class. 9212391Sjason@lowepower.com// If we don't need an alias (because this class doesn't have one, or because the final type is 9312391Sjason@lowepower.com// inherited on the Python side) we can simply take over ownership. Otherwise we need to try to 9412391Sjason@lowepower.com// construct an Alias from the returned base instance. 9512391Sjason@lowepower.comtemplate <typename Class> 9612391Sjason@lowepower.comvoid construct(value_and_holder &v_h, Cpp<Class> *ptr, bool need_alias) { 9712391Sjason@lowepower.com no_nullptr(ptr); 9812391Sjason@lowepower.com if (Class::has_alias && need_alias && !is_alias<Class>(ptr)) { 9912391Sjason@lowepower.com // We're going to try to construct an alias by moving the cpp type. Whether or not 10012391Sjason@lowepower.com // that succeeds, we still need to destroy the original cpp pointer (either the 10112391Sjason@lowepower.com // moved away leftover, if the alias construction works, or the value itself if we 10212391Sjason@lowepower.com // throw an error), but we can't just call `delete ptr`: it might have a special 10312391Sjason@lowepower.com // deleter, or might be shared_from_this. So we construct a holder around it as if 10412391Sjason@lowepower.com // it was a normal instance, then steal the holder away into a local variable; thus 10512391Sjason@lowepower.com // the holder and destruction happens when we leave the C++ scope, and the holder 10612391Sjason@lowepower.com // class gets to handle the destruction however it likes. 10712391Sjason@lowepower.com v_h.value_ptr() = ptr; 10812391Sjason@lowepower.com v_h.set_instance_registered(true); // To prevent init_instance from registering it 10912391Sjason@lowepower.com v_h.type->init_instance(v_h.inst, nullptr); // Set up the holder 11012391Sjason@lowepower.com Holder<Class> temp_holder(std::move(v_h.holder<Holder<Class>>())); // Steal the holder 11112391Sjason@lowepower.com v_h.type->dealloc(v_h); // Destroys the moved-out holder remains, resets value ptr to null 11212391Sjason@lowepower.com v_h.set_instance_registered(false); 11312391Sjason@lowepower.com 11412391Sjason@lowepower.com construct_alias_from_cpp<Class>(is_alias_constructible<Class>{}, v_h, std::move(*ptr)); 11512391Sjason@lowepower.com } else { 11612391Sjason@lowepower.com // Otherwise the type isn't inherited, so we don't need an Alias 11712391Sjason@lowepower.com v_h.value_ptr() = ptr; 11812391Sjason@lowepower.com } 11912391Sjason@lowepower.com} 12012391Sjason@lowepower.com 12112391Sjason@lowepower.com// Pointer return v2: a factory that always returns an alias instance ptr. We simply take over 12212391Sjason@lowepower.com// ownership of the pointer. 12312391Sjason@lowepower.comtemplate <typename Class, enable_if_t<Class::has_alias, int> = 0> 12412391Sjason@lowepower.comvoid construct(value_and_holder &v_h, Alias<Class> *alias_ptr, bool) { 12512391Sjason@lowepower.com no_nullptr(alias_ptr); 12612391Sjason@lowepower.com v_h.value_ptr() = static_cast<Cpp<Class> *>(alias_ptr); 12712391Sjason@lowepower.com} 12812391Sjason@lowepower.com 12912391Sjason@lowepower.com// Holder return: copy its pointer, and move or copy the returned holder into the new instance's 13012391Sjason@lowepower.com// holder. This also handles types like std::shared_ptr<T> and std::unique_ptr<T> where T is a 13112391Sjason@lowepower.com// derived type (through those holder's implicit conversion from derived class holder constructors). 13212391Sjason@lowepower.comtemplate <typename Class> 13312391Sjason@lowepower.comvoid construct(value_and_holder &v_h, Holder<Class> holder, bool need_alias) { 13412391Sjason@lowepower.com auto *ptr = holder_helper<Holder<Class>>::get(holder); 13512391Sjason@lowepower.com // If we need an alias, check that the held pointer is actually an alias instance 13612391Sjason@lowepower.com if (Class::has_alias && need_alias && !is_alias<Class>(ptr)) 13712391Sjason@lowepower.com throw type_error("pybind11::init(): construction failed: returned holder-wrapped instance " 13812391Sjason@lowepower.com "is not an alias instance"); 13912391Sjason@lowepower.com 14012391Sjason@lowepower.com v_h.value_ptr() = ptr; 14112391Sjason@lowepower.com v_h.type->init_instance(v_h.inst, &holder); 14212391Sjason@lowepower.com} 14312391Sjason@lowepower.com 14412391Sjason@lowepower.com// return-by-value version 1: returning a cpp class by value. If the class has an alias and an 14512391Sjason@lowepower.com// alias is required the alias must have an `Alias(Cpp &&)` constructor so that we can construct 14612391Sjason@lowepower.com// the alias from the base when needed (i.e. because of Python-side inheritance). When we don't 14712391Sjason@lowepower.com// need it, we simply move-construct the cpp value into a new instance. 14812391Sjason@lowepower.comtemplate <typename Class> 14912391Sjason@lowepower.comvoid construct(value_and_holder &v_h, Cpp<Class> &&result, bool need_alias) { 15012391Sjason@lowepower.com static_assert(std::is_move_constructible<Cpp<Class>>::value, 15112391Sjason@lowepower.com "pybind11::init() return-by-value factory function requires a movable class"); 15212391Sjason@lowepower.com if (Class::has_alias && need_alias) 15312391Sjason@lowepower.com construct_alias_from_cpp<Class>(is_alias_constructible<Class>{}, v_h, std::move(result)); 15412391Sjason@lowepower.com else 15512391Sjason@lowepower.com v_h.value_ptr() = new Cpp<Class>(std::move(result)); 15612391Sjason@lowepower.com} 15712391Sjason@lowepower.com 15812391Sjason@lowepower.com// return-by-value version 2: returning a value of the alias type itself. We move-construct an 15912391Sjason@lowepower.com// Alias instance (even if no the python-side inheritance is involved). The is intended for 16012391Sjason@lowepower.com// cases where Alias initialization is always desired. 16112391Sjason@lowepower.comtemplate <typename Class> 16212391Sjason@lowepower.comvoid construct(value_and_holder &v_h, Alias<Class> &&result, bool) { 16312391Sjason@lowepower.com static_assert(std::is_move_constructible<Alias<Class>>::value, 16412391Sjason@lowepower.com "pybind11::init() return-by-alias-value factory function requires a movable alias class"); 16512391Sjason@lowepower.com v_h.value_ptr() = new Alias<Class>(std::move(result)); 16612391Sjason@lowepower.com} 16712391Sjason@lowepower.com 16812391Sjason@lowepower.com// Implementing class for py::init<...>() 16912391Sjason@lowepower.comtemplate <typename... Args> 17012391Sjason@lowepower.comstruct constructor { 17112391Sjason@lowepower.com template <typename Class, typename... Extra, enable_if_t<!Class::has_alias, int> = 0> 17212391Sjason@lowepower.com static void execute(Class &cl, const Extra&... extra) { 17312391Sjason@lowepower.com cl.def("__init__", [](value_and_holder &v_h, Args... args) { 17414299Sbbruce@ucdavis.edu v_h.value_ptr() = construct_or_initialize<Cpp<Class>>(std::forward<Args>(args)...); 17512391Sjason@lowepower.com }, is_new_style_constructor(), extra...); 17612391Sjason@lowepower.com } 17712391Sjason@lowepower.com 17812391Sjason@lowepower.com template <typename Class, typename... Extra, 17912391Sjason@lowepower.com enable_if_t<Class::has_alias && 18012391Sjason@lowepower.com std::is_constructible<Cpp<Class>, Args...>::value, int> = 0> 18112391Sjason@lowepower.com static void execute(Class &cl, const Extra&... extra) { 18212391Sjason@lowepower.com cl.def("__init__", [](value_and_holder &v_h, Args... args) { 18312391Sjason@lowepower.com if (Py_TYPE(v_h.inst) == v_h.type->type) 18414299Sbbruce@ucdavis.edu v_h.value_ptr() = construct_or_initialize<Cpp<Class>>(std::forward<Args>(args)...); 18512391Sjason@lowepower.com else 18614299Sbbruce@ucdavis.edu v_h.value_ptr() = construct_or_initialize<Alias<Class>>(std::forward<Args>(args)...); 18712391Sjason@lowepower.com }, is_new_style_constructor(), extra...); 18812391Sjason@lowepower.com } 18912391Sjason@lowepower.com 19012391Sjason@lowepower.com template <typename Class, typename... Extra, 19112391Sjason@lowepower.com enable_if_t<Class::has_alias && 19212391Sjason@lowepower.com !std::is_constructible<Cpp<Class>, Args...>::value, int> = 0> 19312391Sjason@lowepower.com static void execute(Class &cl, const Extra&... extra) { 19412391Sjason@lowepower.com cl.def("__init__", [](value_and_holder &v_h, Args... args) { 19514299Sbbruce@ucdavis.edu v_h.value_ptr() = construct_or_initialize<Alias<Class>>(std::forward<Args>(args)...); 19612391Sjason@lowepower.com }, is_new_style_constructor(), extra...); 19712391Sjason@lowepower.com } 19812391Sjason@lowepower.com}; 19912391Sjason@lowepower.com 20012391Sjason@lowepower.com// Implementing class for py::init_alias<...>() 20112391Sjason@lowepower.comtemplate <typename... Args> struct alias_constructor { 20212391Sjason@lowepower.com template <typename Class, typename... Extra, 20312391Sjason@lowepower.com enable_if_t<Class::has_alias && std::is_constructible<Alias<Class>, Args...>::value, int> = 0> 20412391Sjason@lowepower.com static void execute(Class &cl, const Extra&... extra) { 20512391Sjason@lowepower.com cl.def("__init__", [](value_and_holder &v_h, Args... args) { 20614299Sbbruce@ucdavis.edu v_h.value_ptr() = construct_or_initialize<Alias<Class>>(std::forward<Args>(args)...); 20712391Sjason@lowepower.com }, is_new_style_constructor(), extra...); 20812391Sjason@lowepower.com } 20912391Sjason@lowepower.com}; 21012391Sjason@lowepower.com 21112391Sjason@lowepower.com// Implementation class for py::init(Func) and py::init(Func, AliasFunc) 21212391Sjason@lowepower.comtemplate <typename CFunc, typename AFunc = void_type (*)(), 21312391Sjason@lowepower.com typename = function_signature_t<CFunc>, typename = function_signature_t<AFunc>> 21412391Sjason@lowepower.comstruct factory; 21512391Sjason@lowepower.com 21612391Sjason@lowepower.com// Specialization for py::init(Func) 21712391Sjason@lowepower.comtemplate <typename Func, typename Return, typename... Args> 21812391Sjason@lowepower.comstruct factory<Func, void_type (*)(), Return(Args...)> { 21912391Sjason@lowepower.com remove_reference_t<Func> class_factory; 22012391Sjason@lowepower.com 22112391Sjason@lowepower.com factory(Func &&f) : class_factory(std::forward<Func>(f)) { } 22212391Sjason@lowepower.com 22312391Sjason@lowepower.com // The given class either has no alias or has no separate alias factory; 22412391Sjason@lowepower.com // this always constructs the class itself. If the class is registered with an alias 22512391Sjason@lowepower.com // type and an alias instance is needed (i.e. because the final type is a Python class 22612391Sjason@lowepower.com // inheriting from the C++ type) the returned value needs to either already be an alias 22712391Sjason@lowepower.com // instance, or the alias needs to be constructible from a `Class &&` argument. 22812391Sjason@lowepower.com template <typename Class, typename... Extra> 22912391Sjason@lowepower.com void execute(Class &cl, const Extra &...extra) && { 23012391Sjason@lowepower.com #if defined(PYBIND11_CPP14) 23112391Sjason@lowepower.com cl.def("__init__", [func = std::move(class_factory)] 23212391Sjason@lowepower.com #else 23312391Sjason@lowepower.com auto &func = class_factory; 23412391Sjason@lowepower.com cl.def("__init__", [func] 23512391Sjason@lowepower.com #endif 23612391Sjason@lowepower.com (value_and_holder &v_h, Args... args) { 23712391Sjason@lowepower.com construct<Class>(v_h, func(std::forward<Args>(args)...), 23812391Sjason@lowepower.com Py_TYPE(v_h.inst) != v_h.type->type); 23912391Sjason@lowepower.com }, is_new_style_constructor(), extra...); 24012391Sjason@lowepower.com } 24112391Sjason@lowepower.com}; 24212391Sjason@lowepower.com 24312391Sjason@lowepower.com// Specialization for py::init(Func, AliasFunc) 24412391Sjason@lowepower.comtemplate <typename CFunc, typename AFunc, 24512391Sjason@lowepower.com typename CReturn, typename... CArgs, typename AReturn, typename... AArgs> 24612391Sjason@lowepower.comstruct factory<CFunc, AFunc, CReturn(CArgs...), AReturn(AArgs...)> { 24712391Sjason@lowepower.com static_assert(sizeof...(CArgs) == sizeof...(AArgs), 24812391Sjason@lowepower.com "pybind11::init(class_factory, alias_factory): class and alias factories " 24912391Sjason@lowepower.com "must have identical argument signatures"); 25012391Sjason@lowepower.com static_assert(all_of<std::is_same<CArgs, AArgs>...>::value, 25112391Sjason@lowepower.com "pybind11::init(class_factory, alias_factory): class and alias factories " 25212391Sjason@lowepower.com "must have identical argument signatures"); 25312391Sjason@lowepower.com 25412391Sjason@lowepower.com remove_reference_t<CFunc> class_factory; 25512391Sjason@lowepower.com remove_reference_t<AFunc> alias_factory; 25612391Sjason@lowepower.com 25712391Sjason@lowepower.com factory(CFunc &&c, AFunc &&a) 25812391Sjason@lowepower.com : class_factory(std::forward<CFunc>(c)), alias_factory(std::forward<AFunc>(a)) { } 25912391Sjason@lowepower.com 26012391Sjason@lowepower.com // The class factory is called when the `self` type passed to `__init__` is the direct 26112391Sjason@lowepower.com // class (i.e. not inherited), the alias factory when `self` is a Python-side subtype. 26212391Sjason@lowepower.com template <typename Class, typename... Extra> 26312391Sjason@lowepower.com void execute(Class &cl, const Extra&... extra) && { 26412391Sjason@lowepower.com static_assert(Class::has_alias, "The two-argument version of `py::init()` can " 26512391Sjason@lowepower.com "only be used if the class has an alias"); 26612391Sjason@lowepower.com #if defined(PYBIND11_CPP14) 26712391Sjason@lowepower.com cl.def("__init__", [class_func = std::move(class_factory), alias_func = std::move(alias_factory)] 26812391Sjason@lowepower.com #else 26912391Sjason@lowepower.com auto &class_func = class_factory; 27012391Sjason@lowepower.com auto &alias_func = alias_factory; 27112391Sjason@lowepower.com cl.def("__init__", [class_func, alias_func] 27212391Sjason@lowepower.com #endif 27312391Sjason@lowepower.com (value_and_holder &v_h, CArgs... args) { 27412391Sjason@lowepower.com if (Py_TYPE(v_h.inst) == v_h.type->type) 27512391Sjason@lowepower.com // If the instance type equals the registered type we don't have inheritance, so 27612391Sjason@lowepower.com // don't need the alias and can construct using the class function: 27712391Sjason@lowepower.com construct<Class>(v_h, class_func(std::forward<CArgs>(args)...), false); 27812391Sjason@lowepower.com else 27912391Sjason@lowepower.com construct<Class>(v_h, alias_func(std::forward<CArgs>(args)...), true); 28012391Sjason@lowepower.com }, is_new_style_constructor(), extra...); 28112391Sjason@lowepower.com } 28212391Sjason@lowepower.com}; 28312391Sjason@lowepower.com 28412391Sjason@lowepower.com/// Set just the C++ state. Same as `__init__`. 28512391Sjason@lowepower.comtemplate <typename Class, typename T> 28612391Sjason@lowepower.comvoid setstate(value_and_holder &v_h, T &&result, bool need_alias) { 28712391Sjason@lowepower.com construct<Class>(v_h, std::forward<T>(result), need_alias); 28812391Sjason@lowepower.com} 28912391Sjason@lowepower.com 29012391Sjason@lowepower.com/// Set both the C++ and Python states 29112391Sjason@lowepower.comtemplate <typename Class, typename T, typename O, 29212391Sjason@lowepower.com enable_if_t<std::is_convertible<O, handle>::value, int> = 0> 29312391Sjason@lowepower.comvoid setstate(value_and_holder &v_h, std::pair<T, O> &&result, bool need_alias) { 29412391Sjason@lowepower.com construct<Class>(v_h, std::move(result.first), need_alias); 29512391Sjason@lowepower.com setattr((PyObject *) v_h.inst, "__dict__", result.second); 29612391Sjason@lowepower.com} 29712391Sjason@lowepower.com 29812391Sjason@lowepower.com/// Implementation for py::pickle(GetState, SetState) 29912391Sjason@lowepower.comtemplate <typename Get, typename Set, 30012391Sjason@lowepower.com typename = function_signature_t<Get>, typename = function_signature_t<Set>> 30112391Sjason@lowepower.comstruct pickle_factory; 30212391Sjason@lowepower.com 30312391Sjason@lowepower.comtemplate <typename Get, typename Set, 30412391Sjason@lowepower.com typename RetState, typename Self, typename NewInstance, typename ArgState> 30512391Sjason@lowepower.comstruct pickle_factory<Get, Set, RetState(Self), NewInstance(ArgState)> { 30612391Sjason@lowepower.com static_assert(std::is_same<intrinsic_t<RetState>, intrinsic_t<ArgState>>::value, 30712391Sjason@lowepower.com "The type returned by `__getstate__` must be the same " 30812391Sjason@lowepower.com "as the argument accepted by `__setstate__`"); 30912391Sjason@lowepower.com 31012391Sjason@lowepower.com remove_reference_t<Get> get; 31112391Sjason@lowepower.com remove_reference_t<Set> set; 31212391Sjason@lowepower.com 31312391Sjason@lowepower.com pickle_factory(Get get, Set set) 31412391Sjason@lowepower.com : get(std::forward<Get>(get)), set(std::forward<Set>(set)) { } 31512391Sjason@lowepower.com 31612391Sjason@lowepower.com template <typename Class, typename... Extra> 31712391Sjason@lowepower.com void execute(Class &cl, const Extra &...extra) && { 31812391Sjason@lowepower.com cl.def("__getstate__", std::move(get)); 31912391Sjason@lowepower.com 32012391Sjason@lowepower.com#if defined(PYBIND11_CPP14) 32112391Sjason@lowepower.com cl.def("__setstate__", [func = std::move(set)] 32212391Sjason@lowepower.com#else 32312391Sjason@lowepower.com auto &func = set; 32412391Sjason@lowepower.com cl.def("__setstate__", [func] 32512391Sjason@lowepower.com#endif 32612391Sjason@lowepower.com (value_and_holder &v_h, ArgState state) { 32712391Sjason@lowepower.com setstate<Class>(v_h, func(std::forward<ArgState>(state)), 32812391Sjason@lowepower.com Py_TYPE(v_h.inst) != v_h.type->type); 32912391Sjason@lowepower.com }, is_new_style_constructor(), extra...); 33012391Sjason@lowepower.com } 33112391Sjason@lowepower.com}; 33212391Sjason@lowepower.com 33312391Sjason@lowepower.comNAMESPACE_END(initimpl) 33412391Sjason@lowepower.comNAMESPACE_END(detail) 33512391Sjason@lowepower.comNAMESPACE_END(pybind11) 336