Scarab  v2.9.1
Project 8 C++ Utility Library
stl.h
Go to the documentation of this file.
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 <deque>
20 #include <valarray>
21 
22 #if defined(_MSC_VER)
23 #pragma warning(push)
24 #pragma warning(disable: 4127) // warning C4127: Conditional expression is constant
25 #endif
26 
27 #ifdef __has_include
28 // std::optional (but including it in c++14 mode isn't allowed)
29 # if defined(PYBIND11_CPP17) && __has_include(<optional>)
30 # include <optional>
31 # define PYBIND11_HAS_OPTIONAL 1
32 # endif
33 // std::experimental::optional (but not allowed in c++11 mode)
34 # if defined(PYBIND11_CPP14) && (__has_include(<experimental/optional>) && \
35  !__has_include(<optional>))
36 # include <experimental/optional>
37 # define PYBIND11_HAS_EXP_OPTIONAL 1
38 # endif
39 // std::variant
40 # if defined(PYBIND11_CPP17) && __has_include(<variant>)
41 # include <variant>
42 # define PYBIND11_HAS_VARIANT 1
43 # endif
44 #elif defined(_MSC_VER) && defined(PYBIND11_CPP17)
45 # include <optional>
46 # include <variant>
47 # define PYBIND11_HAS_OPTIONAL 1
48 # define PYBIND11_HAS_VARIANT 1
49 #endif
50 
52 NAMESPACE_BEGIN(detail)
53 
54 template <typename T, typename U>
59 
62 template <typename T, typename U>
64  return std::forward<detail::forwarded_type<T, U>>(std::forward<U>(u));
65 }
66 
67 template <typename Type, typename Key> struct set_caster {
68  using type = Type;
70 
71  bool load(handle src, bool convert) {
72  if (!isinstance<pybind11::set>(src))
73  return false;
74  auto s = reinterpret_borrow<pybind11::set>(src);
75  value.clear();
76  for (auto entry : s) {
77  key_conv conv;
78  if (!conv.load(entry, convert))
79  return false;
80  value.insert(cast_op<Key &&>(std::move(conv)));
81  }
82  return true;
83  }
84 
85  template <typename T>
86  static handle cast(T &&src, return_value_policy policy, handle parent) {
89  pybind11::set s;
90  for (auto &&value : src) {
91  auto value_ = reinterpret_steal<object>(key_conv::cast(forward_like<T>(value), policy, parent));
92  if (!value_ || !s.add(value_))
93  return handle();
94  }
95  return s.release();
96  }
97 
98  PYBIND11_TYPE_CASTER(type, _("Set[") + key_conv::name + _("]"));
99 };
100 
101 template <typename Type, typename Key, typename Value> struct map_caster {
104 
105  bool load(handle src, bool convert) {
106  if (!isinstance<dict>(src))
107  return false;
108  auto d = reinterpret_borrow<dict>(src);
109  value.clear();
110  for (auto it : d) {
111  key_conv kconv;
112  value_conv vconv;
113  if (!kconv.load(it.first.ptr(), convert) ||
114  !vconv.load(it.second.ptr(), convert))
115  return false;
116  value.emplace(cast_op<Key &&>(std::move(kconv)), cast_op<Value &&>(std::move(vconv)));
117  }
118  return true;
119  }
120 
121  template <typename T>
122  static handle cast(T &&src, return_value_policy policy, handle parent) {
123  dict d;
124  return_value_policy policy_key = policy;
125  return_value_policy policy_value = policy;
127  policy_key = return_value_policy_override<Key>::policy(policy_key);
128  policy_value = return_value_policy_override<Value>::policy(policy_value);
129  }
130  for (auto &&kv : src) {
131  auto key = reinterpret_steal<object>(key_conv::cast(forward_like<T>(kv.first), policy_key, parent));
132  auto value = reinterpret_steal<object>(value_conv::cast(forward_like<T>(kv.second), policy_value, parent));
133  if (!key || !value)
134  return handle();
135  d[key] = value;
136  }
137  return d.release();
138  }
139 
140  PYBIND11_TYPE_CASTER(Type, _("Dict[") + key_conv::name + _(", ") + value_conv::name + _("]"));
141 };
142 
143 template <typename Type, typename Value> struct list_caster {
145 
146  bool load(handle src, bool convert) {
147  if (!isinstance<sequence>(src) || isinstance<str>(src))
148  return false;
149  auto s = reinterpret_borrow<sequence>(src);
150  value.clear();
151  reserve_maybe(s, &value);
152  for (auto it : s) {
153  value_conv conv;
154  if (!conv.load(it, convert))
155  return false;
156  value.push_back(cast_op<Value &&>(std::move(conv)));
157  }
158  return true;
159  }
160 
161 private:
162  template <typename T = Type,
163  enable_if_t<std::is_same<decltype(std::declval<T>().reserve(0)), void>::value, int> = 0>
164  void reserve_maybe(sequence s, Type *) { value.reserve(s.size()); }
165  void reserve_maybe(sequence, void *) { }
166 
167 public:
168  template <typename T>
169  static handle cast(T &&src, return_value_policy policy, handle parent) {
172  list l(src.size());
173  size_t index = 0;
174  for (auto &&value : src) {
175  auto value_ = reinterpret_steal<object>(value_conv::cast(forward_like<T>(value), policy, parent));
176  if (!value_)
177  return handle();
178  PyList_SET_ITEM(l.ptr(), (ssize_t) index++, value_.release().ptr()); // steals a reference
179  }
180  return l.release();
181  }
182 
183  PYBIND11_TYPE_CASTER(Type, _("List[") + value_conv::name + _("]"));
184 };
185 
186 template <typename Type, typename Alloc> struct type_caster<std::vector<Type, Alloc>>
188 
189 template <typename Type, typename Alloc> struct type_caster<std::deque<Type, Alloc>>
190  : list_caster<std::deque<Type, Alloc>, Type> { };
191 
192 template <typename Type, typename Alloc> struct type_caster<std::list<Type, Alloc>>
193  : list_caster<std::list<Type, Alloc>, Type> { };
194 
195 template <typename ArrayType, typename Value, bool Resizable, size_t Size = 0> struct array_caster {
197 
198 private:
199  template <bool R = Resizable>
201  if (value.size() != size)
202  value.resize(size);
203  return true;
204  }
205  template <bool R = Resizable>
207  return size == Size;
208  }
209 
210 public:
211  bool load(handle src, bool convert) {
212  if (!isinstance<sequence>(src))
213  return false;
214  auto l = reinterpret_borrow<sequence>(src);
215  if (!require_size(l.size()))
216  return false;
217  size_t ctr = 0;
218  for (auto it : l) {
219  value_conv conv;
220  if (!conv.load(it, convert))
221  return false;
222  value[ctr++] = cast_op<Value &&>(std::move(conv));
223  }
224  return true;
225  }
226 
227  template <typename T>
228  static handle cast(T &&src, return_value_policy policy, handle parent) {
229  list l(src.size());
230  size_t index = 0;
231  for (auto &&value : src) {
232  auto value_ = reinterpret_steal<object>(value_conv::cast(forward_like<T>(value), policy, parent));
233  if (!value_)
234  return handle();
235  PyList_SET_ITEM(l.ptr(), (ssize_t) index++, value_.release().ptr()); // steals a reference
236  }
237  return l.release();
238  }
239 
240  PYBIND11_TYPE_CASTER(ArrayType, _("List[") + value_conv::name + _<Resizable>(_(""), _("[") + _<Size>() + _("]")) + _("]"));
241 };
242 
243 template <typename Type, size_t Size> struct type_caster<std::array<Type, Size>>
244  : array_caster<std::array<Type, Size>, Type, false, Size> { };
245 
246 template <typename Type> struct type_caster<std::valarray<Type>>
247  : array_caster<std::valarray<Type>, Type, true> { };
248 
249 template <typename Key, typename Compare, typename Alloc> struct type_caster<std::set<Key, Compare, Alloc>>
250  : set_caster<std::set<Key, Compare, Alloc>, Key> { };
251 
252 template <typename Key, typename Hash, typename Equal, typename Alloc> struct type_caster<std::unordered_set<Key, Hash, Equal, Alloc>>
253  : set_caster<std::unordered_set<Key, Hash, Equal, Alloc>, Key> { };
254 
255 template <typename Key, typename Value, typename Compare, typename Alloc> struct type_caster<std::map<Key, Value, Compare, Alloc>>
256  : map_caster<std::map<Key, Value, Compare, Alloc>, Key, Value> { };
257 
258 template <typename Key, typename Value, typename Hash, typename Equal, typename Alloc> struct type_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>>
259  : map_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>, Key, Value> { };
260 
261 // This type caster is intended to be used for std::optional and std::experimental::optional
262 template<typename T> struct optional_caster {
264 
265  template <typename T_>
266  static handle cast(T_ &&src, return_value_policy policy, handle parent) {
267  if (!src)
268  return none().inc_ref();
270  return value_conv::cast(*std::forward<T_>(src), policy, parent);
271  }
272 
273  bool load(handle src, bool convert) {
274  if (!src) {
275  return false;
276  } else if (src.is_none()) {
277  return true; // default-constructed value is already empty
278  }
279  value_conv inner_caster;
280  if (!inner_caster.load(src, convert))
281  return false;
282 
283  value.emplace(cast_op<typename T::value_type &&>(std::move(inner_caster)));
284  return true;
285  }
286 
287  PYBIND11_TYPE_CASTER(T, _("Optional[") + value_conv::name + _("]"));
288 };
289 
290 #if PYBIND11_HAS_OPTIONAL
291 template<typename T> struct type_caster<std::optional<T>>
292  : public optional_caster<std::optional<T>> {};
293 
294 template<> struct type_caster<std::nullopt_t>
295  : public void_caster<std::nullopt_t> {};
296 #endif
297 
298 #if PYBIND11_HAS_EXP_OPTIONAL
299 template<typename T> struct type_caster<std::experimental::optional<T>>
300  : public optional_caster<std::experimental::optional<T>> {};
301 
302 template<> struct type_caster<std::experimental::nullopt_t>
303  : public void_caster<std::experimental::nullopt_t> {};
304 #endif
305 
310 
311  using result_type = handle; // required by boost::variant in C++11
312 
313  template <typename T>
314  result_type operator()(T &&src) const {
315  return make_caster<T>::cast(std::forward<T>(src), policy, parent);
316  }
317 };
318 
323 template <template<typename...> class Variant>
324 struct visit_helper {
325  template <typename... Args>
326  static auto call(Args &&...args) -> decltype(visit(std::forward<Args>(args)...)) {
327  return visit(std::forward<Args>(args)...);
328  }
329 };
330 
332 template <typename Variant> struct variant_caster;
333 
334 template <template<typename...> class V, typename... Ts>
335 struct variant_caster<V<Ts...>> {
336  static_assert(sizeof...(Ts) > 0, "Variant must consist of at least one alternative.");
337 
338  template <typename U, typename... Us>
339  bool load_alternative(handle src, bool convert, type_list<U, Us...>) {
340  auto caster = make_caster<U>();
341  if (caster.load(src, convert)) {
342  value = cast_op<U>(caster);
343  return true;
344  }
345  return load_alternative(src, convert, type_list<Us...>{});
346  }
347 
348  bool load_alternative(handle, bool, type_list<>) { return false; }
349 
350  bool load(handle src, bool convert) {
351  // Do a first pass without conversions to improve constructor resolution.
352  // E.g. `py::int_(1).cast<variant<double, int>>()` needs to fill the `int`
353  // slot of the variant. Without two-pass loading `double` would be filled
354  // because it appears first and a conversion is possible.
355  if (convert && load_alternative(src, false, type_list<Ts...>{}))
356  return true;
357  return load_alternative(src, convert, type_list<Ts...>{});
358  }
359 
360  template <typename Variant>
361  static handle cast(Variant &&src, return_value_policy policy, handle parent) {
362  return visit_helper<V>::call(variant_caster_visitor{policy, parent},
363  std::forward<Variant>(src));
364  }
365 
366  using Type = V<Ts...>;
368 };
369 
370 #if PYBIND11_HAS_VARIANT
371 template <typename... Ts>
372 struct type_caster<std::variant<Ts...>> : variant_caster<std::variant<Ts...>> { };
373 #endif
374 
375 NAMESPACE_END(detail)
376 
377 inline std::ostream &operator<<(std::ostream &os, const handle &obj) {
378  os << (std::string) str(obj);
379  return os;
380 }
381 
383 
384 #if defined(_MSC_VER)
385 #pragma warning(pop)
386 #endif
bool require_size(enable_if_t<!R, size_t > size)
Definition: stl.h:206
Generic variant caster.
Definition: stl.h:332
forwarded_type< T, U > forward_like(U &&u)
Definition: stl.h:63
#define PYBIND11_NAMESPACE
Definition: detail/common.h:26
Visit a variant and cast any found type to Python.
Definition: stl.h:307
bool load(handle src, bool convert)
Definition: stl.h:71
bool load(handle src, bool convert)
Definition: stl.h:273
STL namespace.
static handle cast(T &&src, return_value_policy policy, handle parent)
Definition: stl.h:228
constexpr descr< N - 1 > _(char const(&text)[N])
Definition: descr.h:54
bool is_none() const
Equivalent to obj is None in Python.
Definition: pytypes.h:116
return_value_policy policy
Definition: stl.h:308
bool load(handle src, bool convert)
Definition: stl.h:105
void reserve_maybe(sequence, void *)
Definition: stl.h:165
static auto call(Args &&...args) -> decltype(visit(std::forward< Args >(args)...))
Definition: stl.h:326
static handle cast(T &&src, return_value_policy policy, handle parent)
Definition: stl.h:169
#define NAMESPACE_END(name)
Definition: detail/common.h:16
bool load_alternative(handle src, bool convert, type_list< U, Us... >)
Definition: stl.h:339
return_value_policy
Approach used to cast a previously unknown C++ instance into a Python object.
conditional_t< std::is_lvalue_reference< T >::value, remove_reference_t< U > &, remove_reference_t< U > && > forwarded_type
Definition: stl.h:58
size_t function_call & call
Definition: pybind11.h:1610
static handle cast(Variant &&src, return_value_policy policy, handle parent)
Definition: stl.h:361
Helper template which holds a list of types.
bool load(handle src, bool convert)
Definition: stl.h:146
typename std::remove_reference< T >::type remove_reference_t
def d(s)
Definition: mkdoc.py:69
bool load(handle src, bool convert)
Definition: stl.h:350
bool require_size(enable_if_t< R, size_t > size)
Definition: stl.h:200
detail::enable_if_t<!detail::move_never< T >::value, T > move(object &&obj)
Definition: cast.h:1685
handle release()
Definition: pytypes.h:247
static handle cast(T &&src, return_value_policy policy, handle parent)
Definition: stl.h:122
return os str()
#define NAMESPACE_BEGIN(name)
Definition: detail/common.h:13
static handle cast(T &&src, return_value_policy policy, handle parent)
Definition: stl.h:86
bool load(handle src, bool convert)
Definition: stl.h:211
T cast(const handle &handle)
Definition: cast.h:1659
bool load(handle src, bool convert)
Definition: cast.h:491
result_type operator()(T &&src) const
Definition: stl.h:314
void reserve_maybe(sequence s, Type *)
Definition: stl.h:164
typename std::conditional< B, T, F >::type conditional_t
A copy of std::conditional_t from C++14 - same reasoning as enable_if_t, it does not hurt to redefine...
Definition: CLI11.hpp:927
#define PYBIND11_TYPE_CASTER(type, py_name)
Definition: cast.h:942
typename std::enable_if< B, T >::type enable_if_t
from cpp_future import (convenient aliases from C++14/17)
const handle & inc_ref() const &
Definition: pytypes.h:190
bool load_alternative(handle, bool, type_list<>)
Definition: stl.h:348
Py_ssize_t ssize_t
constexpr descr< 0 > concat()
Definition: descr.h:83
static handle cast(T_ &&src, return_value_policy policy, handle parent)
Definition: stl.h:266