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
0003
0004
0005
0006
0007
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
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
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
0062 template <typename >
0063 constexpr bool is_alias(void *) {
0064 return false;
0065 }
0066
0067
0068
0069
0070
0071
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
0086
0087
0088
0089
0090 template <typename Class>
0091 void construct_alias_from_cpp(std::true_type ,
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 ,
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
0105
0106 template <typename Class>
0107 void construct(...) {
0108 static_assert(!std::is_same<Class, Class>::value ,
0109 "pybind11::init(): init function must return a compatible pointer, "
0110 "holder, or value");
0111 }
0112
0113
0114
0115
0116
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
0123
0124
0125
0126
0127
0128
0129
0130 v_h.value_ptr() = ptr;
0131 v_h.set_instance_registered(true);
0132 v_h.type->init_instance(v_h.inst, nullptr);
0133 Holder<Class> temp_holder(std::move(v_h.holder<Holder<Class>>()));
0134 v_h.type->dealloc(v_h);
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
0140 v_h.value_ptr() = ptr;
0141 }
0142 }
0143
0144
0145
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
0153
0154
0155
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
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
0172
0173
0174
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
0188
0189
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
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
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
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
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
0283 factory(Func &&f) : class_factory(std::forward<Func>(f)) {}
0284
0285
0286
0287
0288
0289
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
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
0333
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
0353
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
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
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
0380
0381 return;
0382 }
0383 setattr((PyObject *) v_h.inst, "__dict__", d);
0384 }
0385
0386
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)