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