Back to home page

EIC code displayed by LXR

 
 

    


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

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 (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 (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("List[") + value_conv::name
0277                              + const_name<Resizable>(const_name(""),
0278                                                      const_name("[") + const_name<Size>()
0279                                                          + const_name("]"))
0280                              + 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         return value_conv::cast(*std::forward<T>(src), policy, parent);
0320     }
0321 
0322     bool load(handle src, bool convert) {
0323         if (!src) {
0324             return false;
0325         }
0326         if (src.is_none()) {
0327             return true; // default-constructed value is already empty
0328         }
0329         value_conv inner_caster;
0330         if (!inner_caster.load(src, convert)) {
0331             return false;
0332         }
0333 
0334         value.emplace(cast_op<Value &&>(std::move(inner_caster)));
0335         return true;
0336     }
0337 
0338     PYBIND11_TYPE_CASTER(Type, const_name("Optional[") + value_conv::name + const_name("]"));
0339 };
0340 
0341 #if defined(PYBIND11_HAS_OPTIONAL)
0342 template <typename T>
0343 struct type_caster<std::optional<T>> : public optional_caster<std::optional<T>> {};
0344 
0345 template <>
0346 struct type_caster<std::nullopt_t> : public void_caster<std::nullopt_t> {};
0347 #endif
0348 
0349 #if defined(PYBIND11_HAS_EXP_OPTIONAL)
0350 template <typename T>
0351 struct type_caster<std::experimental::optional<T>>
0352     : public optional_caster<std::experimental::optional<T>> {};
0353 
0354 template <>
0355 struct type_caster<std::experimental::nullopt_t>
0356     : public void_caster<std::experimental::nullopt_t> {};
0357 #endif
0358 
0359 /// Visit a variant and cast any found type to Python
0360 struct variant_caster_visitor {
0361     return_value_policy policy;
0362     handle parent;
0363 
0364     using result_type = handle; // required by boost::variant in C++11
0365 
0366     template <typename T>
0367     result_type operator()(T &&src) const {
0368         return make_caster<T>::cast(std::forward<T>(src), policy, parent);
0369     }
0370 };
0371 
0372 /// Helper class which abstracts away variant's `visit` function. `std::variant` and similar
0373 /// `namespace::variant` types which provide a `namespace::visit()` function are handled here
0374 /// automatically using argument-dependent lookup. Users can provide specializations for other
0375 /// variant-like classes, e.g. `boost::variant` and `boost::apply_visitor`.
0376 template <template <typename...> class Variant>
0377 struct visit_helper {
0378     template <typename... Args>
0379     static auto call(Args &&...args) -> decltype(visit(std::forward<Args>(args)...)) {
0380         return visit(std::forward<Args>(args)...);
0381     }
0382 };
0383 
0384 /// Generic variant caster
0385 template <typename Variant>
0386 struct variant_caster;
0387 
0388 template <template <typename...> class V, typename... Ts>
0389 struct variant_caster<V<Ts...>> {
0390     static_assert(sizeof...(Ts) > 0, "Variant must consist of at least one alternative.");
0391 
0392     template <typename U, typename... Us>
0393     bool load_alternative(handle src, bool convert, type_list<U, Us...>) {
0394         auto caster = make_caster<U>();
0395         if (caster.load(src, convert)) {
0396             value = cast_op<U>(std::move(caster));
0397             return true;
0398         }
0399         return load_alternative(src, convert, type_list<Us...>{});
0400     }
0401 
0402     bool load_alternative(handle, bool, type_list<>) { return false; }
0403 
0404     bool load(handle src, bool convert) {
0405         // Do a first pass without conversions to improve constructor resolution.
0406         // E.g. `py::int_(1).cast<variant<double, int>>()` needs to fill the `int`
0407         // slot of the variant. Without two-pass loading `double` would be filled
0408         // because it appears first and a conversion is possible.
0409         if (convert && load_alternative(src, false, type_list<Ts...>{})) {
0410             return true;
0411         }
0412         return load_alternative(src, convert, type_list<Ts...>{});
0413     }
0414 
0415     template <typename Variant>
0416     static handle cast(Variant &&src, return_value_policy policy, handle parent) {
0417         return visit_helper<V>::call(variant_caster_visitor{policy, parent},
0418                                      std::forward<Variant>(src));
0419     }
0420 
0421     using Type = V<Ts...>;
0422     PYBIND11_TYPE_CASTER(Type,
0423                          const_name("Union[") + detail::concat(make_caster<Ts>::name...)
0424                              + const_name("]"));
0425 };
0426 
0427 #if defined(PYBIND11_HAS_VARIANT)
0428 template <typename... Ts>
0429 struct type_caster<std::variant<Ts...>> : variant_caster<std::variant<Ts...>> {};
0430 
0431 template <>
0432 struct type_caster<std::monostate> : public void_caster<std::monostate> {};
0433 #endif
0434 
0435 PYBIND11_NAMESPACE_END(detail)
0436 
0437 inline std::ostream &operator<<(std::ostream &os, const handle &obj) {
0438 #ifdef PYBIND11_HAS_STRING_VIEW
0439     os << str(obj).cast<std::string_view>();
0440 #else
0441     os << (std::string) str(obj);
0442 #endif
0443     return os;
0444 }
0445 
0446 PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)