stl.h revision 12391
111986Sandreas.sandberg@arm.com/* 211986Sandreas.sandberg@arm.com pybind11/stl.h: Transparent conversion for STL data types 311986Sandreas.sandberg@arm.com 411986Sandreas.sandberg@arm.com Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch> 511986Sandreas.sandberg@arm.com 611986Sandreas.sandberg@arm.com All rights reserved. Use of this source code is governed by a 711986Sandreas.sandberg@arm.com BSD-style license that can be found in the LICENSE file. 811986Sandreas.sandberg@arm.com*/ 911986Sandreas.sandberg@arm.com 1011986Sandreas.sandberg@arm.com#pragma once 1111986Sandreas.sandberg@arm.com 1211986Sandreas.sandberg@arm.com#include "pybind11.h" 1311986Sandreas.sandberg@arm.com#include <set> 1411986Sandreas.sandberg@arm.com#include <unordered_set> 1511986Sandreas.sandberg@arm.com#include <map> 1611986Sandreas.sandberg@arm.com#include <unordered_map> 1711986Sandreas.sandberg@arm.com#include <iostream> 1811986Sandreas.sandberg@arm.com#include <list> 1911986Sandreas.sandberg@arm.com#include <valarray> 2011986Sandreas.sandberg@arm.com 2111986Sandreas.sandberg@arm.com#if defined(_MSC_VER) 2211986Sandreas.sandberg@arm.com#pragma warning(push) 2311986Sandreas.sandberg@arm.com#pragma warning(disable: 4127) // warning C4127: Conditional expression is constant 2411986Sandreas.sandberg@arm.com#endif 2511986Sandreas.sandberg@arm.com 2611986Sandreas.sandberg@arm.com#ifdef __has_include 2711986Sandreas.sandberg@arm.com// std::optional (but including it in c++14 mode isn't allowed) 2811986Sandreas.sandberg@arm.com# if defined(PYBIND11_CPP17) && __has_include(<optional>) 2911986Sandreas.sandberg@arm.com# include <optional> 3011986Sandreas.sandberg@arm.com# define PYBIND11_HAS_OPTIONAL 1 3111986Sandreas.sandberg@arm.com# endif 3211986Sandreas.sandberg@arm.com// std::experimental::optional (but not allowed in c++11 mode) 3311986Sandreas.sandberg@arm.com# if defined(PYBIND11_CPP14) && __has_include(<experimental/optional>) 3411986Sandreas.sandberg@arm.com# include <experimental/optional> 3512391Sjason@lowepower.com# define PYBIND11_HAS_EXP_OPTIONAL 1 3611986Sandreas.sandberg@arm.com# endif 3712391Sjason@lowepower.com// std::variant 3812391Sjason@lowepower.com# if defined(PYBIND11_CPP17) && __has_include(<variant>) 3912391Sjason@lowepower.com# include <variant> 4012391Sjason@lowepower.com# define PYBIND11_HAS_VARIANT 1 4112391Sjason@lowepower.com# endif 4212391Sjason@lowepower.com#elif defined(_MSC_VER) && defined(PYBIND11_CPP17) 4312391Sjason@lowepower.com# include <optional> 4412391Sjason@lowepower.com# include <variant> 4512391Sjason@lowepower.com# define PYBIND11_HAS_OPTIONAL 1 4612391Sjason@lowepower.com# define PYBIND11_HAS_VARIANT 1 4711986Sandreas.sandberg@arm.com#endif 4811986Sandreas.sandberg@arm.com 4912391Sjason@lowepower.comNAMESPACE_BEGIN(PYBIND11_NAMESPACE) 5011986Sandreas.sandberg@arm.comNAMESPACE_BEGIN(detail) 5111986Sandreas.sandberg@arm.com 5212391Sjason@lowepower.com/// Extracts an const lvalue reference or rvalue reference for U based on the type of T (e.g. for 5312391Sjason@lowepower.com/// forwarding a container element). Typically used indirect via forwarded_type(), below. 5412391Sjason@lowepower.comtemplate <typename T, typename U> 5512391Sjason@lowepower.comusing forwarded_type = conditional_t< 5612391Sjason@lowepower.com std::is_lvalue_reference<T>::value, remove_reference_t<U> &, remove_reference_t<U> &&>; 5712391Sjason@lowepower.com 5812391Sjason@lowepower.com/// Forwards a value U as rvalue or lvalue according to whether T is rvalue or lvalue; typically 5912391Sjason@lowepower.com/// used for forwarding a container's elements. 6012391Sjason@lowepower.comtemplate <typename T, typename U> 6112391Sjason@lowepower.comforwarded_type<T, U> forward_like(U &&u) { 6212391Sjason@lowepower.com return std::forward<detail::forwarded_type<T, U>>(std::forward<U>(u)); 6312391Sjason@lowepower.com} 6412391Sjason@lowepower.com 6511986Sandreas.sandberg@arm.comtemplate <typename Type, typename Key> struct set_caster { 6611986Sandreas.sandberg@arm.com using type = Type; 6711986Sandreas.sandberg@arm.com using key_conv = make_caster<Key>; 6811986Sandreas.sandberg@arm.com 6911986Sandreas.sandberg@arm.com bool load(handle src, bool convert) { 7011986Sandreas.sandberg@arm.com if (!isinstance<pybind11::set>(src)) 7111986Sandreas.sandberg@arm.com return false; 7211986Sandreas.sandberg@arm.com auto s = reinterpret_borrow<pybind11::set>(src); 7311986Sandreas.sandberg@arm.com value.clear(); 7411986Sandreas.sandberg@arm.com for (auto entry : s) { 7512391Sjason@lowepower.com key_conv conv; 7611986Sandreas.sandberg@arm.com if (!conv.load(entry, convert)) 7711986Sandreas.sandberg@arm.com return false; 7812391Sjason@lowepower.com value.insert(cast_op<Key &&>(std::move(conv))); 7911986Sandreas.sandberg@arm.com } 8011986Sandreas.sandberg@arm.com return true; 8111986Sandreas.sandberg@arm.com } 8211986Sandreas.sandberg@arm.com 8312391Sjason@lowepower.com template <typename T> 8412391Sjason@lowepower.com static handle cast(T &&src, return_value_policy policy, handle parent) { 8511986Sandreas.sandberg@arm.com pybind11::set s; 8612391Sjason@lowepower.com for (auto &&value : src) { 8712391Sjason@lowepower.com auto value_ = reinterpret_steal<object>(key_conv::cast(forward_like<T>(value), policy, parent)); 8811986Sandreas.sandberg@arm.com if (!value_ || !s.add(value_)) 8911986Sandreas.sandberg@arm.com return handle(); 9011986Sandreas.sandberg@arm.com } 9111986Sandreas.sandberg@arm.com return s.release(); 9211986Sandreas.sandberg@arm.com } 9311986Sandreas.sandberg@arm.com 9411986Sandreas.sandberg@arm.com PYBIND11_TYPE_CASTER(type, _("Set[") + key_conv::name() + _("]")); 9511986Sandreas.sandberg@arm.com}; 9611986Sandreas.sandberg@arm.com 9711986Sandreas.sandberg@arm.comtemplate <typename Type, typename Key, typename Value> struct map_caster { 9811986Sandreas.sandberg@arm.com using key_conv = make_caster<Key>; 9911986Sandreas.sandberg@arm.com using value_conv = make_caster<Value>; 10011986Sandreas.sandberg@arm.com 10111986Sandreas.sandberg@arm.com bool load(handle src, bool convert) { 10211986Sandreas.sandberg@arm.com if (!isinstance<dict>(src)) 10311986Sandreas.sandberg@arm.com return false; 10411986Sandreas.sandberg@arm.com auto d = reinterpret_borrow<dict>(src); 10511986Sandreas.sandberg@arm.com value.clear(); 10611986Sandreas.sandberg@arm.com for (auto it : d) { 10712391Sjason@lowepower.com key_conv kconv; 10812391Sjason@lowepower.com value_conv vconv; 10911986Sandreas.sandberg@arm.com if (!kconv.load(it.first.ptr(), convert) || 11011986Sandreas.sandberg@arm.com !vconv.load(it.second.ptr(), convert)) 11111986Sandreas.sandberg@arm.com return false; 11212391Sjason@lowepower.com value.emplace(cast_op<Key &&>(std::move(kconv)), cast_op<Value &&>(std::move(vconv))); 11311986Sandreas.sandberg@arm.com } 11411986Sandreas.sandberg@arm.com return true; 11511986Sandreas.sandberg@arm.com } 11611986Sandreas.sandberg@arm.com 11712391Sjason@lowepower.com template <typename T> 11812391Sjason@lowepower.com static handle cast(T &&src, return_value_policy policy, handle parent) { 11911986Sandreas.sandberg@arm.com dict d; 12012391Sjason@lowepower.com for (auto &&kv : src) { 12112391Sjason@lowepower.com auto key = reinterpret_steal<object>(key_conv::cast(forward_like<T>(kv.first), policy, parent)); 12212391Sjason@lowepower.com auto value = reinterpret_steal<object>(value_conv::cast(forward_like<T>(kv.second), policy, parent)); 12311986Sandreas.sandberg@arm.com if (!key || !value) 12411986Sandreas.sandberg@arm.com return handle(); 12511986Sandreas.sandberg@arm.com d[key] = value; 12611986Sandreas.sandberg@arm.com } 12711986Sandreas.sandberg@arm.com return d.release(); 12811986Sandreas.sandberg@arm.com } 12911986Sandreas.sandberg@arm.com 13011986Sandreas.sandberg@arm.com PYBIND11_TYPE_CASTER(Type, _("Dict[") + key_conv::name() + _(", ") + value_conv::name() + _("]")); 13111986Sandreas.sandberg@arm.com}; 13211986Sandreas.sandberg@arm.com 13311986Sandreas.sandberg@arm.comtemplate <typename Type, typename Value> struct list_caster { 13411986Sandreas.sandberg@arm.com using value_conv = make_caster<Value>; 13511986Sandreas.sandberg@arm.com 13611986Sandreas.sandberg@arm.com bool load(handle src, bool convert) { 13711986Sandreas.sandberg@arm.com if (!isinstance<sequence>(src)) 13811986Sandreas.sandberg@arm.com return false; 13911986Sandreas.sandberg@arm.com auto s = reinterpret_borrow<sequence>(src); 14011986Sandreas.sandberg@arm.com value.clear(); 14111986Sandreas.sandberg@arm.com reserve_maybe(s, &value); 14211986Sandreas.sandberg@arm.com for (auto it : s) { 14312391Sjason@lowepower.com value_conv conv; 14411986Sandreas.sandberg@arm.com if (!conv.load(it, convert)) 14511986Sandreas.sandberg@arm.com return false; 14612391Sjason@lowepower.com value.push_back(cast_op<Value &&>(std::move(conv))); 14711986Sandreas.sandberg@arm.com } 14811986Sandreas.sandberg@arm.com return true; 14911986Sandreas.sandberg@arm.com } 15011986Sandreas.sandberg@arm.com 15111986Sandreas.sandberg@arm.comprivate: 15211986Sandreas.sandberg@arm.com template <typename T = Type, 15311986Sandreas.sandberg@arm.com enable_if_t<std::is_same<decltype(std::declval<T>().reserve(0)), void>::value, int> = 0> 15411986Sandreas.sandberg@arm.com void reserve_maybe(sequence s, Type *) { value.reserve(s.size()); } 15511986Sandreas.sandberg@arm.com void reserve_maybe(sequence, void *) { } 15611986Sandreas.sandberg@arm.com 15711986Sandreas.sandberg@arm.compublic: 15812391Sjason@lowepower.com template <typename T> 15912391Sjason@lowepower.com static handle cast(T &&src, return_value_policy policy, handle parent) { 16011986Sandreas.sandberg@arm.com list l(src.size()); 16111986Sandreas.sandberg@arm.com size_t index = 0; 16212391Sjason@lowepower.com for (auto &&value : src) { 16312391Sjason@lowepower.com auto value_ = reinterpret_steal<object>(value_conv::cast(forward_like<T>(value), policy, parent)); 16411986Sandreas.sandberg@arm.com if (!value_) 16511986Sandreas.sandberg@arm.com return handle(); 16612037Sandreas.sandberg@arm.com PyList_SET_ITEM(l.ptr(), (ssize_t) index++, value_.release().ptr()); // steals a reference 16711986Sandreas.sandberg@arm.com } 16811986Sandreas.sandberg@arm.com return l.release(); 16911986Sandreas.sandberg@arm.com } 17011986Sandreas.sandberg@arm.com 17111986Sandreas.sandberg@arm.com PYBIND11_TYPE_CASTER(Type, _("List[") + value_conv::name() + _("]")); 17211986Sandreas.sandberg@arm.com}; 17311986Sandreas.sandberg@arm.com 17411986Sandreas.sandberg@arm.comtemplate <typename Type, typename Alloc> struct type_caster<std::vector<Type, Alloc>> 17511986Sandreas.sandberg@arm.com : list_caster<std::vector<Type, Alloc>, Type> { }; 17611986Sandreas.sandberg@arm.com 17711986Sandreas.sandberg@arm.comtemplate <typename Type, typename Alloc> struct type_caster<std::list<Type, Alloc>> 17811986Sandreas.sandberg@arm.com : list_caster<std::list<Type, Alloc>, Type> { }; 17911986Sandreas.sandberg@arm.com 18011986Sandreas.sandberg@arm.comtemplate <typename ArrayType, typename Value, bool Resizable, size_t Size = 0> struct array_caster { 18111986Sandreas.sandberg@arm.com using value_conv = make_caster<Value>; 18211986Sandreas.sandberg@arm.com 18311986Sandreas.sandberg@arm.comprivate: 18411986Sandreas.sandberg@arm.com template <bool R = Resizable> 18511986Sandreas.sandberg@arm.com bool require_size(enable_if_t<R, size_t> size) { 18611986Sandreas.sandberg@arm.com if (value.size() != size) 18711986Sandreas.sandberg@arm.com value.resize(size); 18811986Sandreas.sandberg@arm.com return true; 18911986Sandreas.sandberg@arm.com } 19011986Sandreas.sandberg@arm.com template <bool R = Resizable> 19111986Sandreas.sandberg@arm.com bool require_size(enable_if_t<!R, size_t> size) { 19211986Sandreas.sandberg@arm.com return size == Size; 19311986Sandreas.sandberg@arm.com } 19411986Sandreas.sandberg@arm.com 19511986Sandreas.sandberg@arm.compublic: 19611986Sandreas.sandberg@arm.com bool load(handle src, bool convert) { 19711986Sandreas.sandberg@arm.com if (!isinstance<list>(src)) 19811986Sandreas.sandberg@arm.com return false; 19911986Sandreas.sandberg@arm.com auto l = reinterpret_borrow<list>(src); 20011986Sandreas.sandberg@arm.com if (!require_size(l.size())) 20111986Sandreas.sandberg@arm.com return false; 20211986Sandreas.sandberg@arm.com size_t ctr = 0; 20311986Sandreas.sandberg@arm.com for (auto it : l) { 20412391Sjason@lowepower.com value_conv conv; 20511986Sandreas.sandberg@arm.com if (!conv.load(it, convert)) 20611986Sandreas.sandberg@arm.com return false; 20712391Sjason@lowepower.com value[ctr++] = cast_op<Value &&>(std::move(conv)); 20811986Sandreas.sandberg@arm.com } 20911986Sandreas.sandberg@arm.com return true; 21011986Sandreas.sandberg@arm.com } 21111986Sandreas.sandberg@arm.com 21212391Sjason@lowepower.com template <typename T> 21312391Sjason@lowepower.com static handle cast(T &&src, return_value_policy policy, handle parent) { 21411986Sandreas.sandberg@arm.com list l(src.size()); 21511986Sandreas.sandberg@arm.com size_t index = 0; 21612391Sjason@lowepower.com for (auto &&value : src) { 21712391Sjason@lowepower.com auto value_ = reinterpret_steal<object>(value_conv::cast(forward_like<T>(value), policy, parent)); 21811986Sandreas.sandberg@arm.com if (!value_) 21911986Sandreas.sandberg@arm.com return handle(); 22012037Sandreas.sandberg@arm.com PyList_SET_ITEM(l.ptr(), (ssize_t) index++, value_.release().ptr()); // steals a reference 22111986Sandreas.sandberg@arm.com } 22211986Sandreas.sandberg@arm.com return l.release(); 22311986Sandreas.sandberg@arm.com } 22411986Sandreas.sandberg@arm.com 22511986Sandreas.sandberg@arm.com PYBIND11_TYPE_CASTER(ArrayType, _("List[") + value_conv::name() + _<Resizable>(_(""), _("[") + _<Size>() + _("]")) + _("]")); 22611986Sandreas.sandberg@arm.com}; 22711986Sandreas.sandberg@arm.com 22811986Sandreas.sandberg@arm.comtemplate <typename Type, size_t Size> struct type_caster<std::array<Type, Size>> 22911986Sandreas.sandberg@arm.com : array_caster<std::array<Type, Size>, Type, false, Size> { }; 23011986Sandreas.sandberg@arm.com 23111986Sandreas.sandberg@arm.comtemplate <typename Type> struct type_caster<std::valarray<Type>> 23211986Sandreas.sandberg@arm.com : array_caster<std::valarray<Type>, Type, true> { }; 23311986Sandreas.sandberg@arm.com 23411986Sandreas.sandberg@arm.comtemplate <typename Key, typename Compare, typename Alloc> struct type_caster<std::set<Key, Compare, Alloc>> 23511986Sandreas.sandberg@arm.com : set_caster<std::set<Key, Compare, Alloc>, Key> { }; 23611986Sandreas.sandberg@arm.com 23711986Sandreas.sandberg@arm.comtemplate <typename Key, typename Hash, typename Equal, typename Alloc> struct type_caster<std::unordered_set<Key, Hash, Equal, Alloc>> 23811986Sandreas.sandberg@arm.com : set_caster<std::unordered_set<Key, Hash, Equal, Alloc>, Key> { }; 23911986Sandreas.sandberg@arm.com 24011986Sandreas.sandberg@arm.comtemplate <typename Key, typename Value, typename Compare, typename Alloc> struct type_caster<std::map<Key, Value, Compare, Alloc>> 24111986Sandreas.sandberg@arm.com : map_caster<std::map<Key, Value, Compare, Alloc>, Key, Value> { }; 24211986Sandreas.sandberg@arm.com 24311986Sandreas.sandberg@arm.comtemplate <typename Key, typename Value, typename Hash, typename Equal, typename Alloc> struct type_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>> 24411986Sandreas.sandberg@arm.com : map_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>, Key, Value> { }; 24511986Sandreas.sandberg@arm.com 24611986Sandreas.sandberg@arm.com// This type caster is intended to be used for std::optional and std::experimental::optional 24711986Sandreas.sandberg@arm.comtemplate<typename T> struct optional_caster { 24811986Sandreas.sandberg@arm.com using value_conv = make_caster<typename T::value_type>; 24911986Sandreas.sandberg@arm.com 25012391Sjason@lowepower.com template <typename T_> 25112391Sjason@lowepower.com static handle cast(T_ &&src, return_value_policy policy, handle parent) { 25211986Sandreas.sandberg@arm.com if (!src) 25311986Sandreas.sandberg@arm.com return none().inc_ref(); 25412391Sjason@lowepower.com return value_conv::cast(*std::forward<T_>(src), policy, parent); 25511986Sandreas.sandberg@arm.com } 25611986Sandreas.sandberg@arm.com 25711986Sandreas.sandberg@arm.com bool load(handle src, bool convert) { 25811986Sandreas.sandberg@arm.com if (!src) { 25911986Sandreas.sandberg@arm.com return false; 26011986Sandreas.sandberg@arm.com } else if (src.is_none()) { 26112391Sjason@lowepower.com return true; // default-constructed value is already empty 26211986Sandreas.sandberg@arm.com } 26311986Sandreas.sandberg@arm.com value_conv inner_caster; 26411986Sandreas.sandberg@arm.com if (!inner_caster.load(src, convert)) 26511986Sandreas.sandberg@arm.com return false; 26611986Sandreas.sandberg@arm.com 26712391Sjason@lowepower.com value.emplace(cast_op<typename T::value_type &&>(std::move(inner_caster))); 26811986Sandreas.sandberg@arm.com return true; 26911986Sandreas.sandberg@arm.com } 27011986Sandreas.sandberg@arm.com 27111986Sandreas.sandberg@arm.com PYBIND11_TYPE_CASTER(T, _("Optional[") + value_conv::name() + _("]")); 27211986Sandreas.sandberg@arm.com}; 27311986Sandreas.sandberg@arm.com 27411987Sandreas.sandberg@arm.com#ifdef PYBIND11_HAS_OPTIONAL 27511986Sandreas.sandberg@arm.comtemplate<typename T> struct type_caster<std::optional<T>> 27611986Sandreas.sandberg@arm.com : public optional_caster<std::optional<T>> {}; 27711986Sandreas.sandberg@arm.com 27811986Sandreas.sandberg@arm.comtemplate<> struct type_caster<std::nullopt_t> 27911986Sandreas.sandberg@arm.com : public void_caster<std::nullopt_t> {}; 28011986Sandreas.sandberg@arm.com#endif 28111986Sandreas.sandberg@arm.com 28211987Sandreas.sandberg@arm.com#ifdef PYBIND11_HAS_EXP_OPTIONAL 28311986Sandreas.sandberg@arm.comtemplate<typename T> struct type_caster<std::experimental::optional<T>> 28411986Sandreas.sandberg@arm.com : public optional_caster<std::experimental::optional<T>> {}; 28511986Sandreas.sandberg@arm.com 28611986Sandreas.sandberg@arm.comtemplate<> struct type_caster<std::experimental::nullopt_t> 28711986Sandreas.sandberg@arm.com : public void_caster<std::experimental::nullopt_t> {}; 28811986Sandreas.sandberg@arm.com#endif 28911986Sandreas.sandberg@arm.com 29012391Sjason@lowepower.com/// Visit a variant and cast any found type to Python 29112391Sjason@lowepower.comstruct variant_caster_visitor { 29212391Sjason@lowepower.com return_value_policy policy; 29312391Sjason@lowepower.com handle parent; 29412391Sjason@lowepower.com 29512391Sjason@lowepower.com using result_type = handle; // required by boost::variant in C++11 29612391Sjason@lowepower.com 29712391Sjason@lowepower.com template <typename T> 29812391Sjason@lowepower.com result_type operator()(T &&src) const { 29912391Sjason@lowepower.com return make_caster<T>::cast(std::forward<T>(src), policy, parent); 30012391Sjason@lowepower.com } 30112391Sjason@lowepower.com}; 30212391Sjason@lowepower.com 30312391Sjason@lowepower.com/// Helper class which abstracts away variant's `visit` function. `std::variant` and similar 30412391Sjason@lowepower.com/// `namespace::variant` types which provide a `namespace::visit()` function are handled here 30512391Sjason@lowepower.com/// automatically using argument-dependent lookup. Users can provide specializations for other 30612391Sjason@lowepower.com/// variant-like classes, e.g. `boost::variant` and `boost::apply_visitor`. 30712391Sjason@lowepower.comtemplate <template<typename...> class Variant> 30812391Sjason@lowepower.comstruct visit_helper { 30912391Sjason@lowepower.com template <typename... Args> 31012391Sjason@lowepower.com static auto call(Args &&...args) -> decltype(visit(std::forward<Args>(args)...)) { 31112391Sjason@lowepower.com return visit(std::forward<Args>(args)...); 31212391Sjason@lowepower.com } 31312391Sjason@lowepower.com}; 31412391Sjason@lowepower.com 31512391Sjason@lowepower.com/// Generic variant caster 31612391Sjason@lowepower.comtemplate <typename Variant> struct variant_caster; 31712391Sjason@lowepower.com 31812391Sjason@lowepower.comtemplate <template<typename...> class V, typename... Ts> 31912391Sjason@lowepower.comstruct variant_caster<V<Ts...>> { 32012391Sjason@lowepower.com static_assert(sizeof...(Ts) > 0, "Variant must consist of at least one alternative."); 32112391Sjason@lowepower.com 32212391Sjason@lowepower.com template <typename U, typename... Us> 32312391Sjason@lowepower.com bool load_alternative(handle src, bool convert, type_list<U, Us...>) { 32412391Sjason@lowepower.com auto caster = make_caster<U>(); 32512391Sjason@lowepower.com if (caster.load(src, convert)) { 32612391Sjason@lowepower.com value = cast_op<U>(caster); 32712391Sjason@lowepower.com return true; 32812391Sjason@lowepower.com } 32912391Sjason@lowepower.com return load_alternative(src, convert, type_list<Us...>{}); 33012391Sjason@lowepower.com } 33112391Sjason@lowepower.com 33212391Sjason@lowepower.com bool load_alternative(handle, bool, type_list<>) { return false; } 33312391Sjason@lowepower.com 33412391Sjason@lowepower.com bool load(handle src, bool convert) { 33512391Sjason@lowepower.com // Do a first pass without conversions to improve constructor resolution. 33612391Sjason@lowepower.com // E.g. `py::int_(1).cast<variant<double, int>>()` needs to fill the `int` 33712391Sjason@lowepower.com // slot of the variant. Without two-pass loading `double` would be filled 33812391Sjason@lowepower.com // because it appears first and a conversion is possible. 33912391Sjason@lowepower.com if (convert && load_alternative(src, false, type_list<Ts...>{})) 34012391Sjason@lowepower.com return true; 34112391Sjason@lowepower.com return load_alternative(src, convert, type_list<Ts...>{}); 34212391Sjason@lowepower.com } 34312391Sjason@lowepower.com 34412391Sjason@lowepower.com template <typename Variant> 34512391Sjason@lowepower.com static handle cast(Variant &&src, return_value_policy policy, handle parent) { 34612391Sjason@lowepower.com return visit_helper<V>::call(variant_caster_visitor{policy, parent}, 34712391Sjason@lowepower.com std::forward<Variant>(src)); 34812391Sjason@lowepower.com } 34912391Sjason@lowepower.com 35012391Sjason@lowepower.com using Type = V<Ts...>; 35112391Sjason@lowepower.com PYBIND11_TYPE_CASTER(Type, _("Union[") + detail::concat(make_caster<Ts>::name()...) + _("]")); 35212391Sjason@lowepower.com}; 35312391Sjason@lowepower.com 35412391Sjason@lowepower.com#ifdef PYBIND11_HAS_VARIANT 35512391Sjason@lowepower.comtemplate <typename... Ts> 35612391Sjason@lowepower.comstruct type_caster<std::variant<Ts...>> : variant_caster<std::variant<Ts...>> { }; 35712391Sjason@lowepower.com#endif 35811986Sandreas.sandberg@arm.comNAMESPACE_END(detail) 35911986Sandreas.sandberg@arm.com 36011986Sandreas.sandberg@arm.cominline std::ostream &operator<<(std::ostream &os, const handle &obj) { 36111986Sandreas.sandberg@arm.com os << (std::string) str(obj); 36211986Sandreas.sandberg@arm.com return os; 36311986Sandreas.sandberg@arm.com} 36411986Sandreas.sandberg@arm.com 36512391Sjason@lowepower.comNAMESPACE_END(PYBIND11_NAMESPACE) 36611986Sandreas.sandberg@arm.com 36711986Sandreas.sandberg@arm.com#if defined(_MSC_VER) 36811986Sandreas.sandberg@arm.com#pragma warning(pop) 36911986Sandreas.sandberg@arm.com#endif 370