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> 1914299Sbbruce@ucdavis.edu#include <deque> 2011986Sandreas.sandberg@arm.com#include <valarray> 2111986Sandreas.sandberg@arm.com 2211986Sandreas.sandberg@arm.com#if defined(_MSC_VER) 2311986Sandreas.sandberg@arm.com#pragma warning(push) 2411986Sandreas.sandberg@arm.com#pragma warning(disable: 4127) // warning C4127: Conditional expression is constant 2511986Sandreas.sandberg@arm.com#endif 2611986Sandreas.sandberg@arm.com 2711986Sandreas.sandberg@arm.com#ifdef __has_include 2811986Sandreas.sandberg@arm.com// std::optional (but including it in c++14 mode isn't allowed) 2911986Sandreas.sandberg@arm.com# if defined(PYBIND11_CPP17) && __has_include(<optional>) 3011986Sandreas.sandberg@arm.com# include <optional> 3111986Sandreas.sandberg@arm.com# define PYBIND11_HAS_OPTIONAL 1 3211986Sandreas.sandberg@arm.com# endif 3311986Sandreas.sandberg@arm.com// std::experimental::optional (but not allowed in c++11 mode) 3414299Sbbruce@ucdavis.edu# if defined(PYBIND11_CPP14) && (__has_include(<experimental/optional>) && \ 3514299Sbbruce@ucdavis.edu !__has_include(<optional>)) 3611986Sandreas.sandberg@arm.com# include <experimental/optional> 3712391Sjason@lowepower.com# define PYBIND11_HAS_EXP_OPTIONAL 1 3811986Sandreas.sandberg@arm.com# endif 3912391Sjason@lowepower.com// std::variant 4012391Sjason@lowepower.com# if defined(PYBIND11_CPP17) && __has_include(<variant>) 4112391Sjason@lowepower.com# include <variant> 4212391Sjason@lowepower.com# define PYBIND11_HAS_VARIANT 1 4312391Sjason@lowepower.com# endif 4412391Sjason@lowepower.com#elif defined(_MSC_VER) && defined(PYBIND11_CPP17) 4512391Sjason@lowepower.com# include <optional> 4612391Sjason@lowepower.com# include <variant> 4712391Sjason@lowepower.com# define PYBIND11_HAS_OPTIONAL 1 4812391Sjason@lowepower.com# define PYBIND11_HAS_VARIANT 1 4911986Sandreas.sandberg@arm.com#endif 5011986Sandreas.sandberg@arm.com 5112391Sjason@lowepower.comNAMESPACE_BEGIN(PYBIND11_NAMESPACE) 5211986Sandreas.sandberg@arm.comNAMESPACE_BEGIN(detail) 5311986Sandreas.sandberg@arm.com 5412391Sjason@lowepower.com/// Extracts an const lvalue reference or rvalue reference for U based on the type of T (e.g. for 5512391Sjason@lowepower.com/// forwarding a container element). Typically used indirect via forwarded_type(), below. 5612391Sjason@lowepower.comtemplate <typename T, typename U> 5712391Sjason@lowepower.comusing forwarded_type = conditional_t< 5812391Sjason@lowepower.com std::is_lvalue_reference<T>::value, remove_reference_t<U> &, remove_reference_t<U> &&>; 5912391Sjason@lowepower.com 6012391Sjason@lowepower.com/// Forwards a value U as rvalue or lvalue according to whether T is rvalue or lvalue; typically 6112391Sjason@lowepower.com/// used for forwarding a container's elements. 6212391Sjason@lowepower.comtemplate <typename T, typename U> 6312391Sjason@lowepower.comforwarded_type<T, U> forward_like(U &&u) { 6412391Sjason@lowepower.com return std::forward<detail::forwarded_type<T, U>>(std::forward<U>(u)); 6512391Sjason@lowepower.com} 6612391Sjason@lowepower.com 6711986Sandreas.sandberg@arm.comtemplate <typename Type, typename Key> struct set_caster { 6811986Sandreas.sandberg@arm.com using type = Type; 6911986Sandreas.sandberg@arm.com using key_conv = make_caster<Key>; 7011986Sandreas.sandberg@arm.com 7111986Sandreas.sandberg@arm.com bool load(handle src, bool convert) { 7211986Sandreas.sandberg@arm.com if (!isinstance<pybind11::set>(src)) 7311986Sandreas.sandberg@arm.com return false; 7411986Sandreas.sandberg@arm.com auto s = reinterpret_borrow<pybind11::set>(src); 7511986Sandreas.sandberg@arm.com value.clear(); 7611986Sandreas.sandberg@arm.com for (auto entry : s) { 7712391Sjason@lowepower.com key_conv conv; 7811986Sandreas.sandberg@arm.com if (!conv.load(entry, convert)) 7911986Sandreas.sandberg@arm.com return false; 8012391Sjason@lowepower.com value.insert(cast_op<Key &&>(std::move(conv))); 8111986Sandreas.sandberg@arm.com } 8211986Sandreas.sandberg@arm.com return true; 8311986Sandreas.sandberg@arm.com } 8411986Sandreas.sandberg@arm.com 8512391Sjason@lowepower.com template <typename T> 8612391Sjason@lowepower.com static handle cast(T &&src, return_value_policy policy, handle parent) { 8714299Sbbruce@ucdavis.edu if (!std::is_lvalue_reference<T>::value) 8814299Sbbruce@ucdavis.edu policy = return_value_policy_override<Key>::policy(policy); 8911986Sandreas.sandberg@arm.com pybind11::set s; 9012391Sjason@lowepower.com for (auto &&value : src) { 9112391Sjason@lowepower.com auto value_ = reinterpret_steal<object>(key_conv::cast(forward_like<T>(value), policy, parent)); 9211986Sandreas.sandberg@arm.com if (!value_ || !s.add(value_)) 9311986Sandreas.sandberg@arm.com return handle(); 9411986Sandreas.sandberg@arm.com } 9511986Sandreas.sandberg@arm.com return s.release(); 9611986Sandreas.sandberg@arm.com } 9711986Sandreas.sandberg@arm.com 9814299Sbbruce@ucdavis.edu PYBIND11_TYPE_CASTER(type, _("Set[") + key_conv::name + _("]")); 9911986Sandreas.sandberg@arm.com}; 10011986Sandreas.sandberg@arm.com 10111986Sandreas.sandberg@arm.comtemplate <typename Type, typename Key, typename Value> struct map_caster { 10211986Sandreas.sandberg@arm.com using key_conv = make_caster<Key>; 10311986Sandreas.sandberg@arm.com using value_conv = make_caster<Value>; 10411986Sandreas.sandberg@arm.com 10511986Sandreas.sandberg@arm.com bool load(handle src, bool convert) { 10611986Sandreas.sandberg@arm.com if (!isinstance<dict>(src)) 10711986Sandreas.sandberg@arm.com return false; 10811986Sandreas.sandberg@arm.com auto d = reinterpret_borrow<dict>(src); 10911986Sandreas.sandberg@arm.com value.clear(); 11011986Sandreas.sandberg@arm.com for (auto it : d) { 11112391Sjason@lowepower.com key_conv kconv; 11212391Sjason@lowepower.com value_conv vconv; 11311986Sandreas.sandberg@arm.com if (!kconv.load(it.first.ptr(), convert) || 11411986Sandreas.sandberg@arm.com !vconv.load(it.second.ptr(), convert)) 11511986Sandreas.sandberg@arm.com return false; 11612391Sjason@lowepower.com value.emplace(cast_op<Key &&>(std::move(kconv)), cast_op<Value &&>(std::move(vconv))); 11711986Sandreas.sandberg@arm.com } 11811986Sandreas.sandberg@arm.com return true; 11911986Sandreas.sandberg@arm.com } 12011986Sandreas.sandberg@arm.com 12112391Sjason@lowepower.com template <typename T> 12212391Sjason@lowepower.com static handle cast(T &&src, return_value_policy policy, handle parent) { 12311986Sandreas.sandberg@arm.com dict d; 12414299Sbbruce@ucdavis.edu return_value_policy policy_key = policy; 12514299Sbbruce@ucdavis.edu return_value_policy policy_value = policy; 12614299Sbbruce@ucdavis.edu if (!std::is_lvalue_reference<T>::value) { 12714299Sbbruce@ucdavis.edu policy_key = return_value_policy_override<Key>::policy(policy_key); 12814299Sbbruce@ucdavis.edu policy_value = return_value_policy_override<Value>::policy(policy_value); 12914299Sbbruce@ucdavis.edu } 13012391Sjason@lowepower.com for (auto &&kv : src) { 13114299Sbbruce@ucdavis.edu auto key = reinterpret_steal<object>(key_conv::cast(forward_like<T>(kv.first), policy_key, parent)); 13214299Sbbruce@ucdavis.edu auto value = reinterpret_steal<object>(value_conv::cast(forward_like<T>(kv.second), policy_value, parent)); 13311986Sandreas.sandberg@arm.com if (!key || !value) 13411986Sandreas.sandberg@arm.com return handle(); 13511986Sandreas.sandberg@arm.com d[key] = value; 13611986Sandreas.sandberg@arm.com } 13711986Sandreas.sandberg@arm.com return d.release(); 13811986Sandreas.sandberg@arm.com } 13911986Sandreas.sandberg@arm.com 14014299Sbbruce@ucdavis.edu PYBIND11_TYPE_CASTER(Type, _("Dict[") + key_conv::name + _(", ") + value_conv::name + _("]")); 14111986Sandreas.sandberg@arm.com}; 14211986Sandreas.sandberg@arm.com 14311986Sandreas.sandberg@arm.comtemplate <typename Type, typename Value> struct list_caster { 14411986Sandreas.sandberg@arm.com using value_conv = make_caster<Value>; 14511986Sandreas.sandberg@arm.com 14611986Sandreas.sandberg@arm.com bool load(handle src, bool convert) { 14714299Sbbruce@ucdavis.edu if (!isinstance<sequence>(src) || isinstance<str>(src)) 14811986Sandreas.sandberg@arm.com return false; 14911986Sandreas.sandberg@arm.com auto s = reinterpret_borrow<sequence>(src); 15011986Sandreas.sandberg@arm.com value.clear(); 15111986Sandreas.sandberg@arm.com reserve_maybe(s, &value); 15211986Sandreas.sandberg@arm.com for (auto it : s) { 15312391Sjason@lowepower.com value_conv conv; 15411986Sandreas.sandberg@arm.com if (!conv.load(it, convert)) 15511986Sandreas.sandberg@arm.com return false; 15612391Sjason@lowepower.com value.push_back(cast_op<Value &&>(std::move(conv))); 15711986Sandreas.sandberg@arm.com } 15811986Sandreas.sandberg@arm.com return true; 15911986Sandreas.sandberg@arm.com } 16011986Sandreas.sandberg@arm.com 16111986Sandreas.sandberg@arm.comprivate: 16211986Sandreas.sandberg@arm.com template <typename T = Type, 16311986Sandreas.sandberg@arm.com enable_if_t<std::is_same<decltype(std::declval<T>().reserve(0)), void>::value, int> = 0> 16411986Sandreas.sandberg@arm.com void reserve_maybe(sequence s, Type *) { value.reserve(s.size()); } 16511986Sandreas.sandberg@arm.com void reserve_maybe(sequence, void *) { } 16611986Sandreas.sandberg@arm.com 16711986Sandreas.sandberg@arm.compublic: 16812391Sjason@lowepower.com template <typename T> 16912391Sjason@lowepower.com static handle cast(T &&src, return_value_policy policy, handle parent) { 17014299Sbbruce@ucdavis.edu if (!std::is_lvalue_reference<T>::value) 17114299Sbbruce@ucdavis.edu policy = return_value_policy_override<Value>::policy(policy); 17211986Sandreas.sandberg@arm.com list l(src.size()); 17311986Sandreas.sandberg@arm.com size_t index = 0; 17412391Sjason@lowepower.com for (auto &&value : src) { 17512391Sjason@lowepower.com auto value_ = reinterpret_steal<object>(value_conv::cast(forward_like<T>(value), policy, parent)); 17611986Sandreas.sandberg@arm.com if (!value_) 17711986Sandreas.sandberg@arm.com return handle(); 17812037Sandreas.sandberg@arm.com PyList_SET_ITEM(l.ptr(), (ssize_t) index++, value_.release().ptr()); // steals a reference 17911986Sandreas.sandberg@arm.com } 18011986Sandreas.sandberg@arm.com return l.release(); 18111986Sandreas.sandberg@arm.com } 18211986Sandreas.sandberg@arm.com 18314299Sbbruce@ucdavis.edu PYBIND11_TYPE_CASTER(Type, _("List[") + value_conv::name + _("]")); 18411986Sandreas.sandberg@arm.com}; 18511986Sandreas.sandberg@arm.com 18611986Sandreas.sandberg@arm.comtemplate <typename Type, typename Alloc> struct type_caster<std::vector<Type, Alloc>> 18711986Sandreas.sandberg@arm.com : list_caster<std::vector<Type, Alloc>, Type> { }; 18811986Sandreas.sandberg@arm.com 18914299Sbbruce@ucdavis.edutemplate <typename Type, typename Alloc> struct type_caster<std::deque<Type, Alloc>> 19014299Sbbruce@ucdavis.edu : list_caster<std::deque<Type, Alloc>, Type> { }; 19114299Sbbruce@ucdavis.edu 19211986Sandreas.sandberg@arm.comtemplate <typename Type, typename Alloc> struct type_caster<std::list<Type, Alloc>> 19311986Sandreas.sandberg@arm.com : list_caster<std::list<Type, Alloc>, Type> { }; 19411986Sandreas.sandberg@arm.com 19511986Sandreas.sandberg@arm.comtemplate <typename ArrayType, typename Value, bool Resizable, size_t Size = 0> struct array_caster { 19611986Sandreas.sandberg@arm.com using value_conv = make_caster<Value>; 19711986Sandreas.sandberg@arm.com 19811986Sandreas.sandberg@arm.comprivate: 19911986Sandreas.sandberg@arm.com template <bool R = Resizable> 20011986Sandreas.sandberg@arm.com bool require_size(enable_if_t<R, size_t> size) { 20111986Sandreas.sandberg@arm.com if (value.size() != size) 20211986Sandreas.sandberg@arm.com value.resize(size); 20311986Sandreas.sandberg@arm.com return true; 20411986Sandreas.sandberg@arm.com } 20511986Sandreas.sandberg@arm.com template <bool R = Resizable> 20611986Sandreas.sandberg@arm.com bool require_size(enable_if_t<!R, size_t> size) { 20711986Sandreas.sandberg@arm.com return size == Size; 20811986Sandreas.sandberg@arm.com } 20911986Sandreas.sandberg@arm.com 21011986Sandreas.sandberg@arm.compublic: 21111986Sandreas.sandberg@arm.com bool load(handle src, bool convert) { 21214299Sbbruce@ucdavis.edu if (!isinstance<sequence>(src)) 21311986Sandreas.sandberg@arm.com return false; 21414299Sbbruce@ucdavis.edu auto l = reinterpret_borrow<sequence>(src); 21511986Sandreas.sandberg@arm.com if (!require_size(l.size())) 21611986Sandreas.sandberg@arm.com return false; 21711986Sandreas.sandberg@arm.com size_t ctr = 0; 21811986Sandreas.sandberg@arm.com for (auto it : l) { 21912391Sjason@lowepower.com value_conv conv; 22011986Sandreas.sandberg@arm.com if (!conv.load(it, convert)) 22111986Sandreas.sandberg@arm.com return false; 22212391Sjason@lowepower.com value[ctr++] = cast_op<Value &&>(std::move(conv)); 22311986Sandreas.sandberg@arm.com } 22411986Sandreas.sandberg@arm.com return true; 22511986Sandreas.sandberg@arm.com } 22611986Sandreas.sandberg@arm.com 22712391Sjason@lowepower.com template <typename T> 22812391Sjason@lowepower.com static handle cast(T &&src, return_value_policy policy, handle parent) { 22911986Sandreas.sandberg@arm.com list l(src.size()); 23011986Sandreas.sandberg@arm.com size_t index = 0; 23112391Sjason@lowepower.com for (auto &&value : src) { 23212391Sjason@lowepower.com auto value_ = reinterpret_steal<object>(value_conv::cast(forward_like<T>(value), policy, parent)); 23311986Sandreas.sandberg@arm.com if (!value_) 23411986Sandreas.sandberg@arm.com return handle(); 23512037Sandreas.sandberg@arm.com PyList_SET_ITEM(l.ptr(), (ssize_t) index++, value_.release().ptr()); // steals a reference 23611986Sandreas.sandberg@arm.com } 23711986Sandreas.sandberg@arm.com return l.release(); 23811986Sandreas.sandberg@arm.com } 23911986Sandreas.sandberg@arm.com 24014299Sbbruce@ucdavis.edu PYBIND11_TYPE_CASTER(ArrayType, _("List[") + value_conv::name + _<Resizable>(_(""), _("[") + _<Size>() + _("]")) + _("]")); 24111986Sandreas.sandberg@arm.com}; 24211986Sandreas.sandberg@arm.com 24311986Sandreas.sandberg@arm.comtemplate <typename Type, size_t Size> struct type_caster<std::array<Type, Size>> 24411986Sandreas.sandberg@arm.com : array_caster<std::array<Type, Size>, Type, false, Size> { }; 24511986Sandreas.sandberg@arm.com 24611986Sandreas.sandberg@arm.comtemplate <typename Type> struct type_caster<std::valarray<Type>> 24711986Sandreas.sandberg@arm.com : array_caster<std::valarray<Type>, Type, true> { }; 24811986Sandreas.sandberg@arm.com 24911986Sandreas.sandberg@arm.comtemplate <typename Key, typename Compare, typename Alloc> struct type_caster<std::set<Key, Compare, Alloc>> 25011986Sandreas.sandberg@arm.com : set_caster<std::set<Key, Compare, Alloc>, Key> { }; 25111986Sandreas.sandberg@arm.com 25211986Sandreas.sandberg@arm.comtemplate <typename Key, typename Hash, typename Equal, typename Alloc> struct type_caster<std::unordered_set<Key, Hash, Equal, Alloc>> 25311986Sandreas.sandberg@arm.com : set_caster<std::unordered_set<Key, Hash, Equal, Alloc>, Key> { }; 25411986Sandreas.sandberg@arm.com 25511986Sandreas.sandberg@arm.comtemplate <typename Key, typename Value, typename Compare, typename Alloc> struct type_caster<std::map<Key, Value, Compare, Alloc>> 25611986Sandreas.sandberg@arm.com : map_caster<std::map<Key, Value, Compare, Alloc>, Key, Value> { }; 25711986Sandreas.sandberg@arm.com 25811986Sandreas.sandberg@arm.comtemplate <typename Key, typename Value, typename Hash, typename Equal, typename Alloc> struct type_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>> 25911986Sandreas.sandberg@arm.com : map_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>, Key, Value> { }; 26011986Sandreas.sandberg@arm.com 26111986Sandreas.sandberg@arm.com// This type caster is intended to be used for std::optional and std::experimental::optional 26211986Sandreas.sandberg@arm.comtemplate<typename T> struct optional_caster { 26311986Sandreas.sandberg@arm.com using value_conv = make_caster<typename T::value_type>; 26411986Sandreas.sandberg@arm.com 26512391Sjason@lowepower.com template <typename T_> 26612391Sjason@lowepower.com static handle cast(T_ &&src, return_value_policy policy, handle parent) { 26711986Sandreas.sandberg@arm.com if (!src) 26811986Sandreas.sandberg@arm.com return none().inc_ref(); 26914299Sbbruce@ucdavis.edu policy = return_value_policy_override<typename T::value_type>::policy(policy); 27012391Sjason@lowepower.com return value_conv::cast(*std::forward<T_>(src), policy, parent); 27111986Sandreas.sandberg@arm.com } 27211986Sandreas.sandberg@arm.com 27311986Sandreas.sandberg@arm.com bool load(handle src, bool convert) { 27411986Sandreas.sandberg@arm.com if (!src) { 27511986Sandreas.sandberg@arm.com return false; 27611986Sandreas.sandberg@arm.com } else if (src.is_none()) { 27712391Sjason@lowepower.com return true; // default-constructed value is already empty 27811986Sandreas.sandberg@arm.com } 27911986Sandreas.sandberg@arm.com value_conv inner_caster; 28011986Sandreas.sandberg@arm.com if (!inner_caster.load(src, convert)) 28111986Sandreas.sandberg@arm.com return false; 28211986Sandreas.sandberg@arm.com 28312391Sjason@lowepower.com value.emplace(cast_op<typename T::value_type &&>(std::move(inner_caster))); 28411986Sandreas.sandberg@arm.com return true; 28511986Sandreas.sandberg@arm.com } 28611986Sandreas.sandberg@arm.com 28714299Sbbruce@ucdavis.edu PYBIND11_TYPE_CASTER(T, _("Optional[") + value_conv::name + _("]")); 28811986Sandreas.sandberg@arm.com}; 28911986Sandreas.sandberg@arm.com 29011987Sandreas.sandberg@arm.com#ifdef PYBIND11_HAS_OPTIONAL 29111986Sandreas.sandberg@arm.comtemplate<typename T> struct type_caster<std::optional<T>> 29211986Sandreas.sandberg@arm.com : public optional_caster<std::optional<T>> {}; 29311986Sandreas.sandberg@arm.com 29411986Sandreas.sandberg@arm.comtemplate<> struct type_caster<std::nullopt_t> 29511986Sandreas.sandberg@arm.com : public void_caster<std::nullopt_t> {}; 29611986Sandreas.sandberg@arm.com#endif 29711986Sandreas.sandberg@arm.com 29811987Sandreas.sandberg@arm.com#ifdef PYBIND11_HAS_EXP_OPTIONAL 29911986Sandreas.sandberg@arm.comtemplate<typename T> struct type_caster<std::experimental::optional<T>> 30011986Sandreas.sandberg@arm.com : public optional_caster<std::experimental::optional<T>> {}; 30111986Sandreas.sandberg@arm.com 30211986Sandreas.sandberg@arm.comtemplate<> struct type_caster<std::experimental::nullopt_t> 30311986Sandreas.sandberg@arm.com : public void_caster<std::experimental::nullopt_t> {}; 30411986Sandreas.sandberg@arm.com#endif 30511986Sandreas.sandberg@arm.com 30612391Sjason@lowepower.com/// Visit a variant and cast any found type to Python 30712391Sjason@lowepower.comstruct variant_caster_visitor { 30812391Sjason@lowepower.com return_value_policy policy; 30912391Sjason@lowepower.com handle parent; 31012391Sjason@lowepower.com 31112391Sjason@lowepower.com using result_type = handle; // required by boost::variant in C++11 31212391Sjason@lowepower.com 31312391Sjason@lowepower.com template <typename T> 31412391Sjason@lowepower.com result_type operator()(T &&src) const { 31512391Sjason@lowepower.com return make_caster<T>::cast(std::forward<T>(src), policy, parent); 31612391Sjason@lowepower.com } 31712391Sjason@lowepower.com}; 31812391Sjason@lowepower.com 31912391Sjason@lowepower.com/// Helper class which abstracts away variant's `visit` function. `std::variant` and similar 32012391Sjason@lowepower.com/// `namespace::variant` types which provide a `namespace::visit()` function are handled here 32112391Sjason@lowepower.com/// automatically using argument-dependent lookup. Users can provide specializations for other 32212391Sjason@lowepower.com/// variant-like classes, e.g. `boost::variant` and `boost::apply_visitor`. 32312391Sjason@lowepower.comtemplate <template<typename...> class Variant> 32412391Sjason@lowepower.comstruct visit_helper { 32512391Sjason@lowepower.com template <typename... Args> 32612391Sjason@lowepower.com static auto call(Args &&...args) -> decltype(visit(std::forward<Args>(args)...)) { 32712391Sjason@lowepower.com return visit(std::forward<Args>(args)...); 32812391Sjason@lowepower.com } 32912391Sjason@lowepower.com}; 33012391Sjason@lowepower.com 33112391Sjason@lowepower.com/// Generic variant caster 33212391Sjason@lowepower.comtemplate <typename Variant> struct variant_caster; 33312391Sjason@lowepower.com 33412391Sjason@lowepower.comtemplate <template<typename...> class V, typename... Ts> 33512391Sjason@lowepower.comstruct variant_caster<V<Ts...>> { 33612391Sjason@lowepower.com static_assert(sizeof...(Ts) > 0, "Variant must consist of at least one alternative."); 33712391Sjason@lowepower.com 33812391Sjason@lowepower.com template <typename U, typename... Us> 33912391Sjason@lowepower.com bool load_alternative(handle src, bool convert, type_list<U, Us...>) { 34012391Sjason@lowepower.com auto caster = make_caster<U>(); 34112391Sjason@lowepower.com if (caster.load(src, convert)) { 34212391Sjason@lowepower.com value = cast_op<U>(caster); 34312391Sjason@lowepower.com return true; 34412391Sjason@lowepower.com } 34512391Sjason@lowepower.com return load_alternative(src, convert, type_list<Us...>{}); 34612391Sjason@lowepower.com } 34712391Sjason@lowepower.com 34812391Sjason@lowepower.com bool load_alternative(handle, bool, type_list<>) { return false; } 34912391Sjason@lowepower.com 35012391Sjason@lowepower.com bool load(handle src, bool convert) { 35112391Sjason@lowepower.com // Do a first pass without conversions to improve constructor resolution. 35212391Sjason@lowepower.com // E.g. `py::int_(1).cast<variant<double, int>>()` needs to fill the `int` 35312391Sjason@lowepower.com // slot of the variant. Without two-pass loading `double` would be filled 35412391Sjason@lowepower.com // because it appears first and a conversion is possible. 35512391Sjason@lowepower.com if (convert && load_alternative(src, false, type_list<Ts...>{})) 35612391Sjason@lowepower.com return true; 35712391Sjason@lowepower.com return load_alternative(src, convert, type_list<Ts...>{}); 35812391Sjason@lowepower.com } 35912391Sjason@lowepower.com 36012391Sjason@lowepower.com template <typename Variant> 36112391Sjason@lowepower.com static handle cast(Variant &&src, return_value_policy policy, handle parent) { 36212391Sjason@lowepower.com return visit_helper<V>::call(variant_caster_visitor{policy, parent}, 36312391Sjason@lowepower.com std::forward<Variant>(src)); 36412391Sjason@lowepower.com } 36512391Sjason@lowepower.com 36612391Sjason@lowepower.com using Type = V<Ts...>; 36714299Sbbruce@ucdavis.edu PYBIND11_TYPE_CASTER(Type, _("Union[") + detail::concat(make_caster<Ts>::name...) + _("]")); 36812391Sjason@lowepower.com}; 36912391Sjason@lowepower.com 37012391Sjason@lowepower.com#ifdef PYBIND11_HAS_VARIANT 37112391Sjason@lowepower.comtemplate <typename... Ts> 37212391Sjason@lowepower.comstruct type_caster<std::variant<Ts...>> : variant_caster<std::variant<Ts...>> { }; 37312391Sjason@lowepower.com#endif 37414299Sbbruce@ucdavis.edu 37511986Sandreas.sandberg@arm.comNAMESPACE_END(detail) 37611986Sandreas.sandberg@arm.com 37711986Sandreas.sandberg@arm.cominline std::ostream &operator<<(std::ostream &os, const handle &obj) { 37811986Sandreas.sandberg@arm.com os << (std::string) str(obj); 37911986Sandreas.sandberg@arm.com return os; 38011986Sandreas.sandberg@arm.com} 38111986Sandreas.sandberg@arm.com 38212391Sjason@lowepower.comNAMESPACE_END(PYBIND11_NAMESPACE) 38311986Sandreas.sandberg@arm.com 38411986Sandreas.sandberg@arm.com#if defined(_MSC_VER) 38511986Sandreas.sandberg@arm.com#pragma warning(pop) 38611986Sandreas.sandberg@arm.com#endif 387