stl_bind.h
Go to the documentation of this file.
1 /*
2  pybind11/std_bind.h: Binding generators for STL data types
3 
4  Copyright (c) 2016 Sergey Lyskov and Wenzel Jakob
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 "detail/common.h"
14 #include "cast.h"
15 #include "operators.h"
16 
17 #include <algorithm>
18 #include <sstream>
19 #include <type_traits>
20 
23 
24 /* SFINAE helper class used by 'is_comparable */
25 template <typename T>
27  template <typename T2>
28  static std::true_type
29  test_comparable(decltype(std::declval<const T2 &>() == std::declval<const T2 &>()) *);
30  template <typename T2>
31  static std::false_type test_comparable(...);
32  template <typename T2>
33  static std::true_type test_value(typename T2::value_type *);
34  template <typename T2>
35  static std::false_type test_value(...);
36  template <typename T2>
37  static std::true_type test_pair(typename T2::first_type *, typename T2::second_type *);
38  template <typename T2>
39  static std::false_type test_pair(...);
40 
41  static constexpr const bool is_comparable
42  = std::is_same<std::true_type, decltype(test_comparable<T>(nullptr))>::value;
43  static constexpr const bool is_pair
44  = std::is_same<std::true_type, decltype(test_pair<T>(nullptr, nullptr))>::value;
45  static constexpr const bool is_vector
46  = std::is_same<std::true_type, decltype(test_value<T>(nullptr))>::value;
47  static constexpr const bool is_element = !is_pair && !is_vector;
48 };
49 
50 /* Default: is_comparable -> std::false_type */
51 template <typename T, typename SFINAE = void>
52 struct is_comparable : std::false_type {};
53 
54 /* For non-map data structures, check whether operator== can be instantiated */
55 template <typename T>
57  T,
59  : std::true_type {};
60 
61 /* For a vector/map data structure, recursively check the value type
62  (which is std::pair for maps) */
63 template <typename T>
65  : is_comparable<typename recursive_container_traits<T>::type_to_check_recursively> {};
66 
67 template <>
68 struct is_comparable<recursive_bottom> : std::true_type {};
69 
70 /* For pairs, recursively check the two data types */
71 template <typename T>
75 };
76 
77 /* Fallback functions */
78 template <typename, typename, typename... Args>
79 void vector_if_copy_constructible(const Args &...) {}
80 template <typename, typename, typename... Args>
81 void vector_if_equal_operator(const Args &...) {}
82 template <typename, typename, typename... Args>
83 void vector_if_insertion_operator(const Args &...) {}
84 template <typename, typename, typename... Args>
85 void vector_modifiers(const Args &...) {}
86 
87 template <typename Vector, typename Class_>
89  cl.def(init<const Vector &>(), "Copy constructor");
90 }
91 
92 template <typename Vector, typename Class_>
94  using T = typename Vector::value_type;
95 
96  cl.def(self == self);
97  cl.def(self != self);
98 
99  cl.def(
100  "count",
101  [](const Vector &v, const T &x) { return std::count(v.begin(), v.end(), x); },
102  arg("x"),
103  "Return the number of times ``x`` appears in the list");
104 
105  cl.def(
106  "remove",
107  [](Vector &v, const T &x) {
108  auto p = std::find(v.begin(), v.end(), x);
109  if (p != v.end()) {
110  v.erase(p);
111  } else {
112  throw value_error();
113  }
114  },
115  arg("x"),
116  "Remove the first item from the list whose value is x. "
117  "It is an error if there is no such item.");
118 
119  cl.def(
120  "__contains__",
121  [](const Vector &v, const T &x) { return std::find(v.begin(), v.end(), x) != v.end(); },
122  arg("x"),
123  "Return true the container contains ``x``");
124 }
125 
126 // Vector modifiers -- requires a copyable vector_type:
127 // (Technically, some of these (pop and __delitem__) don't actually require copyability, but it
128 // seems silly to allow deletion but not insertion, so include them here too.)
129 template <typename Vector, typename Class_>
132  using T = typename Vector::value_type;
133  using SizeType = typename Vector::size_type;
134  using DiffType = typename Vector::difference_type;
135 
136  auto wrap_i = [](DiffType i, SizeType n) {
137  if (i < 0) {
138  i += n;
139  }
140  if (i < 0 || (SizeType) i >= n) {
141  throw index_error();
142  }
143  return i;
144  };
145 
146  cl.def(
147  "append",
148  [](Vector &v, const T &value) { v.push_back(value); },
149  arg("x"),
150  "Add an item to the end of the list");
151 
152  cl.def(init([](const iterable &it) {
153  auto v = std::unique_ptr<Vector>(new Vector());
154  v->reserve(len_hint(it));
155  for (handle h : it) {
156  v->push_back(h.cast<T>());
157  }
158  return v.release();
159  }));
160 
161  cl.def("clear", [](Vector &v) { v.clear(); }, "Clear the contents");
162 
163  cl.def(
164  "extend",
165  [](Vector &v, const Vector &src) { v.insert(v.end(), src.begin(), src.end()); },
166  arg("L"),
167  "Extend the list by appending all the items in the given list");
168 
169  cl.def(
170  "extend",
171  [](Vector &v, const iterable &it) {
172  const size_t old_size = v.size();
173  v.reserve(old_size + len_hint(it));
174  try {
175  for (handle h : it) {
176  v.push_back(h.cast<T>());
177  }
178  } catch (const cast_error &) {
179  v.erase(v.begin() + static_cast<typename Vector::difference_type>(old_size),
180  v.end());
181  try {
182  v.shrink_to_fit();
183  } catch (const std::exception &) {
184  // Do nothing
185  }
186  throw;
187  }
188  },
189  arg("L"),
190  "Extend the list by appending all the items in the given list");
191 
192  cl.def(
193  "insert",
194  [](Vector &v, DiffType i, const T &x) {
195  // Can't use wrap_i; i == v.size() is OK
196  if (i < 0) {
197  i += v.size();
198  }
199  if (i < 0 || (SizeType) i > v.size()) {
200  throw index_error();
201  }
202  v.insert(v.begin() + i, x);
203  },
204  arg("i"),
205  arg("x"),
206  "Insert an item at a given position.");
207 
208  cl.def(
209  "pop",
210  [](Vector &v) {
211  if (v.empty()) {
212  throw index_error();
213  }
214  T t = std::move(v.back());
215  v.pop_back();
216  return t;
217  },
218  "Remove and return the last item");
219 
220  cl.def(
221  "pop",
222  [wrap_i](Vector &v, DiffType i) {
223  i = wrap_i(i, v.size());
224  T t = std::move(v[(SizeType) i]);
225  v.erase(std::next(v.begin(), i));
226  return t;
227  },
228  arg("i"),
229  "Remove and return the item at index ``i``");
230 
231  cl.def("__setitem__", [wrap_i](Vector &v, DiffType i, const T &t) {
232  i = wrap_i(i, v.size());
233  v[(SizeType) i] = t;
234  });
235 
237  cl.def(
238  "__getitem__",
239  [](const Vector &v, const slice &slice) -> Vector * {
240  size_t start = 0, stop = 0, step = 0, slicelength = 0;
241 
242  if (!slice.compute(v.size(), &start, &stop, &step, &slicelength)) {
243  throw error_already_set();
244  }
245 
246  auto *seq = new Vector();
247  seq->reserve((size_t) slicelength);
248 
249  for (size_t i = 0; i < slicelength; ++i) {
250  seq->push_back(v[start]);
251  start += step;
252  }
253  return seq;
254  },
255  arg("s"),
256  "Retrieve list elements using a slice object");
257 
258  cl.def(
259  "__setitem__",
260  [](Vector &v, const slice &slice, const Vector &value) {
261  size_t start = 0, stop = 0, step = 0, slicelength = 0;
262  if (!slice.compute(v.size(), &start, &stop, &step, &slicelength)) {
263  throw error_already_set();
264  }
265 
266  if (slicelength != value.size()) {
267  throw std::runtime_error(
268  "Left and right hand size of slice assignment have different sizes!");
269  }
270 
271  for (size_t i = 0; i < slicelength; ++i) {
272  v[start] = value[i];
273  start += step;
274  }
275  },
276  "Assign list elements using a slice object");
277 
278  cl.def(
279  "__delitem__",
280  [wrap_i](Vector &v, DiffType i) {
281  i = wrap_i(i, v.size());
282  v.erase(v.begin() + i);
283  },
284  "Delete the list elements at index ``i``");
285 
286  cl.def(
287  "__delitem__",
288  [](Vector &v, const slice &slice) {
289  size_t start = 0, stop = 0, step = 0, slicelength = 0;
290 
291  if (!slice.compute(v.size(), &start, &stop, &step, &slicelength)) {
292  throw error_already_set();
293  }
294 
295  if (step == 1 && false) {
296  v.erase(v.begin() + (DiffType) start, v.begin() + DiffType(start + slicelength));
297  } else {
298  for (size_t i = 0; i < slicelength; ++i) {
299  v.erase(v.begin() + DiffType(start));
300  start += step - 1;
301  }
302  }
303  },
304  "Delete list elements using a slice object");
305 }
306 
307 // If the type has an operator[] that doesn't return a reference (most notably std::vector<bool>),
308 // we have to access by copying; otherwise we return by reference.
309 template <typename Vector>
310 using vector_needs_copy
311  = negation<std::is_same<decltype(std::declval<Vector>()[typename Vector::size_type()]),
312  typename Vector::value_type &>>;
313 
314 // The usual case: access and iterate by reference
315 template <typename Vector, typename Class_>
317  using T = typename Vector::value_type;
318  using SizeType = typename Vector::size_type;
319  using DiffType = typename Vector::difference_type;
320  using ItType = typename Vector::iterator;
321 
322  auto wrap_i = [](DiffType i, SizeType n) {
323  if (i < 0) {
324  i += n;
325  }
326  if (i < 0 || (SizeType) i >= n) {
327  throw index_error();
328  }
329  return i;
330  };
331 
332  cl.def(
333  "__getitem__",
334  [wrap_i](Vector &v, DiffType i) -> T & {
335  i = wrap_i(i, v.size());
336  return v[(SizeType) i];
337  },
338  return_value_policy::reference_internal // ref + keepalive
339  );
340 
341  cl.def(
342  "__iter__",
343  [](Vector &v) {
344  return make_iterator<return_value_policy::reference_internal, ItType, ItType, T &>(
345  v.begin(), v.end());
346  },
347  keep_alive<0, 1>() /* Essential: keep list alive while iterator exists */
348  );
349 }
350 
351 // The case for special objects, like std::vector<bool>, that have to be returned-by-copy:
352 template <typename Vector, typename Class_>
354  using T = typename Vector::value_type;
355  using SizeType = typename Vector::size_type;
356  using DiffType = typename Vector::difference_type;
357  using ItType = typename Vector::iterator;
358  cl.def("__getitem__", [](const Vector &v, DiffType i) -> T {
359  if (i < 0) {
360  i += v.size();
361  if (i < 0) {
362  throw index_error();
363  }
364  }
365  auto i_st = static_cast<SizeType>(i);
366  if (i_st >= v.size()) {
367  throw index_error();
368  }
369  return v[i_st];
370  });
371 
372  cl.def(
373  "__iter__",
374  [](Vector &v) {
375  return make_iterator<return_value_policy::copy, ItType, ItType, T>(v.begin(), v.end());
376  },
377  keep_alive<0, 1>() /* Essential: keep list alive while iterator exists */
378  );
379 }
380 
381 template <typename Vector, typename Class_>
382 auto vector_if_insertion_operator(Class_ &cl, std::string const &name)
383  -> decltype(std::declval<std::ostream &>() << std::declval<typename Vector::value_type>(),
384  void()) {
385  using size_type = typename Vector::size_type;
386 
387  cl.def(
388  "__repr__",
389  [name](Vector &v) {
390  std::ostringstream s;
391  s << name << '[';
392  for (size_type i = 0; i < v.size(); ++i) {
393  s << v[i];
394  if (i != v.size() - 1) {
395  s << ", ";
396  }
397  }
398  s << ']';
399  return s.str();
400  },
401  "Return the canonical string representation of this list.");
402 }
403 
404 // Provide the buffer interface for vectors if we have data() and we have a format for it
405 // GCC seems to have "void std::vector<bool>::data()" - doing SFINAE on the existence of data()
406 // is insufficient, we need to check it returns an appropriate pointer
407 template <typename Vector, typename = void>
408 struct vector_has_data_and_format : std::false_type {};
409 template <typename Vector>
411  Vector,
412  enable_if_t<std::is_same<decltype(format_descriptor<typename Vector::value_type>::format(),
413  std::declval<Vector>().data()),
414  typename Vector::value_type *>::value>> : std::true_type {};
415 
416 // [workaround(intel)] Separate function required here
417 // Workaround as the Intel compiler does not compile the enable_if_t part below
418 // (tested with icc (ICC) 2021.1 Beta 20200827)
419 template <typename... Args>
420 constexpr bool args_any_are_buffer() {
421  return detail::any_of<std::is_same<Args, buffer_protocol>...>::value;
422 }
423 
424 // [workaround(intel)] Separate function required here
425 // [workaround(msvc)] Can't use constexpr bool in return type
426 
427 // Add the buffer interface to a vector
428 template <typename Vector, typename Class_, typename... Args>
429 void vector_buffer_impl(Class_ &cl, std::true_type) {
430  using T = typename Vector::value_type;
431 
433  "There is not an appropriate format descriptor for this vector");
434 
435  // numpy.h declares this for arbitrary types, but it may raise an exception and crash hard
436  // at runtime if PYBIND11_NUMPY_DTYPE hasn't been called, so check here
438 
439  cl.def_buffer([](Vector &v) -> buffer_info {
440  return buffer_info(v.data(),
441  static_cast<ssize_t>(sizeof(T)),
443  1,
444  {v.size()},
445  {sizeof(T)});
446  });
447 
448  cl.def(init([](const buffer &buf) {
449  auto info = buf.request();
450  if (info.ndim != 1 || info.strides[0] % static_cast<ssize_t>(sizeof(T))) {
451  throw type_error("Only valid 1D buffers can be copied to a vector");
452  }
454  || (ssize_t) sizeof(T) != info.itemsize) {
455  throw type_error("Format mismatch (Python: " + info.format
456  + " C++: " + format_descriptor<T>::format() + ")");
457  }
458 
459  T *p = static_cast<T *>(info.ptr);
460  ssize_t step = info.strides[0] / static_cast<ssize_t>(sizeof(T));
461  T *end = p + info.shape[0] * step;
462  if (step == 1) {
463  return Vector(p, end);
464  }
465  Vector vec;
466  vec.reserve((size_t) info.shape[0]);
467  for (; p != end; p += step) {
468  vec.push_back(*p);
469  }
470  return vec;
471  }));
472 
473  return;
474 }
475 
476 template <typename Vector, typename Class_, typename... Args>
477 void vector_buffer_impl(Class_ &, std::false_type) {}
478 
479 template <typename Vector, typename Class_, typename... Args>
480 void vector_buffer(Class_ &cl) {
481  vector_buffer_impl<Vector, Class_, Args...>(
482  cl, detail::any_of<std::is_same<Args, buffer_protocol>...>{});
483 }
484 
486 
487 //
488 // std::vector
489 //
490 template <typename Vector, typename holder_type = std::unique_ptr<Vector>, typename... Args>
491 class_<Vector, holder_type> bind_vector(handle scope, std::string const &name, Args &&...args) {
492  using Class_ = class_<Vector, holder_type>;
493 
494  // If the value_type is unregistered (e.g. a converting type) or is itself registered
495  // module-local then make the vector binding module-local as well:
496  using vtype = typename Vector::value_type;
497  auto *vtype_info = detail::get_type_info(typeid(vtype));
498  bool local = !vtype_info || vtype_info->module_local;
499 
500  Class_ cl(scope, name.c_str(), pybind11::module_local(local), std::forward<Args>(args)...);
501 
502  // Declare the buffer interface if a buffer_protocol() is passed in
503  detail::vector_buffer<Vector, Class_, Args...>(cl);
504 
505  cl.def(init<>());
506 
507  // Register copy constructor (if possible)
508  detail::vector_if_copy_constructible<Vector, Class_>(cl);
509 
510  // Register comparison-related operators and functions (if possible)
511  detail::vector_if_equal_operator<Vector, Class_>(cl);
512 
513  // Register stream insertion operator (if possible)
514  detail::vector_if_insertion_operator<Vector, Class_>(cl, name);
515 
516  // Modifiers require copyable vector value type
517  detail::vector_modifiers<Vector, Class_>(cl);
518 
519  // Accessor and iterator; return by value if copyable, otherwise we return by ref + keep-alive
520  detail::vector_accessor<Vector, Class_>(cl);
521 
522  cl.def(
523  "__bool__",
524  [](const Vector &v) -> bool { return !v.empty(); },
525  "Check whether the list is nonempty");
526 
527  cl.def("__len__", [](const Vector &vec) { return vec.size(); });
528 
529 #if 0
530  // C++ style functions deprecated, leaving it here as an example
531  cl.def(init<size_type>());
532 
533  cl.def("resize",
534  (void (Vector::*) (size_type count)) & Vector::resize,
535  "changes the number of elements stored");
536 
537  cl.def("erase",
538  [](Vector &v, SizeType i) {
539  if (i >= v.size())
540  throw index_error();
541  v.erase(v.begin() + i);
542  }, "erases element at index ``i``");
543 
544  cl.def("empty", &Vector::empty, "checks whether the container is empty");
545  cl.def("size", &Vector::size, "returns the number of elements");
546  cl.def("push_back", (void (Vector::*)(const T&)) &Vector::push_back, "adds an element to the end");
547  cl.def("pop_back", &Vector::pop_back, "removes the last element");
548 
549  cl.def("max_size", &Vector::max_size, "returns the maximum possible number of elements");
550  cl.def("reserve", &Vector::reserve, "reserves storage");
551  cl.def("capacity", &Vector::capacity, "returns the number of elements that can be held in currently allocated storage");
552  cl.def("shrink_to_fit", &Vector::shrink_to_fit, "reduces memory usage by freeing unused memory");
553 
554  cl.def("clear", &Vector::clear, "clears the contents");
555  cl.def("swap", &Vector::swap, "swaps the contents");
556 
557  cl.def("front", [](Vector &v) {
558  if (v.size()) return v.front();
559  else throw index_error();
560  }, "access the first element");
561 
562  cl.def("back", [](Vector &v) {
563  if (v.size()) return v.back();
564  else throw index_error();
565  }, "access the last element ");
566 
567 #endif
568 
569  return cl;
570 }
571 
572 //
573 // std::map, std::unordered_map
574 //
575 
577 
578 /* Fallback functions */
579 template <typename, typename, typename... Args>
580 void map_if_insertion_operator(const Args &...) {}
581 template <typename, typename, typename... Args>
582 void map_assignment(const Args &...) {}
583 
584 // Map assignment when copy-assignable: just copy the value
585 template <typename Map, typename Class_>
588  using KeyType = typename Map::key_type;
589  using MappedType = typename Map::mapped_type;
590 
591  cl.def("__setitem__", [](Map &m, const KeyType &k, const MappedType &v) {
592  auto it = m.find(k);
593  if (it != m.end()) {
594  it->second = v;
595  } else {
596  m.emplace(k, v);
597  }
598  });
599 }
600 
601 // Not copy-assignable, but still copy-constructible: we can update the value by erasing and
602 // reinserting
603 template <typename Map, typename Class_>
606  Class_> &cl) {
607  using KeyType = typename Map::key_type;
608  using MappedType = typename Map::mapped_type;
609 
610  cl.def("__setitem__", [](Map &m, const KeyType &k, const MappedType &v) {
611  // We can't use m[k] = v; because value type might not be default constructable
612  auto r = m.emplace(k, v);
613  if (!r.second) {
614  // value type is not copy assignable so the only way to insert it is to erase it
615  // first...
616  m.erase(r.first);
617  m.emplace(k, v);
618  }
619  });
620 }
621 
622 template <typename Map, typename Class_>
623 auto map_if_insertion_operator(Class_ &cl, std::string const &name)
624  -> decltype(std::declval<std::ostream &>() << std::declval<typename Map::key_type>()
625  << std::declval<typename Map::mapped_type>(),
626  void()) {
627 
628  cl.def(
629  "__repr__",
630  [name](Map &m) {
631  std::ostringstream s;
632  s << name << '{';
633  bool f = false;
634  for (auto const &kv : m) {
635  if (f) {
636  s << ", ";
637  }
638  s << kv.first << ": " << kv.second;
639  f = true;
640  }
641  s << '}';
642  return s.str();
643  },
644  "Return the canonical string representation of this map.");
645 }
646 
647 struct keys_view {
648  virtual size_t len() = 0;
649  virtual iterator iter() = 0;
650  virtual bool contains(const handle &k) = 0;
651  virtual ~keys_view() = default;
652 };
653 
654 struct values_view {
655  virtual size_t len() = 0;
656  virtual iterator iter() = 0;
657  virtual ~values_view() = default;
658 };
659 
660 struct items_view {
661  virtual size_t len() = 0;
662  virtual iterator iter() = 0;
663  virtual ~items_view() = default;
664 };
665 
666 template <typename Map>
667 struct KeysViewImpl : public detail::keys_view {
668  explicit KeysViewImpl(Map &map) : map(map) {}
669  size_t len() override { return map.size(); }
670  iterator iter() override { return make_key_iterator(map.begin(), map.end()); }
671  bool contains(const handle &k) override {
672  try {
673  return map.find(k.template cast<typename Map::key_type>()) != map.end();
674  } catch (const cast_error &) {
675  return false;
676  }
677  }
678  Map &map;
679 };
680 
681 template <typename Map>
682 struct ValuesViewImpl : public detail::values_view {
683  explicit ValuesViewImpl(Map &map) : map(map) {}
684  size_t len() override { return map.size(); }
685  iterator iter() override { return make_value_iterator(map.begin(), map.end()); }
686  Map &map;
687 };
688 
689 template <typename Map>
690 struct ItemsViewImpl : public detail::items_view {
691  explicit ItemsViewImpl(Map &map) : map(map) {}
692  size_t len() override { return map.size(); }
693  iterator iter() override { return make_iterator(map.begin(), map.end()); }
694  Map &map;
695 };
696 
698 
699 template <typename Map, typename holder_type = std::unique_ptr<Map>, typename... Args>
700 class_<Map, holder_type> bind_map(handle scope, const std::string &name, Args &&...args) {
701  using KeyType = typename Map::key_type;
702  using MappedType = typename Map::mapped_type;
703  using KeysView = detail::keys_view;
704  using ValuesView = detail::values_view;
705  using ItemsView = detail::items_view;
706  using Class_ = class_<Map, holder_type>;
707 
708  // If either type is a non-module-local bound type then make the map binding non-local as well;
709  // otherwise (e.g. both types are either module-local or converting) the map will be
710  // module-local.
711  auto *tinfo = detail::get_type_info(typeid(MappedType));
712  bool local = !tinfo || tinfo->module_local;
713  if (local) {
714  tinfo = detail::get_type_info(typeid(KeyType));
715  local = !tinfo || tinfo->module_local;
716  }
717 
718  Class_ cl(scope, name.c_str(), pybind11::module_local(local), std::forward<Args>(args)...);
719 
720  // Wrap KeysView if it wasn't already wrapped
721  if (!detail::get_type_info(typeid(KeysView))) {
722  class_<KeysView> keys_view(scope, "KeysView", pybind11::module_local(local));
723  keys_view.def("__len__", &KeysView::len);
724  keys_view.def("__iter__",
726  keep_alive<0, 1>() /* Essential: keep view alive while iterator exists */
727  );
728  keys_view.def("__contains__", &KeysView::contains);
729  }
730  // Similarly for ValuesView:
731  if (!detail::get_type_info(typeid(ValuesView))) {
732  class_<ValuesView> values_view(scope, "ValuesView", pybind11::module_local(local));
733  values_view.def("__len__", &ValuesView::len);
734  values_view.def("__iter__",
736  keep_alive<0, 1>() /* Essential: keep view alive while iterator exists */
737  );
738  }
739  // Similarly for ItemsView:
740  if (!detail::get_type_info(typeid(ItemsView))) {
741  class_<ItemsView> items_view(scope, "ItemsView", pybind11::module_local(local));
742  items_view.def("__len__", &ItemsView::len);
743  items_view.def("__iter__",
745  keep_alive<0, 1>() /* Essential: keep view alive while iterator exists */
746  );
747  }
748 
749  cl.def(init<>());
750 
751  // Register stream insertion operator (if possible)
752  detail::map_if_insertion_operator<Map, Class_>(cl, name);
753 
754  cl.def(
755  "__bool__",
756  [](const Map &m) -> bool { return !m.empty(); },
757  "Check whether the map is nonempty");
758 
759  cl.def(
760  "__iter__",
761  [](Map &m) { return make_key_iterator(m.begin(), m.end()); },
762  keep_alive<0, 1>() /* Essential: keep map alive while iterator exists */
763  );
764 
765  cl.def(
766  "keys",
767  [](Map &m) { return std::unique_ptr<KeysView>(new detail::KeysViewImpl<Map>(m)); },
768  keep_alive<0, 1>() /* Essential: keep map alive while view exists */
769  );
770 
771  cl.def(
772  "values",
773  [](Map &m) { return std::unique_ptr<ValuesView>(new detail::ValuesViewImpl<Map>(m)); },
774  keep_alive<0, 1>() /* Essential: keep map alive while view exists */
775  );
776 
777  cl.def(
778  "items",
779  [](Map &m) { return std::unique_ptr<ItemsView>(new detail::ItemsViewImpl<Map>(m)); },
780  keep_alive<0, 1>() /* Essential: keep map alive while view exists */
781  );
782 
783  cl.def(
784  "__getitem__",
785  [](Map &m, const KeyType &k) -> MappedType & {
786  auto it = m.find(k);
787  if (it == m.end()) {
788  throw key_error();
789  }
790  return it->second;
791  },
792  return_value_policy::reference_internal // ref + keepalive
793  );
794 
795  cl.def("__contains__", [](Map &m, const KeyType &k) -> bool {
796  auto it = m.find(k);
797  if (it == m.end()) {
798  return false;
799  }
800  return true;
801  });
802  // Fallback for when the object is not of the key type
803  cl.def("__contains__", [](Map &, const object &) -> bool { return false; });
804 
805  // Assignment provided only if the type is copyable
806  detail::map_assignment<Map, Class_>(cl);
807 
808  cl.def("__delitem__", [](Map &m, const KeyType &k) {
809  auto it = m.find(k);
810  if (it == m.end()) {
811  throw key_error();
812  }
813  m.erase(it);
814  });
815 
816  // Always use a lambda in case of `using` declaration
817  cl.def("__len__", [](const Map &m) { return m.size(); });
818 
819  return cl;
820 }
821 
make_value_iterator
typing::Iterator< ValueType > make_value_iterator(Iterator first, Sentinel last, Extra &&...extra)
Definition: pybind11.h:2543
return_value_policy::reference_internal
@ reference_internal
compare
bool compare
Definition: SolverComparer.cpp:98
format_descriptor
Definition: wrap/pybind11/include/pybind11/detail/common.h:1036
vector_if_insertion_operator
void vector_if_insertion_operator(const Args &...)
Definition: stl_bind.h:83
name
Annotation for function names.
Definition: attr.h:51
container_traits::test_comparable
static std::true_type test_comparable(decltype(std::declval< const T2 & >()==std::declval< const T2 & >()) *)
ItemsViewImpl
Definition: stl_bind.h:690
cast.h
vector_if_copy_constructible
void vector_if_copy_constructible(const Args &...)
Definition: stl_bind.h:79
format
std::string format(const std::string &str, const std::vector< std::string > &find, const std::vector< std::string > &replace)
Definition: openglsupport.cpp:226
items_view
Definition: stl_bind.h:660
ItemsViewImpl::iter
iterator iter() override
Definition: stl_bind.h:693
vector_if_equal_operator
void vector_if_equal_operator(const Args &...)
Definition: stl_bind.h:81
ssize_t
Py_ssize_t ssize_t
Definition: wrap/pybind11/include/pybind11/detail/common.h:489
ItemsViewImpl::map
Map & map
Definition: stl_bind.h:694
scope
Annotation for parent scope.
Definition: attr.h:39
resize
v resize(3)
error_already_set
Definition: pytypes.h:739
ValuesViewImpl::ValuesViewImpl
ValuesViewImpl(Map &map)
Definition: stl_bind.h:683
map_assignment
void map_assignment(const Args &...)
Definition: stl_bind.h:582
s
RealScalar s
Definition: level1_cplx_impl.h:126
container_traits
Definition: stl_bind.h:26
keys_view::~keys_view
virtual ~keys_view()=default
x
set noclip points set clip one set noclip two set bar set border lt lw set xdata set ydata set zdata set x2data set y2data set boxwidth set dummy x
Definition: gnuplot_common_settings.hh:12
is_comparable
Definition: stl_bind.h:52
container_traits::test_pair
static std::true_type test_pair(typename T2::first_type *, typename T2::second_type *)
PYBIND11_NAMESPACE_END
#define PYBIND11_NAMESPACE_END(name)
Definition: wrap/pybind11/include/pybind11/detail/common.h:80
vector_buffer
void vector_buffer(Class_ &cl)
Definition: stl_bind.h:480
detail
Definition: testSerializationNonlinear.cpp:70
buffer
Definition: pytypes.h:2270
PYBIND11_NAMESPACE_BEGIN
#define PYBIND11_NAMESPACE_BEGIN(name)
Definition: wrap/pybind11/include/pybind11/detail/common.h:76
iterator
Definition: pytypes.h:1460
is_copy_assignable
Definition: type_caster_base.h:1042
h
const double h
Definition: testSimpleHelicopter.cpp:19
keys_view::contains
virtual bool contains(const handle &k)=0
gtsam::utils.numerical_derivative.local
np.ndarray local(Y a, Y b)
Definition: numerical_derivative.py:33
bind_vector
class_< Vector, holder_type > bind_vector(handle scope, std::string const &name, Args &&...args)
Definition: stl_bind.h:491
KeysViewImpl::len
size_t len() override
Definition: stl_bind.h:669
size
Scalar Scalar int size
Definition: benchVecAdd.cpp:17
n
int n
Definition: BiCGSTAB_simple.cpp:1
slice
Definition: pytypes.h:1909
buffer::request
buffer_info request(bool writable=false) const
Definition: pytypes.h:2274
values_view::len
virtual size_t len()=0
class_
Definition: pybind11.h:1588
handle
Definition: pytypes.h:226
ValuesViewImpl::len
size_t len() override
Definition: stl_bind.h:684
ValuesViewImpl::map
Map & map
Definition: stl_bind.h:686
ValuesViewImpl
Definition: stl_bind.h:682
vector_has_data_and_format
Definition: stl_bind.h:408
container_traits::is_vector
static constexpr const bool is_vector
Definition: stl_bind.h:46
keep_alive
Keep patient alive while nurse lives.
Definition: attr.h:73
vector_buffer_impl
void vector_buffer_impl(Class_ &cl, std::true_type)
Definition: stl_bind.h:429
slice::compute
bool compute(size_t length, size_t *start, size_t *stop, size_t *step, size_t *slicelength) const
Definition: pytypes.h:1928
negation
Definition: wrap/pybind11/include/pybind11/detail/common.h:713
gtsam::utils.visual_isam.step
def step(data, isam, result, truth, currPoseIndex, isamArgs=())
Definition: visual_isam.py:82
values_view::~values_view
virtual ~values_view()=default
info
else if n * info
Definition: 3rdparty/Eigen/lapack/cholesky.cpp:18
get_type_info
PYBIND11_NOINLINE detail::type_info * get_type_info(PyTypeObject *type)
Definition: type_caster_base.h:188
cl
Definition: cxx11_tensor_builtins_sycl.cpp:30
vector_accessor
void vector_accessor(enable_if_t<!vector_needs_copy< Vector >::value, Class_ > &cl)
Definition: stl_bind.h:316
is_copy_constructible
Definition: type_caster_base.h:1024
PYBIND11_NAMESPACE
Definition: test_custom_type_casters.cpp:24
m
Matrix3f m
Definition: AngleAxis_mimic_euler.cpp:1
Eigen::Triplet< double >
items_view::~items_view
virtual ~items_view()=default
arg
EIGEN_DEVICE_FUNC const EIGEN_STRONG_INLINE ArgReturnType arg() const
Definition: ArrayCwiseUnaryOps.h:66
map_if_insertion_operator
void map_if_insertion_operator(const Args &...)
Definition: stl_bind.h:580
common.h
init
detail::initimpl::constructor< Args... > init()
Binds an existing constructor taking arguments Args...
Definition: pybind11.h:2006
KeysViewImpl::KeysViewImpl
KeysViewImpl(Map &map)
Definition: stl_bind.h:668
values_view
Definition: stl_bind.h:654
tree::f
Point2(* f)(const Point3 &, OptionalJacobian< 2, 3 >)
Definition: testExpression.cpp:218
items_view::len
virtual size_t len()=0
bind_map
class_< Map, holder_type > bind_map(handle scope, const std::string &name, Args &&...args)
Definition: stl_bind.h:700
ItemsViewImpl::len
size_t len() override
Definition: stl_bind.h:692
ValuesViewImpl::iter
iterator iter() override
Definition: stl_bind.h:685
iter
iterator iter(handle obj)
Definition: pytypes.h:2475
iterable
Definition: pytypes.h:1551
container_traits::test_value
static std::true_type test_value(typename T2::value_type *)
std
Definition: BFloat16.h:88
args
Definition: pytypes.h:2210
KeysViewImpl
Definition: stl_bind.h:667
buffer_info
Information record describing a Python buffer object.
Definition: buffer_info.h:46
p
float * p
Definition: Tutorial_Map_using.cpp:9
items_view::iter
virtual iterator iter()=0
keys_view::len
virtual size_t len()=0
keys_view::iter
virtual iterator iter()=0
v
Array< int, Dynamic, 1 > v
Definition: Array_initializer_list_vector_cxx11.cpp:1
if
if((m *x).isApprox(y))
Definition: FullPivLU_solve.cpp:6
len_hint
size_t len_hint(handle h)
Definition: pytypes.h:2456
keys_view
Definition: stl_bind.h:647
container_traits::is_pair
static constexpr const bool is_pair
Definition: stl_bind.h:44
len
size_t len(handle h)
Get the length of a Python object.
Definition: pytypes.h:2446
container_traits::is_element
static constexpr const bool is_element
Definition: stl_bind.h:47
recursive_bottom
Definition: type_caster_base.h:914
Eigen::placeholders::end
static const EIGEN_DEPRECATED end_t end
Definition: IndexedViewHelper.h:181
KeysViewImpl::iter
iterator iter() override
Definition: stl_bind.h:670
align_3::t
Point2 t(10, 10)
make_key_iterator
typing::Iterator< KeyType > make_key_iterator(Iterator first, Sentinel last, Extra &&...extra)
Definition: pybind11.h:2525
swap
int EIGEN_BLAS_FUNC() swap(int *n, RealScalar *px, int *incx, RealScalar *py, int *incy)
Definition: level1_impl.h:130
init
Definition: TutorialInplaceLU.cpp:2
Eigen::seq
internal::enable_if<!(symbolic::is_symbolic< FirstType >::value||symbolic::is_symbolic< LastType >::value), ArithmeticSequence< typename internal::cleanup_index_type< FirstType >::type, Index > >::type seq(FirstType f, LastType l)
Definition: ArithmeticSequence.h:234
ceres::Vector
Eigen::Matrix< double, Eigen::Dynamic, 1 > Vector
Definition: gtsam/3rdparty/ceres/eigen.h:38
enable_if_t
typename std::enable_if< B, T >::type enable_if_t
from cpp_future import (convenient aliases from C++14/17)
Definition: wrap/pybind11/include/pybind11/detail/common.h:654
operators.h
test_callbacks.value
value
Definition: test_callbacks.py:160
KeysViewImpl::map
Map & map
Definition: stl_bind.h:678
i
int i
Definition: BiCGSTAB_step_by_step.cpp:9
ItemsViewImpl::ItemsViewImpl
ItemsViewImpl(Map &map)
Definition: stl_bind.h:691
KeysViewImpl::contains
bool contains(const handle &k) override
Definition: stl_bind.h:671
values_view::iter
virtual iterator iter()=0
vector_modifiers
void vector_modifiers(const Args &...)
Definition: stl_bind.h:85
make_iterator
typing::Iterator< ValueType > make_iterator(Iterator first, Sentinel last, Extra &&...extra)
Makes a python iterator from a first and past-the-end C++ InputIterator.
Definition: pybind11.h:2507
args_any_are_buffer
constexpr bool args_any_are_buffer()
Definition: stl_bind.h:420
type_caster_base.h


gtsam
Author(s):
autogenerated on Sun Dec 22 2024 04:14:03