Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:06:17

0001 /*
0002     pybind11/stl.h: Transparent conversion for STL data types
0003 
0004     Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
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 "pybind11.h"
0013 #include "detail/common.h"
0014 
0015 #include <deque>
0016 #include <list>
0017 #include <map>
0018 #include <ostream>
0019 #include <set>
0020 #include <unordered_map>
0021 #include <unordered_set>
0022 #include <valarray>
0023 
0024 // See `detail/common.h` for implementation of these guards.
0025 #if defined(PYBIND11_HAS_OPTIONAL)
0026 #    include <optional>
0027 #elif defined(PYBIND11_HAS_EXP_OPTIONAL)
0028 #    include <experimental/optional>
0029 #endif
0030 
0031 #if defined(PYBIND11_HAS_VARIANT)
0032 #    include <variant>
0033 #endif
0034 
0035 PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
0036 PYBIND11_NAMESPACE_BEGIN(detail)
0037 
0038 /// Extracts an const lvalue reference or rvalue reference for U based on the type of T (e.g. for
0039 /// forwarding a container element).  Typically used indirect via forwarded_type(), below.
0040 template <typename T, typename U>
0041 using forwarded_type = conditional_t<std::is_lvalue_reference<T>::value,
0042                                      remove_reference_t<U> &,
0043                                      remove_reference_t<U> &&>;
0044 
0045 /// Forwards a value U as rvalue or lvalue according to whether T is rvalue or lvalue; typically
0046 /// used for forwarding a container's elements.
0047 template <typename T, typename U>
0048 constexpr forwarded_type<T, U> forward_like(U &&u) {
0049     return std::forward<detail::forwarded_type<T, U>>(std::forward<U>(u));
0050 }
0051 
0052 // Checks if a container has a STL style reserve method.
0053 // This will only return true for a `reserve()` with a `void` return.
0054 template <typename C>
0055 using has_reserve_method = std::is_same<decltype(std::declval<C>().reserve(0)), void>;
0056 
0057 template <typename Type, typename Key>
0058 struct set_caster {
0059     using type = Type;
0060     using key_conv = make_caster<Key>;
0061 
0062 private:
0063     template <typename T = Type, enable_if_t<has_reserve_method<T>::value, int> = 0>
0064     void reserve_maybe(const anyset &s, Type *) {
0065         value.reserve(s.size());
0066     }
0067     void reserve_maybe(const anyset &, void *) {}
0068 
0069 public:
0070     bool load(handle src, bool convert) {
0071         if (!isinstance<anyset>(src)) {
0072             return false;
0073         }
0074         auto s = reinterpret_borrow<anyset>(src);
0075         value.clear();
0076         reserve_maybe(s, &value);
0077         for (auto entry : s) {
0078             key_conv conv;
0079             if (!conv.load(entry, convert)) {
0080                 return false;
0081             }
0082             value.insert(cast_op<Key &&>(std::move(conv)));
0083         }
0084         return true;
0085     }
0086 
0087     template <typename T>
0088     static handle cast(T &&src, return_value_policy policy, handle parent) {
0089         if (!std::is_lvalue_reference<T>::value) {
0090             policy = return_value_policy_override<Key>::policy(policy);
0091         }
0092         pybind11::set s;
0093         for (auto &&value : src) {
0094             auto value_ = reinterpret_steal<object>(
0095                 key_conv::cast(detail::forward_like<T>(value), policy, parent));
0096             if (!value_ || !s.add(std::move(value_))) {
0097                 return handle();
0098             }
0099         }
0100         return s.release();
0101     }
0102 
0103     PYBIND11_TYPE_CASTER(type, const_name("set[") + key_conv::name + const_name("]"));
0104 };
0105 
0106 template <typename Type, typename Key, typename Value>
0107 struct map_caster {
0108     using key_conv = make_caster<Key>;
0109     using value_conv = make_caster<Value>;
0110 
0111 private:
0112     template <typename T = Type, enable_if_t<has_reserve_method<T>::value, int> = 0>
0113     void reserve_maybe(const dict &d, Type *) {
0114         value.reserve(d.size());
0115     }
0116     void reserve_maybe(const dict &, void *) {}
0117 
0118 public:
0119     bool load(handle src, bool convert) {
0120         if (!isinstance<dict>(src)) {
0121             return false;
0122         }
0123         auto d = reinterpret_borrow<dict>(src);
0124         value.clear();
0125         reserve_maybe(d, &value);
0126         for (auto it : d) {
0127             key_conv kconv;
0128             value_conv vconv;
0129             if (!kconv.load(it.first.ptr(), convert) || !vconv.load(it.second.ptr(), convert)) {
0130                 return false;
0131             }
0132             value.emplace(cast_op<Key &&>(std::move(kconv)), cast_op<Value &&>(std::move(vconv)));
0133         }
0134         return true;
0135     }
0136 
0137     template <typename T>
0138     static handle cast(T &&src, return_value_policy policy, handle parent) {
0139         dict d;
0140         return_value_policy policy_key = policy;
0141         return_value_policy policy_value = policy;
0142         if (!std::is_lvalue_reference<T>::value) {
0143             policy_key = return_value_policy_override<Key>::policy(policy_key);
0144             policy_value = return_value_policy_override<Value>::policy(policy_value);
0145         }
0146         for (auto &&kv : src) {
0147             auto key = reinterpret_steal<object>(
0148                 key_conv::cast(detail::forward_like<T>(kv.first), policy_key, parent));
0149             auto value = reinterpret_steal<object>(
0150                 value_conv::cast(detail::forward_like<T>(kv.second), policy_value, parent));
0151             if (!key || !value) {
0152                 return handle();
0153             }
0154             d[std::move(key)] = std::move(value);
0155         }
0156         return d.release();
0157     }
0158 
0159     PYBIND11_TYPE_CASTER(Type,
0160                          const_name("dict[") + key_conv::name + const_name(", ") + value_conv::name
0161                              + const_name("]"));
0162 };
0163 
0164 template <typename Type, typename Value>
0165 struct list_caster {
0166     using value_conv = make_caster<Value>;
0167 
0168     bool load(handle src, bool convert) {
0169         if (!isinstance<sequence>(src) || isinstance<bytes>(src) || isinstance<str>(src)) {
0170             return false;
0171         }
0172         auto s = reinterpret_borrow<sequence>(src);
0173         value.clear();
0174         reserve_maybe(s, &value);
0175         for (const auto &it : s) {
0176             value_conv conv;
0177             if (!conv.load(it, convert)) {
0178                 return false;
0179             }
0180             value.push_back(cast_op<Value &&>(std::move(conv)));
0181         }
0182         return true;
0183     }
0184 
0185 private:
0186     template <typename T = Type, enable_if_t<has_reserve_method<T>::value, int> = 0>
0187     void reserve_maybe(const sequence &s, Type *) {
0188         value.reserve(s.size());
0189     }
0190     void reserve_maybe(const sequence &, void *) {}
0191 
0192 public:
0193     template <typename T>
0194     static handle cast(T &&src, return_value_policy policy, handle parent) {
0195         if (!std::is_lvalue_reference<T>::value) {
0196             policy = return_value_policy_override<Value>::policy(policy);
0197         }
0198         list l(src.size());
0199         ssize_t index = 0;
0200         for (auto &&value : src) {
0201             auto value_ = reinterpret_steal<object>(
0202                 value_conv::cast(detail::forward_like<T>(value), policy, parent));
0203             if (!value_) {
0204                 return handle();
0205             }
0206             PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference
0207         }
0208         return l.release();
0209     }
0210 
0211     PYBIND11_TYPE_CASTER(Type, const_name("list[") + value_conv::name + const_name("]"));
0212 };
0213 
0214 template <typename Type, typename Alloc>
0215 struct type_caster<std::vector<Type, Alloc>> : list_caster<std::vector<Type, Alloc>, Type> {};
0216 
0217 template <typename Type, typename Alloc>
0218 struct type_caster<std::deque<Type, Alloc>> : list_caster<std::deque<Type, Alloc>, Type> {};
0219 
0220 template <typename Type, typename Alloc>
0221 struct type_caster<std::list<Type, Alloc>> : list_caster<std::list<Type, Alloc>, Type> {};
0222 
0223 template <typename ArrayType, typename Value, bool Resizable, size_t Size = 0>
0224 struct array_caster {
0225     using value_conv = make_caster<Value>;
0226 
0227 private:
0228     template <bool R = Resizable>
0229     bool require_size(enable_if_t<R, size_t> size) {
0230         if (value.size() != size) {
0231             value.resize(size);
0232         }
0233         return true;
0234     }
0235     template <bool R = Resizable>
0236     bool require_size(enable_if_t<!R, size_t> size) {
0237         return size == Size;
0238     }
0239 
0240 public:
0241     bool load(handle src, bool convert) {
0242         if (!isinstance<sequence>(src)) {
0243             return false;
0244         }
0245         auto l = reinterpret_borrow<sequence>(src);
0246         if (!require_size(l.size())) {
0247             return false;
0248         }
0249         size_t ctr = 0;
0250         for (const auto &it : l) {
0251             value_conv conv;
0252             if (!conv.load(it, convert)) {
0253                 return false;
0254             }
0255             value[ctr++] = cast_op<Value &&>(std::move(conv));
0256         }
0257         return true;
0258     }
0259 
0260     template <typename T>
0261     static handle cast(T &&src, return_value_policy policy, handle parent) {
0262         list l(src.size());
0263         ssize_t index = 0;
0264         for (auto &&value : src) {
0265             auto value_ = reinterpret_steal<object>(
0266                 value_conv::cast(detail::forward_like<T>(value), policy, parent));
0267             if (!value_) {
0268                 return handle();
0269             }
0270             PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference
0271         }
0272         return l.release();
0273     }
0274 
0275     PYBIND11_TYPE_CASTER(ArrayType,
0276                          const_name<Resizable>(const_name(""), const_name("Annotated["))
0277                              + const_name("list[") + value_conv::name + const_name("]")
0278                              + const_name<Resizable>(const_name(""),
0279                                                      const_name(", FixedSize(")
0280                                                          + const_name<Size>() + const_name(")]")));
0281 };
0282 
0283 template <typename Type, size_t Size>
0284 struct type_caster<std::array<Type, Size>>
0285     : array_caster<std::array<Type, Size>, Type, false, Size> {};
0286 
0287 template <typename Type>
0288 struct type_caster<std::valarray<Type>> : array_caster<std::valarray<Type>, Type, true> {};
0289 
0290 template <typename Key, typename Compare, typename Alloc>
0291 struct type_caster<std::set<Key, Compare, Alloc>>
0292     : set_caster<std::set<Key, Compare, Alloc>, Key> {};
0293 
0294 template <typename Key, typename Hash, typename Equal, typename Alloc>
0295 struct type_caster<std::unordered_set<Key, Hash, Equal, Alloc>>
0296     : set_caster<std::unordered_set<Key, Hash, Equal, Alloc>, Key> {};
0297 
0298 template <typename Key, typename Value, typename Compare, typename Alloc>
0299 struct type_caster<std::map<Key, Value, Compare, Alloc>>
0300     : map_caster<std::map<Key, Value, Compare, Alloc>, Key, Value> {};
0301 
0302 template <typename Key, typename Value, typename Hash, typename Equal, typename Alloc>
0303 struct type_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>>
0304     : map_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>, Key, Value> {};
0305 
0306 // This type caster is intended to be used for std::optional and std::experimental::optional
0307 template <typename Type, typename Value = typename Type::value_type>
0308 struct optional_caster {
0309     using value_conv = make_caster<Value>;
0310 
0311     template <typename T>
0312     static handle cast(T &&src, return_value_policy policy, handle parent) {
0313         if (!src) {
0314             return none().release();
0315         }
0316         if (!std::is_lvalue_reference<T>::value) {
0317             policy = return_value_policy_override<Value>::policy(policy);
0318         }
0319         // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
0320         return value_conv::cast(*std::forward<T>(src), policy, parent);
0321     }
0322 
0323     bool load(handle src, bool convert) {
0324         if (!src) {
0325             return false;
0326         }
0327         if (src.is_none()) {
0328             return true; // default-constructed value is already empty
0329         }
0330         value_conv inner_caster;
0331         if (!inner_caster.load(src, convert)) {
0332             return false;
0333         }
0334 
0335         value.emplace(cast_op<Value &&>(std::move(inner_caster)));
0336         return true;
0337     }
0338 
0339     PYBIND11_TYPE_CASTER(Type, const_name("Optional[") + value_conv::name + const_name("]"));
0340 };
0341 
0342 #if defined(PYBIND11_HAS_OPTIONAL)
0343 template <typename T>
0344 struct type_caster<std::optional<T>> : public optional_caster<std::optional<T>> {};
0345 
0346 template <>
0347 struct type_caster<std::nullopt_t> : public void_caster<std::nullopt_t> {};
0348 #endif
0349 
0350 #if defined(PYBIND11_HAS_EXP_OPTIONAL)
0351 template <typename T>
0352 struct type_caster<std::experimental::optional<T>>
0353     : public optional_caster<std::experimental::optional<T>> {};
0354 
0355 template <>
0356 struct type_caster<std::experimental::nullopt_t>
0357     : public void_caster<std::experimental::nullopt_t> {};
0358 #endif
0359 
0360 /// Visit a variant and cast any found type to Python
0361 struct variant_caster_visitor {
0362     return_value_policy policy;
0363     handle parent;
0364 
0365     using result_type = handle; // required by boost::variant in C++11
0366 
0367     template <typename T>
0368     result_type operator()(T &&src) const {
0369         return make_caster<T>::cast(std::forward<T>(src), policy, parent);
0370     }
0371 };
0372 
0373 /// Helper class which abstracts away variant's `visit` function. `std::variant` and similar
0374 /// `namespace::variant` types which provide a `namespace::visit()` function are handled here
0375 /// automatically using argument-dependent lookup. Users can provide specializations for other
0376 /// variant-like classes, e.g. `boost::variant` and `boost::apply_visitor`.
0377 template <template <typename...> class Variant>
0378 struct visit_helper {
0379     template <typename... Args>
0380     static auto call(Args &&...args) -> decltype(visit(std::forward<Args>(args)...)) {
0381         return visit(std::forward<Args>(args)...);
0382     }
0383 };
0384 
0385 /// Generic variant caster
0386 template <typename Variant>
0387 struct variant_caster;
0388 
0389 template <template <typename...> class V, typename... Ts>
0390 struct variant_caster<V<Ts...>> {
0391     static_assert(sizeof...(Ts) > 0, "Variant must consist of at least one alternative.");
0392 
0393     template <typename U, typename... Us>
0394     bool load_alternative(handle src, bool convert, type_list<U, Us...>) {
0395         auto caster = make_caster<U>();
0396         if (caster.load(src, convert)) {
0397             value = cast_op<U>(std::move(caster));
0398             return true;
0399         }
0400         return load_alternative(src, convert, type_list<Us...>{});
0401     }
0402 
0403     bool load_alternative(handle, bool, type_list<>) { return false; }
0404 
0405     bool load(handle src, bool convert) {
0406         // Do a first pass without conversions to improve constructor resolution.
0407         // E.g. `py::int_(1).cast<variant<double, int>>()` needs to fill the `int`
0408         // slot of the variant. Without two-pass loading `double` would be filled
0409         // because it appears first and a conversion is possible.
0410         if (convert && load_alternative(src, false, type_list<Ts...>{})) {
0411             return true;
0412         }
0413         return load_alternative(src, convert, type_list<Ts...>{});
0414     }
0415 
0416     template <typename Variant>
0417     static handle cast(Variant &&src, return_value_policy policy, handle parent) {
0418         return visit_helper<V>::call(variant_caster_visitor{policy, parent},
0419                                      std::forward<Variant>(src));
0420     }
0421 
0422     using Type = V<Ts...>;
0423     PYBIND11_TYPE_CASTER(Type,
0424                          const_name("Union[")
0425                              + ::pybind11::detail::concat(make_caster<Ts>::name...)
0426                              + const_name("]"));
0427 };
0428 
0429 #if defined(PYBIND11_HAS_VARIANT)
0430 template <typename... Ts>
0431 struct type_caster<std::variant<Ts...>> : variant_caster<std::variant<Ts...>> {};
0432 
0433 template <>
0434 struct type_caster<std::monostate> : public void_caster<std::monostate> {};
0435 #endif
0436 
0437 PYBIND11_NAMESPACE_END(detail)
0438 
0439 inline std::ostream &operator<<(std::ostream &os, const handle &obj) {
0440 #ifdef PYBIND11_HAS_STRING_VIEW
0441     os << str(obj).cast<std::string_view>();
0442 #else
0443     os << (std::string) str(obj);
0444 #endif
0445     return os;
0446 }
0447 
0448 PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)