cppyabm  1.0.17
An agent-based library to integrate C++ and Python
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 
53 
54 /// Extracts an const lvalue reference or rvalue reference for U based on the type of T (e.g. for
55 /// forwarding a container element). Typically used indirect via forwarded_type(), below.
56 template <typename T, typename U>
59 
60 /// Forwards a value U as rvalue or lvalue according to whether T is rvalue or lvalue; typically
61 /// used for forwarding a container's elements.
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 
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<bytes>(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>
200  bool require_size(enable_if_t<R, size_t> size) {
201  if (value.size() != size)
202  value.resize(size);
203  return true;
204  }
205  template <bool R = Resizable>
206  bool require_size(enable_if_t<!R, size_t> size) {
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();
271  }
272  return value_conv::cast(*std::forward<T_>(src), policy, parent);
273  }
274 
275  bool load(handle src, bool convert) {
276  if (!src) {
277  return false;
278  } else if (src.is_none()) {
279  return true; // default-constructed value is already empty
280  }
281  value_conv inner_caster;
282  if (!inner_caster.load(src, convert))
283  return false;
284 
285  value.emplace(cast_op<typename T::value_type &&>(std::move(inner_caster)));
286  return true;
287  }
288 
289  PYBIND11_TYPE_CASTER(T, _("Optional[") + value_conv::name + _("]"));
290 };
291 
292 #if defined(PYBIND11_HAS_OPTIONAL)
293 template<typename T> struct type_caster<std::optional<T>>
294  : public optional_caster<std::optional<T>> {};
295 
296 template<> struct type_caster<std::nullopt_t>
297  : public void_caster<std::nullopt_t> {};
298 #endif
299 
300 #if defined(PYBIND11_HAS_EXP_OPTIONAL)
301 template<typename T> struct type_caster<std::experimental::optional<T>>
302  : public optional_caster<std::experimental::optional<T>> {};
303 
304 template<> struct type_caster<std::experimental::nullopt_t>
305  : public void_caster<std::experimental::nullopt_t> {};
306 #endif
307 
308 /// Visit a variant and cast any found type to Python
312 
313  using result_type = handle; // required by boost::variant in C++11
314 
315  template <typename T>
316  result_type operator()(T &&src) const {
317  return make_caster<T>::cast(std::forward<T>(src), policy, parent);
318  }
319 };
320 
321 /// Helper class which abstracts away variant's `visit` function. `std::variant` and similar
322 /// `namespace::variant` types which provide a `namespace::visit()` function are handled here
323 /// automatically using argument-dependent lookup. Users can provide specializations for other
324 /// variant-like classes, e.g. `boost::variant` and `boost::apply_visitor`.
325 template <template<typename...> class Variant>
326 struct visit_helper {
327  template <typename... Args>
328  static auto call(Args &&...args) -> decltype(visit(std::forward<Args>(args)...)) {
329  return visit(std::forward<Args>(args)...);
330  }
331 };
332 
333 /// Generic variant caster
334 template <typename Variant> struct variant_caster;
335 
336 template <template<typename...> class V, typename... Ts>
337 struct variant_caster<V<Ts...>> {
338  static_assert(sizeof...(Ts) > 0, "Variant must consist of at least one alternative.");
339 
340  template <typename U, typename... Us>
341  bool load_alternative(handle src, bool convert, type_list<U, Us...>) {
342  auto caster = make_caster<U>();
343  if (caster.load(src, convert)) {
344  value = cast_op<U>(caster);
345  return true;
346  }
347  return load_alternative(src, convert, type_list<Us...>{});
348  }
349 
350  bool load_alternative(handle, bool, type_list<>) { return false; }
351 
352  bool load(handle src, bool convert) {
353  // Do a first pass without conversions to improve constructor resolution.
354  // E.g. `py::int_(1).cast<variant<double, int>>()` needs to fill the `int`
355  // slot of the variant. Without two-pass loading `double` would be filled
356  // because it appears first and a conversion is possible.
357  if (convert && load_alternative(src, false, type_list<Ts...>{}))
358  return true;
359  return load_alternative(src, convert, type_list<Ts...>{});
360  }
361 
362  template <typename Variant>
363  static handle cast(Variant &&src, return_value_policy policy, handle parent) {
365  std::forward<Variant>(src));
366  }
367 
368  using Type = V<Ts...>;
370 };
371 
372 #if defined(PYBIND11_HAS_VARIANT)
373 template <typename... Ts>
374 struct type_caster<std::variant<Ts...>> : variant_caster<std::variant<Ts...>> { };
375 #endif
376 
378 
379 inline std::ostream &operator<<(std::ostream &os, const handle &obj) {
380  os << (std::string) str(obj);
381  return os;
382 }
383 
385 
386 #if defined(_MSC_VER)
387 #pragma warning(pop)
388 #endif
enable_if_t
typename std::enable_if< B, T >::type enable_if_t
from cpp_future import (convenient aliases from C++14/17)
Definition: common.h:504
forwarded_type
conditional_t< std::is_lvalue_reference< T >::value, remove_reference_t< U > &, remove_reference_t< U > && > forwarded_type
Definition: stl.h:58
sequence::size
size_t size() const
Definition: pytypes.h:1332
PYBIND11_NAMESPACE_BEGIN
#define PYBIND11_NAMESPACE_BEGIN(name)
Definition: common.h:16
array_caster
Definition: stl.h:195
PYBIND11_NAMESPACE_END
#define PYBIND11_NAMESPACE_END(name)
Definition: common.h:17
set
Definition: pytypes.h:1369
list_caster
Definition: stl.h:143
array_caster::load
bool load(handle src, bool convert)
Definition: stl.h:211
PYBIND11_NAMESPACE
#define PYBIND11_NAMESPACE
Definition: common.h:26
optional_caster
Definition: stl.h:262
list_caster::PYBIND11_TYPE_CASTER
PYBIND11_TYPE_CASTER(Type, _("List[")+value_conv::name+_("]"))
array_caster::cast
static handle cast(T &&src, return_value_policy policy, handle parent)
Definition: stl.h:228
list
Definition: pytypes.h:1345
forward_like
forwarded_type< T, U > forward_like(U &&u)
Definition: stl.h:63
handle::inc_ref
const handle & inc_ref() const &
Definition: pytypes.h:192
map_caster::PYBIND11_TYPE_CASTER
PYBIND11_TYPE_CASTER(Type, _("Dict[")+key_conv::name+_(", ")+value_conv::name+_("]"))
optional_caster::PYBIND11_TYPE_CASTER
PYBIND11_TYPE_CASTER(T, _("Optional[")+value_conv::name+_("]"))
void_caster
Definition: cast.h:1132
_
constexpr descr< N - 1 > _(char const(&text)[N])
Definition: descr.h:54
map_caster::load
bool load(handle src, bool convert)
Definition: stl.h:105
list_caster::cast
static handle cast(T &&src, return_value_policy policy, handle parent)
Definition: stl.h:169
conditional_t
typename std::conditional< B, T, F >::type conditional_t
Definition: common.h:505
remove_reference_t
typename std::remove_reference< T >::type remove_reference_t
Definition: common.h:507
type_list
Helper template which holds a list of types.
Definition: common.h:583
type_caster_base::cast
static handle cast(const itype &src, return_value_policy policy, handle parent)
Definition: cast.h:878
variant_caster< V< Ts... > >::load_alternative
bool load_alternative(handle, bool, type_list<>)
Definition: stl.h:350
dict
Definition: pytypes.h:1299
variant_caster< V< Ts... > >::cast
static handle cast(Variant &&src, return_value_policy policy, handle parent)
Definition: stl.h:363
map_caster
Definition: stl.h:101
handle
Definition: pytypes.h:176
type_caster
Definition: cast.h:954
sequence
Definition: pytypes.h:1329
set_caster
Definition: stl.h:67
variant_caster
Generic variant caster.
Definition: stl.h:334
set_caster::PYBIND11_TYPE_CASTER
PYBIND11_TYPE_CASTER(type, _("Set[")+key_conv::name+_("]"))
return_value_policy_override::policy
static return_value_policy policy(return_value_policy p)
Definition: cast.h:1734
object::release
handle release()
Definition: pytypes.h:249
map_caster::cast
static handle cast(T &&src, return_value_policy policy, handle parent)
Definition: stl.h:122
policy
Definition: policy.py:1
variant_caster_visitor::parent
handle parent
Definition: stl.h:311
variant_caster< V< Ts... > >::load_alternative
bool load_alternative(handle src, bool convert, type_list< U, Us... >)
Definition: stl.h:341
ssize_t
Py_ssize_t ssize_t
Definition: common.h:353
array_caster::PYBIND11_TYPE_CASTER
PYBIND11_TYPE_CASTER(ArrayType, _("List[")+value_conv::name+_< Resizable >(_(""), _("[")+_< Size >()+_("]"))+_("]"))
concat
constexpr descr< 0 > concat()
Definition: descr.h:83
variant_caster< V< Ts... > >::PYBIND11_TYPE_CASTER
PYBIND11_TYPE_CASTER(Type, _("Union[")+detail::concat(make_caster< Ts >::name...)+_("]"))
set_caster< std::set< Key, Compare, Alloc >, Key >::type
std::set< Key, Compare, Alloc > type
Definition: stl.h:68
visit_helper
Definition: stl.h:326
variant_caster_visitor::operator()
result_type operator()(T &&src) const
Definition: stl.h:316
str
Definition: pytypes.h:946
pybind11.h
array
Definition: numpy.h:556
move
detail::enable_if_t<!detail::move_never< T >::value, T > move(object &&obj)
Definition: cast.h:1798
list_caster::load
bool load(handle src, bool convert)
Definition: stl.h:146
handle::ptr
PyObject * ptr() const
Return the underlying PyObject * pointer.
Definition: pytypes.h:184
benchmark.size
size
Definition: benchmark.py:90
variant_caster_visitor::policy
return_value_policy policy
Definition: stl.h:310
optional_caster::load
bool load(handle src, bool convert)
Definition: stl.h:275
args
Definition: pytypes.h:1366
visit_helper::call
static auto call(Args &&...args) -> decltype(visit(std::forward< Args >(args)...))
Definition: stl.h:328
return_value_policy
return_value_policy
Approach used to cast a previously unknown C++ instance into a Python object.
Definition: common.h:357
optional_caster::cast
static handle cast(T_ &&src, return_value_policy policy, handle parent)
Definition: stl.h:266
type_caster_generic::load
bool load(handle src, bool convert)
Definition: cast.h:508
none
Definition: pytypes.h:1075
variant_caster< V< Ts... > >::Type
V< Ts... > Type
Definition: stl.h:368
set_caster::cast
static handle cast(T &&src, return_value_policy policy, handle parent)
Definition: stl.h:86
set_caster::load
bool load(handle src, bool convert)
Definition: stl.h:71
type_caster_base::name
static constexpr auto name
Definition: cast.h:873
variant_caster_visitor
Visit a variant and cast any found type to Python.
Definition: stl.h:309
test_callbacks.value
value
Definition: test_callbacks.py:126
variant_caster< V< Ts... > >::load
bool load(handle src, bool convert)
Definition: stl.h:352