stl.h revision 11987
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> 3511986Sandreas.sandberg@arm.com# if __cpp_lib_experimental_optional // just in case 3611986Sandreas.sandberg@arm.com# define PYBIND11_HAS_EXP_OPTIONAL 1 3711986Sandreas.sandberg@arm.com# endif 3811986Sandreas.sandberg@arm.com# endif 3911986Sandreas.sandberg@arm.com#endif 4011986Sandreas.sandberg@arm.com 4111986Sandreas.sandberg@arm.comNAMESPACE_BEGIN(pybind11) 4211986Sandreas.sandberg@arm.comNAMESPACE_BEGIN(detail) 4311986Sandreas.sandberg@arm.com 4411986Sandreas.sandberg@arm.comtemplate <typename Type, typename Key> struct set_caster { 4511986Sandreas.sandberg@arm.com using type = Type; 4611986Sandreas.sandberg@arm.com using key_conv = make_caster<Key>; 4711986Sandreas.sandberg@arm.com 4811986Sandreas.sandberg@arm.com bool load(handle src, bool convert) { 4911986Sandreas.sandberg@arm.com if (!isinstance<pybind11::set>(src)) 5011986Sandreas.sandberg@arm.com return false; 5111986Sandreas.sandberg@arm.com auto s = reinterpret_borrow<pybind11::set>(src); 5211986Sandreas.sandberg@arm.com value.clear(); 5311986Sandreas.sandberg@arm.com key_conv conv; 5411986Sandreas.sandberg@arm.com for (auto entry : s) { 5511986Sandreas.sandberg@arm.com if (!conv.load(entry, convert)) 5611986Sandreas.sandberg@arm.com return false; 5711986Sandreas.sandberg@arm.com value.insert(cast_op<Key>(conv)); 5811986Sandreas.sandberg@arm.com } 5911986Sandreas.sandberg@arm.com return true; 6011986Sandreas.sandberg@arm.com } 6111986Sandreas.sandberg@arm.com 6211986Sandreas.sandberg@arm.com static handle cast(const type &src, return_value_policy policy, handle parent) { 6311986Sandreas.sandberg@arm.com pybind11::set s; 6411986Sandreas.sandberg@arm.com for (auto const &value: src) { 6511986Sandreas.sandberg@arm.com auto value_ = reinterpret_steal<object>(key_conv::cast(value, policy, parent)); 6611986Sandreas.sandberg@arm.com if (!value_ || !s.add(value_)) 6711986Sandreas.sandberg@arm.com return handle(); 6811986Sandreas.sandberg@arm.com } 6911986Sandreas.sandberg@arm.com return s.release(); 7011986Sandreas.sandberg@arm.com } 7111986Sandreas.sandberg@arm.com 7211986Sandreas.sandberg@arm.com PYBIND11_TYPE_CASTER(type, _("Set[") + key_conv::name() + _("]")); 7311986Sandreas.sandberg@arm.com}; 7411986Sandreas.sandberg@arm.com 7511986Sandreas.sandberg@arm.comtemplate <typename Type, typename Key, typename Value> struct map_caster { 7611986Sandreas.sandberg@arm.com using key_conv = make_caster<Key>; 7711986Sandreas.sandberg@arm.com using value_conv = make_caster<Value>; 7811986Sandreas.sandberg@arm.com 7911986Sandreas.sandberg@arm.com bool load(handle src, bool convert) { 8011986Sandreas.sandberg@arm.com if (!isinstance<dict>(src)) 8111986Sandreas.sandberg@arm.com return false; 8211986Sandreas.sandberg@arm.com auto d = reinterpret_borrow<dict>(src); 8311986Sandreas.sandberg@arm.com key_conv kconv; 8411986Sandreas.sandberg@arm.com value_conv vconv; 8511986Sandreas.sandberg@arm.com value.clear(); 8611986Sandreas.sandberg@arm.com for (auto it : d) { 8711986Sandreas.sandberg@arm.com if (!kconv.load(it.first.ptr(), convert) || 8811986Sandreas.sandberg@arm.com !vconv.load(it.second.ptr(), convert)) 8911986Sandreas.sandberg@arm.com return false; 9011986Sandreas.sandberg@arm.com value.emplace(cast_op<Key>(kconv), cast_op<Value>(vconv)); 9111986Sandreas.sandberg@arm.com } 9211986Sandreas.sandberg@arm.com return true; 9311986Sandreas.sandberg@arm.com } 9411986Sandreas.sandberg@arm.com 9511986Sandreas.sandberg@arm.com static handle cast(const Type &src, return_value_policy policy, handle parent) { 9611986Sandreas.sandberg@arm.com dict d; 9711986Sandreas.sandberg@arm.com for (auto const &kv: src) { 9811986Sandreas.sandberg@arm.com auto key = reinterpret_steal<object>(key_conv::cast(kv.first, policy, parent)); 9911986Sandreas.sandberg@arm.com auto value = reinterpret_steal<object>(value_conv::cast(kv.second, policy, parent)); 10011986Sandreas.sandberg@arm.com if (!key || !value) 10111986Sandreas.sandberg@arm.com return handle(); 10211986Sandreas.sandberg@arm.com d[key] = value; 10311986Sandreas.sandberg@arm.com } 10411986Sandreas.sandberg@arm.com return d.release(); 10511986Sandreas.sandberg@arm.com } 10611986Sandreas.sandberg@arm.com 10711986Sandreas.sandberg@arm.com PYBIND11_TYPE_CASTER(Type, _("Dict[") + key_conv::name() + _(", ") + value_conv::name() + _("]")); 10811986Sandreas.sandberg@arm.com}; 10911986Sandreas.sandberg@arm.com 11011986Sandreas.sandberg@arm.comtemplate <typename Type, typename Value> struct list_caster { 11111986Sandreas.sandberg@arm.com using value_conv = make_caster<Value>; 11211986Sandreas.sandberg@arm.com 11311986Sandreas.sandberg@arm.com bool load(handle src, bool convert) { 11411986Sandreas.sandberg@arm.com if (!isinstance<sequence>(src)) 11511986Sandreas.sandberg@arm.com return false; 11611986Sandreas.sandberg@arm.com auto s = reinterpret_borrow<sequence>(src); 11711986Sandreas.sandberg@arm.com value_conv conv; 11811986Sandreas.sandberg@arm.com value.clear(); 11911986Sandreas.sandberg@arm.com reserve_maybe(s, &value); 12011986Sandreas.sandberg@arm.com for (auto it : s) { 12111986Sandreas.sandberg@arm.com if (!conv.load(it, convert)) 12211986Sandreas.sandberg@arm.com return false; 12311986Sandreas.sandberg@arm.com value.push_back(cast_op<Value>(conv)); 12411986Sandreas.sandberg@arm.com } 12511986Sandreas.sandberg@arm.com return true; 12611986Sandreas.sandberg@arm.com } 12711986Sandreas.sandberg@arm.com 12811986Sandreas.sandberg@arm.comprivate: 12911986Sandreas.sandberg@arm.com template <typename T = Type, 13011986Sandreas.sandberg@arm.com enable_if_t<std::is_same<decltype(std::declval<T>().reserve(0)), void>::value, int> = 0> 13111986Sandreas.sandberg@arm.com void reserve_maybe(sequence s, Type *) { value.reserve(s.size()); } 13211986Sandreas.sandberg@arm.com void reserve_maybe(sequence, void *) { } 13311986Sandreas.sandberg@arm.com 13411986Sandreas.sandberg@arm.compublic: 13511986Sandreas.sandberg@arm.com static handle cast(const Type &src, return_value_policy policy, handle parent) { 13611986Sandreas.sandberg@arm.com list l(src.size()); 13711986Sandreas.sandberg@arm.com size_t index = 0; 13811986Sandreas.sandberg@arm.com for (auto const &value: src) { 13911986Sandreas.sandberg@arm.com auto value_ = reinterpret_steal<object>(value_conv::cast(value, policy, parent)); 14011986Sandreas.sandberg@arm.com if (!value_) 14111986Sandreas.sandberg@arm.com return handle(); 14211986Sandreas.sandberg@arm.com PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference 14311986Sandreas.sandberg@arm.com } 14411986Sandreas.sandberg@arm.com return l.release(); 14511986Sandreas.sandberg@arm.com } 14611986Sandreas.sandberg@arm.com 14711986Sandreas.sandberg@arm.com PYBIND11_TYPE_CASTER(Type, _("List[") + value_conv::name() + _("]")); 14811986Sandreas.sandberg@arm.com}; 14911986Sandreas.sandberg@arm.com 15011986Sandreas.sandberg@arm.comtemplate <typename Type, typename Alloc> struct type_caster<std::vector<Type, Alloc>> 15111986Sandreas.sandberg@arm.com : list_caster<std::vector<Type, Alloc>, Type> { }; 15211986Sandreas.sandberg@arm.com 15311986Sandreas.sandberg@arm.comtemplate <typename Type, typename Alloc> struct type_caster<std::list<Type, Alloc>> 15411986Sandreas.sandberg@arm.com : list_caster<std::list<Type, Alloc>, Type> { }; 15511986Sandreas.sandberg@arm.com 15611986Sandreas.sandberg@arm.comtemplate <typename ArrayType, typename Value, bool Resizable, size_t Size = 0> struct array_caster { 15711986Sandreas.sandberg@arm.com using value_conv = make_caster<Value>; 15811986Sandreas.sandberg@arm.com 15911986Sandreas.sandberg@arm.comprivate: 16011986Sandreas.sandberg@arm.com template <bool R = Resizable> 16111986Sandreas.sandberg@arm.com bool require_size(enable_if_t<R, size_t> size) { 16211986Sandreas.sandberg@arm.com if (value.size() != size) 16311986Sandreas.sandberg@arm.com value.resize(size); 16411986Sandreas.sandberg@arm.com return true; 16511986Sandreas.sandberg@arm.com } 16611986Sandreas.sandberg@arm.com template <bool R = Resizable> 16711986Sandreas.sandberg@arm.com bool require_size(enable_if_t<!R, size_t> size) { 16811986Sandreas.sandberg@arm.com return size == Size; 16911986Sandreas.sandberg@arm.com } 17011986Sandreas.sandberg@arm.com 17111986Sandreas.sandberg@arm.compublic: 17211986Sandreas.sandberg@arm.com bool load(handle src, bool convert) { 17311986Sandreas.sandberg@arm.com if (!isinstance<list>(src)) 17411986Sandreas.sandberg@arm.com return false; 17511986Sandreas.sandberg@arm.com auto l = reinterpret_borrow<list>(src); 17611986Sandreas.sandberg@arm.com if (!require_size(l.size())) 17711986Sandreas.sandberg@arm.com return false; 17811986Sandreas.sandberg@arm.com value_conv conv; 17911986Sandreas.sandberg@arm.com size_t ctr = 0; 18011986Sandreas.sandberg@arm.com for (auto it : l) { 18111986Sandreas.sandberg@arm.com if (!conv.load(it, convert)) 18211986Sandreas.sandberg@arm.com return false; 18311986Sandreas.sandberg@arm.com value[ctr++] = cast_op<Value>(conv); 18411986Sandreas.sandberg@arm.com } 18511986Sandreas.sandberg@arm.com return true; 18611986Sandreas.sandberg@arm.com } 18711986Sandreas.sandberg@arm.com 18811986Sandreas.sandberg@arm.com static handle cast(const ArrayType &src, return_value_policy policy, handle parent) { 18911986Sandreas.sandberg@arm.com list l(src.size()); 19011986Sandreas.sandberg@arm.com size_t index = 0; 19111986Sandreas.sandberg@arm.com for (auto const &value: src) { 19211986Sandreas.sandberg@arm.com auto value_ = reinterpret_steal<object>(value_conv::cast(value, policy, parent)); 19311986Sandreas.sandberg@arm.com if (!value_) 19411986Sandreas.sandberg@arm.com return handle(); 19511986Sandreas.sandberg@arm.com PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference 19611986Sandreas.sandberg@arm.com } 19711986Sandreas.sandberg@arm.com return l.release(); 19811986Sandreas.sandberg@arm.com } 19911986Sandreas.sandberg@arm.com 20011986Sandreas.sandberg@arm.com PYBIND11_TYPE_CASTER(ArrayType, _("List[") + value_conv::name() + _<Resizable>(_(""), _("[") + _<Size>() + _("]")) + _("]")); 20111986Sandreas.sandberg@arm.com}; 20211986Sandreas.sandberg@arm.com 20311986Sandreas.sandberg@arm.comtemplate <typename Type, size_t Size> struct type_caster<std::array<Type, Size>> 20411986Sandreas.sandberg@arm.com : array_caster<std::array<Type, Size>, Type, false, Size> { }; 20511986Sandreas.sandberg@arm.com 20611986Sandreas.sandberg@arm.comtemplate <typename Type> struct type_caster<std::valarray<Type>> 20711986Sandreas.sandberg@arm.com : array_caster<std::valarray<Type>, Type, true> { }; 20811986Sandreas.sandberg@arm.com 20911986Sandreas.sandberg@arm.comtemplate <typename Key, typename Compare, typename Alloc> struct type_caster<std::set<Key, Compare, Alloc>> 21011986Sandreas.sandberg@arm.com : set_caster<std::set<Key, Compare, Alloc>, Key> { }; 21111986Sandreas.sandberg@arm.com 21211986Sandreas.sandberg@arm.comtemplate <typename Key, typename Hash, typename Equal, typename Alloc> struct type_caster<std::unordered_set<Key, Hash, Equal, Alloc>> 21311986Sandreas.sandberg@arm.com : set_caster<std::unordered_set<Key, Hash, Equal, Alloc>, Key> { }; 21411986Sandreas.sandberg@arm.com 21511986Sandreas.sandberg@arm.comtemplate <typename Key, typename Value, typename Compare, typename Alloc> struct type_caster<std::map<Key, Value, Compare, Alloc>> 21611986Sandreas.sandberg@arm.com : map_caster<std::map<Key, Value, Compare, Alloc>, Key, Value> { }; 21711986Sandreas.sandberg@arm.com 21811986Sandreas.sandberg@arm.comtemplate <typename Key, typename Value, typename Hash, typename Equal, typename Alloc> struct type_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>> 21911986Sandreas.sandberg@arm.com : map_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>, Key, Value> { }; 22011986Sandreas.sandberg@arm.com 22111986Sandreas.sandberg@arm.com// This type caster is intended to be used for std::optional and std::experimental::optional 22211986Sandreas.sandberg@arm.comtemplate<typename T> struct optional_caster { 22311986Sandreas.sandberg@arm.com using value_conv = make_caster<typename T::value_type>; 22411986Sandreas.sandberg@arm.com 22511986Sandreas.sandberg@arm.com static handle cast(const T& src, return_value_policy policy, handle parent) { 22611986Sandreas.sandberg@arm.com if (!src) 22711986Sandreas.sandberg@arm.com return none().inc_ref(); 22811986Sandreas.sandberg@arm.com return value_conv::cast(*src, policy, parent); 22911986Sandreas.sandberg@arm.com } 23011986Sandreas.sandberg@arm.com 23111986Sandreas.sandberg@arm.com bool load(handle src, bool convert) { 23211986Sandreas.sandberg@arm.com if (!src) { 23311986Sandreas.sandberg@arm.com return false; 23411986Sandreas.sandberg@arm.com } else if (src.is_none()) { 23511986Sandreas.sandberg@arm.com value = {}; // nullopt 23611986Sandreas.sandberg@arm.com return true; 23711986Sandreas.sandberg@arm.com } 23811986Sandreas.sandberg@arm.com value_conv inner_caster; 23911986Sandreas.sandberg@arm.com if (!inner_caster.load(src, convert)) 24011986Sandreas.sandberg@arm.com return false; 24111986Sandreas.sandberg@arm.com 24211986Sandreas.sandberg@arm.com value.emplace(cast_op<typename T::value_type>(inner_caster)); 24311986Sandreas.sandberg@arm.com return true; 24411986Sandreas.sandberg@arm.com } 24511986Sandreas.sandberg@arm.com 24611986Sandreas.sandberg@arm.com PYBIND11_TYPE_CASTER(T, _("Optional[") + value_conv::name() + _("]")); 24711986Sandreas.sandberg@arm.com}; 24811986Sandreas.sandberg@arm.com 24911987Sandreas.sandberg@arm.com#ifdef PYBIND11_HAS_OPTIONAL 25011986Sandreas.sandberg@arm.comtemplate<typename T> struct type_caster<std::optional<T>> 25111986Sandreas.sandberg@arm.com : public optional_caster<std::optional<T>> {}; 25211986Sandreas.sandberg@arm.com 25311986Sandreas.sandberg@arm.comtemplate<> struct type_caster<std::nullopt_t> 25411986Sandreas.sandberg@arm.com : public void_caster<std::nullopt_t> {}; 25511986Sandreas.sandberg@arm.com#endif 25611986Sandreas.sandberg@arm.com 25711987Sandreas.sandberg@arm.com#ifdef PYBIND11_HAS_EXP_OPTIONAL 25811986Sandreas.sandberg@arm.comtemplate<typename T> struct type_caster<std::experimental::optional<T>> 25911986Sandreas.sandberg@arm.com : public optional_caster<std::experimental::optional<T>> {}; 26011986Sandreas.sandberg@arm.com 26111986Sandreas.sandberg@arm.comtemplate<> struct type_caster<std::experimental::nullopt_t> 26211986Sandreas.sandberg@arm.com : public void_caster<std::experimental::nullopt_t> {}; 26311986Sandreas.sandberg@arm.com#endif 26411986Sandreas.sandberg@arm.com 26511986Sandreas.sandberg@arm.comNAMESPACE_END(detail) 26611986Sandreas.sandberg@arm.com 26711986Sandreas.sandberg@arm.cominline std::ostream &operator<<(std::ostream &os, const handle &obj) { 26811986Sandreas.sandberg@arm.com os << (std::string) str(obj); 26911986Sandreas.sandberg@arm.com return os; 27011986Sandreas.sandberg@arm.com} 27111986Sandreas.sandberg@arm.com 27211986Sandreas.sandberg@arm.comNAMESPACE_END(pybind11) 27311986Sandreas.sandberg@arm.com 27411986Sandreas.sandberg@arm.com#if defined(_MSC_VER) 27511986Sandreas.sandberg@arm.com#pragma warning(pop) 27611986Sandreas.sandberg@arm.com#endif 277