stl.h revision 11987
1/* 2 pybind11/stl.h: Transparent conversion for STL data types 3 4 Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch> 5 6 All rights reserved. Use of this source code is governed by a 7 BSD-style license that can be found in the LICENSE file. 8*/ 9 10#pragma once 11 12#include "pybind11.h" 13#include <set> 14#include <unordered_set> 15#include <map> 16#include <unordered_map> 17#include <iostream> 18#include <list> 19#include <valarray> 20 21#if defined(_MSC_VER) 22#pragma warning(push) 23#pragma warning(disable: 4127) // warning C4127: Conditional expression is constant 24#endif 25 26#ifdef __has_include 27// std::optional (but including it in c++14 mode isn't allowed) 28# if defined(PYBIND11_CPP17) && __has_include(<optional>) 29# include <optional> 30# define PYBIND11_HAS_OPTIONAL 1 31# endif 32// std::experimental::optional (but not allowed in c++11 mode) 33# if defined(PYBIND11_CPP14) && __has_include(<experimental/optional>) 34# include <experimental/optional> 35# if __cpp_lib_experimental_optional // just in case 36# define PYBIND11_HAS_EXP_OPTIONAL 1 37# endif 38# endif 39#endif 40 41NAMESPACE_BEGIN(pybind11) 42NAMESPACE_BEGIN(detail) 43 44template <typename Type, typename Key> struct set_caster { 45 using type = Type; 46 using key_conv = make_caster<Key>; 47 48 bool load(handle src, bool convert) { 49 if (!isinstance<pybind11::set>(src)) 50 return false; 51 auto s = reinterpret_borrow<pybind11::set>(src); 52 value.clear(); 53 key_conv conv; 54 for (auto entry : s) { 55 if (!conv.load(entry, convert)) 56 return false; 57 value.insert(cast_op<Key>(conv)); 58 } 59 return true; 60 } 61 62 static handle cast(const type &src, return_value_policy policy, handle parent) { 63 pybind11::set s; 64 for (auto const &value: src) { 65 auto value_ = reinterpret_steal<object>(key_conv::cast(value, policy, parent)); 66 if (!value_ || !s.add(value_)) 67 return handle(); 68 } 69 return s.release(); 70 } 71 72 PYBIND11_TYPE_CASTER(type, _("Set[") + key_conv::name() + _("]")); 73}; 74 75template <typename Type, typename Key, typename Value> struct map_caster { 76 using key_conv = make_caster<Key>; 77 using value_conv = make_caster<Value>; 78 79 bool load(handle src, bool convert) { 80 if (!isinstance<dict>(src)) 81 return false; 82 auto d = reinterpret_borrow<dict>(src); 83 key_conv kconv; 84 value_conv vconv; 85 value.clear(); 86 for (auto it : d) { 87 if (!kconv.load(it.first.ptr(), convert) || 88 !vconv.load(it.second.ptr(), convert)) 89 return false; 90 value.emplace(cast_op<Key>(kconv), cast_op<Value>(vconv)); 91 } 92 return true; 93 } 94 95 static handle cast(const Type &src, return_value_policy policy, handle parent) { 96 dict d; 97 for (auto const &kv: src) { 98 auto key = reinterpret_steal<object>(key_conv::cast(kv.first, policy, parent)); 99 auto value = reinterpret_steal<object>(value_conv::cast(kv.second, policy, parent)); 100 if (!key || !value) 101 return handle(); 102 d[key] = value; 103 } 104 return d.release(); 105 } 106 107 PYBIND11_TYPE_CASTER(Type, _("Dict[") + key_conv::name() + _(", ") + value_conv::name() + _("]")); 108}; 109 110template <typename Type, typename Value> struct list_caster { 111 using value_conv = make_caster<Value>; 112 113 bool load(handle src, bool convert) { 114 if (!isinstance<sequence>(src)) 115 return false; 116 auto s = reinterpret_borrow<sequence>(src); 117 value_conv conv; 118 value.clear(); 119 reserve_maybe(s, &value); 120 for (auto it : s) { 121 if (!conv.load(it, convert)) 122 return false; 123 value.push_back(cast_op<Value>(conv)); 124 } 125 return true; 126 } 127 128private: 129 template <typename T = Type, 130 enable_if_t<std::is_same<decltype(std::declval<T>().reserve(0)), void>::value, int> = 0> 131 void reserve_maybe(sequence s, Type *) { value.reserve(s.size()); } 132 void reserve_maybe(sequence, void *) { } 133 134public: 135 static handle cast(const Type &src, return_value_policy policy, handle parent) { 136 list l(src.size()); 137 size_t index = 0; 138 for (auto const &value: src) { 139 auto value_ = reinterpret_steal<object>(value_conv::cast(value, policy, parent)); 140 if (!value_) 141 return handle(); 142 PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference 143 } 144 return l.release(); 145 } 146 147 PYBIND11_TYPE_CASTER(Type, _("List[") + value_conv::name() + _("]")); 148}; 149 150template <typename Type, typename Alloc> struct type_caster<std::vector<Type, Alloc>> 151 : list_caster<std::vector<Type, Alloc>, Type> { }; 152 153template <typename Type, typename Alloc> struct type_caster<std::list<Type, Alloc>> 154 : list_caster<std::list<Type, Alloc>, Type> { }; 155 156template <typename ArrayType, typename Value, bool Resizable, size_t Size = 0> struct array_caster { 157 using value_conv = make_caster<Value>; 158 159private: 160 template <bool R = Resizable> 161 bool require_size(enable_if_t<R, size_t> size) { 162 if (value.size() != size) 163 value.resize(size); 164 return true; 165 } 166 template <bool R = Resizable> 167 bool require_size(enable_if_t<!R, size_t> size) { 168 return size == Size; 169 } 170 171public: 172 bool load(handle src, bool convert) { 173 if (!isinstance<list>(src)) 174 return false; 175 auto l = reinterpret_borrow<list>(src); 176 if (!require_size(l.size())) 177 return false; 178 value_conv conv; 179 size_t ctr = 0; 180 for (auto it : l) { 181 if (!conv.load(it, convert)) 182 return false; 183 value[ctr++] = cast_op<Value>(conv); 184 } 185 return true; 186 } 187 188 static handle cast(const ArrayType &src, return_value_policy policy, handle parent) { 189 list l(src.size()); 190 size_t index = 0; 191 for (auto const &value: src) { 192 auto value_ = reinterpret_steal<object>(value_conv::cast(value, policy, parent)); 193 if (!value_) 194 return handle(); 195 PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference 196 } 197 return l.release(); 198 } 199 200 PYBIND11_TYPE_CASTER(ArrayType, _("List[") + value_conv::name() + _<Resizable>(_(""), _("[") + _<Size>() + _("]")) + _("]")); 201}; 202 203template <typename Type, size_t Size> struct type_caster<std::array<Type, Size>> 204 : array_caster<std::array<Type, Size>, Type, false, Size> { }; 205 206template <typename Type> struct type_caster<std::valarray<Type>> 207 : array_caster<std::valarray<Type>, Type, true> { }; 208 209template <typename Key, typename Compare, typename Alloc> struct type_caster<std::set<Key, Compare, Alloc>> 210 : set_caster<std::set<Key, Compare, Alloc>, Key> { }; 211 212template <typename Key, typename Hash, typename Equal, typename Alloc> struct type_caster<std::unordered_set<Key, Hash, Equal, Alloc>> 213 : set_caster<std::unordered_set<Key, Hash, Equal, Alloc>, Key> { }; 214 215template <typename Key, typename Value, typename Compare, typename Alloc> struct type_caster<std::map<Key, Value, Compare, Alloc>> 216 : map_caster<std::map<Key, Value, Compare, Alloc>, Key, Value> { }; 217 218template <typename Key, typename Value, typename Hash, typename Equal, typename Alloc> struct type_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>> 219 : map_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>, Key, Value> { }; 220 221// This type caster is intended to be used for std::optional and std::experimental::optional 222template<typename T> struct optional_caster { 223 using value_conv = make_caster<typename T::value_type>; 224 225 static handle cast(const T& src, return_value_policy policy, handle parent) { 226 if (!src) 227 return none().inc_ref(); 228 return value_conv::cast(*src, policy, parent); 229 } 230 231 bool load(handle src, bool convert) { 232 if (!src) { 233 return false; 234 } else if (src.is_none()) { 235 value = {}; // nullopt 236 return true; 237 } 238 value_conv inner_caster; 239 if (!inner_caster.load(src, convert)) 240 return false; 241 242 value.emplace(cast_op<typename T::value_type>(inner_caster)); 243 return true; 244 } 245 246 PYBIND11_TYPE_CASTER(T, _("Optional[") + value_conv::name() + _("]")); 247}; 248 249#ifdef PYBIND11_HAS_OPTIONAL 250template<typename T> struct type_caster<std::optional<T>> 251 : public optional_caster<std::optional<T>> {}; 252 253template<> struct type_caster<std::nullopt_t> 254 : public void_caster<std::nullopt_t> {}; 255#endif 256 257#ifdef PYBIND11_HAS_EXP_OPTIONAL 258template<typename T> struct type_caster<std::experimental::optional<T>> 259 : public optional_caster<std::experimental::optional<T>> {}; 260 261template<> struct type_caster<std::experimental::nullopt_t> 262 : public void_caster<std::experimental::nullopt_t> {}; 263#endif 264 265NAMESPACE_END(detail) 266 267inline std::ostream &operator<<(std::ostream &os, const handle &obj) { 268 os << (std::string) str(obj); 269 return os; 270} 271 272NAMESPACE_END(pybind11) 273 274#if defined(_MSC_VER) 275#pragma warning(pop) 276#endif 277