Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /jana2/src/python/externals/pybind11-2.10.3/include/pybind11/detail/init.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002     pybind11/detail/init.h: init factory function implementation and support code.
0003 
0004     Copyright (c) 2017 Jason Rhinelander <jason@imaginary.ca>
0005 
0006     All rights reserved. Use of this source code is governed by a
0007     BSD-style license that can be found in the LICENSE file.
0008 */
0009 
0010 #pragma once
0011 
0012 #include "class.h"
0013 
0014 PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
0015 
0016 PYBIND11_WARNING_DISABLE_MSVC(4127)
0017 
0018 PYBIND11_NAMESPACE_BEGIN(detail)
0019 
0020 template <>
0021 class type_caster<value_and_holder> {
0022 public:
0023     bool load(handle h, bool) {
0024         value = reinterpret_cast<value_and_holder *>(h.ptr());
0025         return true;
0026     }
0027 
0028     template <typename>
0029     using cast_op_type = value_and_holder &;
0030     explicit operator value_and_holder &() { return *value; }
0031     static constexpr auto name = const_name<value_and_holder>();
0032 
0033 private:
0034     value_and_holder *value = nullptr;
0035 };
0036 
0037 PYBIND11_NAMESPACE_BEGIN(initimpl)
0038 
0039 inline void no_nullptr(void *ptr) {
0040     if (!ptr) {
0041         throw type_error("pybind11::init(): factory function returned nullptr");
0042     }
0043 }
0044 
0045 // Implementing functions for all forms of py::init<...> and py::init(...)
0046 template <typename Class>
0047 using Cpp = typename Class::type;
0048 template <typename Class>
0049 using Alias = typename Class::type_alias;
0050 template <typename Class>
0051 using Holder = typename Class::holder_type;
0052 
0053 template <typename Class>
0054 using is_alias_constructible = std::is_constructible<Alias<Class>, Cpp<Class> &&>;
0055 
0056 // Takes a Cpp pointer and returns true if it actually is a polymorphic Alias instance.
0057 template <typename Class, enable_if_t<Class::has_alias, int> = 0>
0058 bool is_alias(Cpp<Class> *ptr) {
0059     return dynamic_cast<Alias<Class> *>(ptr) != nullptr;
0060 }
0061 // Failing fallback version of the above for a no-alias class (always returns false)
0062 template <typename /*Class*/>
0063 constexpr bool is_alias(void *) {
0064     return false;
0065 }
0066 
0067 // Constructs and returns a new object; if the given arguments don't map to a constructor, we fall
0068 // back to brace aggregate initiailization so that for aggregate initialization can be used with
0069 // py::init, e.g.  `py::init<int, int>` to initialize a `struct T { int a; int b; }`.  For
0070 // non-aggregate types, we need to use an ordinary T(...) constructor (invoking as `T{...}` usually
0071 // works, but will not do the expected thing when `T` has an `initializer_list<T>` constructor).
0072 template <typename Class,
0073           typename... Args,
0074           detail::enable_if_t<std::is_constructible<Class, Args...>::value, int> = 0>
0075 inline Class *construct_or_initialize(Args &&...args) {
0076     return new Class(std::forward<Args>(args)...);
0077 }
0078 template <typename Class,
0079           typename... Args,
0080           detail::enable_if_t<!std::is_constructible<Class, Args...>::value, int> = 0>
0081 inline Class *construct_or_initialize(Args &&...args) {
0082     return new Class{std::forward<Args>(args)...};
0083 }
0084 
0085 // Attempts to constructs an alias using a `Alias(Cpp &&)` constructor.  This allows types with
0086 // an alias to provide only a single Cpp factory function as long as the Alias can be
0087 // constructed from an rvalue reference of the base Cpp type.  This means that Alias classes
0088 // can, when appropriate, simply define a `Alias(Cpp &&)` constructor rather than needing to
0089 // inherit all the base class constructors.
0090 template <typename Class>
0091 void construct_alias_from_cpp(std::true_type /*is_alias_constructible*/,
0092                               value_and_holder &v_h,
0093                               Cpp<Class> &&base) {
0094     v_h.value_ptr() = new Alias<Class>(std::move(base));
0095 }
0096 template <typename Class>
0097 [[noreturn]] void construct_alias_from_cpp(std::false_type /*!is_alias_constructible*/,
0098                                            value_and_holder &,
0099                                            Cpp<Class> &&) {
0100     throw type_error("pybind11::init(): unable to convert returned instance to required "
0101                      "alias class: no `Alias<Class>(Class &&)` constructor available");
0102 }
0103 
0104 // Error-generating fallback for factories that don't match one of the below construction
0105 // mechanisms.
0106 template <typename Class>
0107 void construct(...) {
0108     static_assert(!std::is_same<Class, Class>::value /* always false */,
0109                   "pybind11::init(): init function must return a compatible pointer, "
0110                   "holder, or value");
0111 }
0112 
0113 // Pointer return v1: the factory function returns a class pointer for a registered class.
0114 // If we don't need an alias (because this class doesn't have one, or because the final type is
0115 // inherited on the Python side) we can simply take over ownership.  Otherwise we need to try to
0116 // construct an Alias from the returned base instance.
0117 template <typename Class>
0118 void construct(value_and_holder &v_h, Cpp<Class> *ptr, bool need_alias) {
0119     PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(need_alias);
0120     no_nullptr(ptr);
0121     if (Class::has_alias && need_alias && !is_alias<Class>(ptr)) {
0122         // We're going to try to construct an alias by moving the cpp type.  Whether or not
0123         // that succeeds, we still need to destroy the original cpp pointer (either the
0124         // moved away leftover, if the alias construction works, or the value itself if we
0125         // throw an error), but we can't just call `delete ptr`: it might have a special
0126         // deleter, or might be shared_from_this.  So we construct a holder around it as if
0127         // it was a normal instance, then steal the holder away into a local variable; thus
0128         // the holder and destruction happens when we leave the C++ scope, and the holder
0129         // class gets to handle the destruction however it likes.
0130         v_h.value_ptr() = ptr;
0131         v_h.set_instance_registered(true);          // To prevent init_instance from registering it
0132         v_h.type->init_instance(v_h.inst, nullptr); // Set up the holder
0133         Holder<Class> temp_holder(std::move(v_h.holder<Holder<Class>>())); // Steal the holder
0134         v_h.type->dealloc(v_h); // Destroys the moved-out holder remains, resets value ptr to null
0135         v_h.set_instance_registered(false);
0136 
0137         construct_alias_from_cpp<Class>(is_alias_constructible<Class>{}, v_h, std::move(*ptr));
0138     } else {
0139         // Otherwise the type isn't inherited, so we don't need an Alias
0140         v_h.value_ptr() = ptr;
0141     }
0142 }
0143 
0144 // Pointer return v2: a factory that always returns an alias instance ptr.  We simply take over
0145 // ownership of the pointer.
0146 template <typename Class, enable_if_t<Class::has_alias, int> = 0>
0147 void construct(value_and_holder &v_h, Alias<Class> *alias_ptr, bool) {
0148     no_nullptr(alias_ptr);
0149     v_h.value_ptr() = static_cast<Cpp<Class> *>(alias_ptr);
0150 }
0151 
0152 // Holder return: copy its pointer, and move or copy the returned holder into the new instance's
0153 // holder.  This also handles types like std::shared_ptr<T> and std::unique_ptr<T> where T is a
0154 // derived type (through those holder's implicit conversion from derived class holder
0155 // constructors).
0156 template <typename Class>
0157 void construct(value_and_holder &v_h, Holder<Class> holder, bool need_alias) {
0158     PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(need_alias);
0159     auto *ptr = holder_helper<Holder<Class>>::get(holder);
0160     no_nullptr(ptr);
0161     // If we need an alias, check that the held pointer is actually an alias instance
0162     if (Class::has_alias && need_alias && !is_alias<Class>(ptr)) {
0163         throw type_error("pybind11::init(): construction failed: returned holder-wrapped instance "
0164                          "is not an alias instance");
0165     }
0166 
0167     v_h.value_ptr() = ptr;
0168     v_h.type->init_instance(v_h.inst, &holder);
0169 }
0170 
0171 // return-by-value version 1: returning a cpp class by value.  If the class has an alias and an
0172 // alias is required the alias must have an `Alias(Cpp &&)` constructor so that we can construct
0173 // the alias from the base when needed (i.e. because of Python-side inheritance).  When we don't
0174 // need it, we simply move-construct the cpp value into a new instance.
0175 template <typename Class>
0176 void construct(value_and_holder &v_h, Cpp<Class> &&result, bool need_alias) {
0177     PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(need_alias);
0178     static_assert(std::is_move_constructible<Cpp<Class>>::value,
0179                   "pybind11::init() return-by-value factory function requires a movable class");
0180     if (Class::has_alias && need_alias) {
0181         construct_alias_from_cpp<Class>(is_alias_constructible<Class>{}, v_h, std::move(result));
0182     } else {
0183         v_h.value_ptr() = new Cpp<Class>(std::move(result));
0184     }
0185 }
0186 
0187 // return-by-value version 2: returning a value of the alias type itself.  We move-construct an
0188 // Alias instance (even if no the python-side inheritance is involved).  The is intended for
0189 // cases where Alias initialization is always desired.
0190 template <typename Class>
0191 void construct(value_and_holder &v_h, Alias<Class> &&result, bool) {
0192     static_assert(
0193         std::is_move_constructible<Alias<Class>>::value,
0194         "pybind11::init() return-by-alias-value factory function requires a movable alias class");
0195     v_h.value_ptr() = new Alias<Class>(std::move(result));
0196 }
0197 
0198 // Implementing class for py::init<...>()
0199 template <typename... Args>
0200 struct constructor {
0201     template <typename Class, typename... Extra, enable_if_t<!Class::has_alias, int> = 0>
0202     static void execute(Class &cl, const Extra &...extra) {
0203         cl.def(
0204             "__init__",
0205             [](value_and_holder &v_h, Args... args) {
0206                 v_h.value_ptr() = construct_or_initialize<Cpp<Class>>(std::forward<Args>(args)...);
0207             },
0208             is_new_style_constructor(),
0209             extra...);
0210     }
0211 
0212     template <
0213         typename Class,
0214         typename... Extra,
0215         enable_if_t<Class::has_alias && std::is_constructible<Cpp<Class>, Args...>::value, int>
0216         = 0>
0217     static void execute(Class &cl, const Extra &...extra) {
0218         cl.def(
0219             "__init__",
0220             [](value_and_holder &v_h, Args... args) {
0221                 if (Py_TYPE(v_h.inst) == v_h.type->type) {
0222                     v_h.value_ptr()
0223                         = construct_or_initialize<Cpp<Class>>(std::forward<Args>(args)...);
0224                 } else {
0225                     v_h.value_ptr()
0226                         = construct_or_initialize<Alias<Class>>(std::forward<Args>(args)...);
0227                 }
0228             },
0229             is_new_style_constructor(),
0230             extra...);
0231     }
0232 
0233     template <
0234         typename Class,
0235         typename... Extra,
0236         enable_if_t<Class::has_alias && !std::is_constructible<Cpp<Class>, Args...>::value, int>
0237         = 0>
0238     static void execute(Class &cl, const Extra &...extra) {
0239         cl.def(
0240             "__init__",
0241             [](value_and_holder &v_h, Args... args) {
0242                 v_h.value_ptr()
0243                     = construct_or_initialize<Alias<Class>>(std::forward<Args>(args)...);
0244             },
0245             is_new_style_constructor(),
0246             extra...);
0247     }
0248 };
0249 
0250 // Implementing class for py::init_alias<...>()
0251 template <typename... Args>
0252 struct alias_constructor {
0253     template <
0254         typename Class,
0255         typename... Extra,
0256         enable_if_t<Class::has_alias && std::is_constructible<Alias<Class>, Args...>::value, int>
0257         = 0>
0258     static void execute(Class &cl, const Extra &...extra) {
0259         cl.def(
0260             "__init__",
0261             [](value_and_holder &v_h, Args... args) {
0262                 v_h.value_ptr()
0263                     = construct_or_initialize<Alias<Class>>(std::forward<Args>(args)...);
0264             },
0265             is_new_style_constructor(),
0266             extra...);
0267     }
0268 };
0269 
0270 // Implementation class for py::init(Func) and py::init(Func, AliasFunc)
0271 template <typename CFunc,
0272           typename AFunc = void_type (*)(),
0273           typename = function_signature_t<CFunc>,
0274           typename = function_signature_t<AFunc>>
0275 struct factory;
0276 
0277 // Specialization for py::init(Func)
0278 template <typename Func, typename Return, typename... Args>
0279 struct factory<Func, void_type (*)(), Return(Args...)> {
0280     remove_reference_t<Func> class_factory;
0281 
0282     // NOLINTNEXTLINE(google-explicit-constructor)
0283     factory(Func &&f) : class_factory(std::forward<Func>(f)) {}
0284 
0285     // The given class either has no alias or has no separate alias factory;
0286     // this always constructs the class itself.  If the class is registered with an alias
0287     // type and an alias instance is needed (i.e. because the final type is a Python class
0288     // inheriting from the C++ type) the returned value needs to either already be an alias
0289     // instance, or the alias needs to be constructible from a `Class &&` argument.
0290     template <typename Class, typename... Extra>
0291     void execute(Class &cl, const Extra &...extra) && {
0292 #if defined(PYBIND11_CPP14)
0293         cl.def(
0294             "__init__",
0295             [func = std::move(class_factory)]
0296 #else
0297         auto &func = class_factory;
0298         cl.def(
0299             "__init__",
0300             [func]
0301 #endif
0302             (value_and_holder &v_h, Args... args) {
0303                 construct<Class>(
0304                     v_h, func(std::forward<Args>(args)...), Py_TYPE(v_h.inst) != v_h.type->type);
0305             },
0306             is_new_style_constructor(),
0307             extra...);
0308     }
0309 };
0310 
0311 // Specialization for py::init(Func, AliasFunc)
0312 template <typename CFunc,
0313           typename AFunc,
0314           typename CReturn,
0315           typename... CArgs,
0316           typename AReturn,
0317           typename... AArgs>
0318 struct factory<CFunc, AFunc, CReturn(CArgs...), AReturn(AArgs...)> {
0319     static_assert(sizeof...(CArgs) == sizeof...(AArgs),
0320                   "pybind11::init(class_factory, alias_factory): class and alias factories "
0321                   "must have identical argument signatures");
0322     static_assert(all_of<std::is_same<CArgs, AArgs>...>::value,
0323                   "pybind11::init(class_factory, alias_factory): class and alias factories "
0324                   "must have identical argument signatures");
0325 
0326     remove_reference_t<CFunc> class_factory;
0327     remove_reference_t<AFunc> alias_factory;
0328 
0329     factory(CFunc &&c, AFunc &&a)
0330         : class_factory(std::forward<CFunc>(c)), alias_factory(std::forward<AFunc>(a)) {}
0331 
0332     // The class factory is called when the `self` type passed to `__init__` is the direct
0333     // class (i.e. not inherited), the alias factory when `self` is a Python-side subtype.
0334     template <typename Class, typename... Extra>
0335     void execute(Class &cl, const Extra &...extra) && {
0336         static_assert(Class::has_alias,
0337                       "The two-argument version of `py::init()` can "
0338                       "only be used if the class has an alias");
0339 #if defined(PYBIND11_CPP14)
0340         cl.def(
0341             "__init__",
0342             [class_func = std::move(class_factory), alias_func = std::move(alias_factory)]
0343 #else
0344         auto &class_func = class_factory;
0345         auto &alias_func = alias_factory;
0346         cl.def(
0347             "__init__",
0348             [class_func, alias_func]
0349 #endif
0350             (value_and_holder &v_h, CArgs... args) {
0351                 if (Py_TYPE(v_h.inst) == v_h.type->type) {
0352                     // If the instance type equals the registered type we don't have inheritance,
0353                     // so don't need the alias and can construct using the class function:
0354                     construct<Class>(v_h, class_func(std::forward<CArgs>(args)...), false);
0355                 } else {
0356                     construct<Class>(v_h, alias_func(std::forward<CArgs>(args)...), true);
0357                 }
0358             },
0359             is_new_style_constructor(),
0360             extra...);
0361     }
0362 };
0363 
0364 /// Set just the C++ state. Same as `__init__`.
0365 template <typename Class, typename T>
0366 void setstate(value_and_holder &v_h, T &&result, bool need_alias) {
0367     construct<Class>(v_h, std::forward<T>(result), need_alias);
0368 }
0369 
0370 /// Set both the C++ and Python states
0371 template <typename Class,
0372           typename T,
0373           typename O,
0374           enable_if_t<std::is_convertible<O, handle>::value, int> = 0>
0375 void setstate(value_and_holder &v_h, std::pair<T, O> &&result, bool need_alias) {
0376     construct<Class>(v_h, std::move(result.first), need_alias);
0377     auto d = handle(result.second);
0378     if (PyDict_Check(d.ptr()) && PyDict_Size(d.ptr()) == 0) {
0379         // Skipping setattr below, to not force use of py::dynamic_attr() for Class unnecessarily.
0380         // See PR #2972 for details.
0381         return;
0382     }
0383     setattr((PyObject *) v_h.inst, "__dict__", d);
0384 }
0385 
0386 /// Implementation for py::pickle(GetState, SetState)
0387 template <typename Get,
0388           typename Set,
0389           typename = function_signature_t<Get>,
0390           typename = function_signature_t<Set>>
0391 struct pickle_factory;
0392 
0393 template <typename Get,
0394           typename Set,
0395           typename RetState,
0396           typename Self,
0397           typename NewInstance,
0398           typename ArgState>
0399 struct pickle_factory<Get, Set, RetState(Self), NewInstance(ArgState)> {
0400     static_assert(std::is_same<intrinsic_t<RetState>, intrinsic_t<ArgState>>::value,
0401                   "The type returned by `__getstate__` must be the same "
0402                   "as the argument accepted by `__setstate__`");
0403 
0404     remove_reference_t<Get> get;
0405     remove_reference_t<Set> set;
0406 
0407     pickle_factory(Get get, Set set) : get(std::forward<Get>(get)), set(std::forward<Set>(set)) {}
0408 
0409     template <typename Class, typename... Extra>
0410     void execute(Class &cl, const Extra &...extra) && {
0411         cl.def("__getstate__", std::move(get));
0412 
0413 #if defined(PYBIND11_CPP14)
0414         cl.def(
0415             "__setstate__",
0416             [func = std::move(set)]
0417 #else
0418         auto &func = set;
0419         cl.def(
0420             "__setstate__",
0421             [func]
0422 #endif
0423             (value_and_holder &v_h, ArgState state) {
0424                 setstate<Class>(
0425                     v_h, func(std::forward<ArgState>(state)), Py_TYPE(v_h.inst) != v_h.type->type);
0426             },
0427             is_new_style_constructor(),
0428             extra...);
0429     }
0430 };
0431 
0432 PYBIND11_NAMESPACE_END(initimpl)
0433 PYBIND11_NAMESPACE_END(detail)
0434 PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)