stl_bind.h 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  1. /*
  2. pybind11/std_bind.h: Binding generators for STL data types
  3. Copyright (c) 2016 Sergey Lyskov and Wenzel Jakob
  4. All rights reserved. Use of this source code is governed by a
  5. BSD-style license that can be found in the LICENSE file.
  6. */
  7. #pragma once
  8. #include "detail/common.h"
  9. #include "operators.h"
  10. #include <algorithm>
  11. #include <sstream>
  12. PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
  13. PYBIND11_NAMESPACE_BEGIN(detail)
  14. /* SFINAE helper class used by 'is_comparable */
  15. template <typename T> struct container_traits {
  16. template <typename T2> static std::true_type test_comparable(decltype(std::declval<const T2 &>() == std::declval<const T2 &>())*);
  17. template <typename T2> static std::false_type test_comparable(...);
  18. template <typename T2> static std::true_type test_value(typename T2::value_type *);
  19. template <typename T2> static std::false_type test_value(...);
  20. template <typename T2> static std::true_type test_pair(typename T2::first_type *, typename T2::second_type *);
  21. template <typename T2> static std::false_type test_pair(...);
  22. static constexpr const bool is_comparable = std::is_same<std::true_type, decltype(test_comparable<T>(nullptr))>::value;
  23. static constexpr const bool is_pair = std::is_same<std::true_type, decltype(test_pair<T>(nullptr, nullptr))>::value;
  24. static constexpr const bool is_vector = std::is_same<std::true_type, decltype(test_value<T>(nullptr))>::value;
  25. static constexpr const bool is_element = !is_pair && !is_vector;
  26. };
  27. /* Default: is_comparable -> std::false_type */
  28. template <typename T, typename SFINAE = void>
  29. struct is_comparable : std::false_type { };
  30. /* For non-map data structures, check whether operator== can be instantiated */
  31. template <typename T>
  32. struct is_comparable<
  33. T, enable_if_t<container_traits<T>::is_element &&
  34. container_traits<T>::is_comparable>>
  35. : std::true_type { };
  36. /* For a vector/map data structure, recursively check the value type (which is std::pair for maps) */
  37. template <typename T>
  38. struct is_comparable<T, enable_if_t<container_traits<T>::is_vector>> {
  39. static constexpr const bool value =
  40. is_comparable<typename T::value_type>::value;
  41. };
  42. /* For pairs, recursively check the two data types */
  43. template <typename T>
  44. struct is_comparable<T, enable_if_t<container_traits<T>::is_pair>> {
  45. static constexpr const bool value =
  46. is_comparable<typename T::first_type>::value &&
  47. is_comparable<typename T::second_type>::value;
  48. };
  49. /* Fallback functions */
  50. template <typename, typename, typename... Args> void vector_if_copy_constructible(const Args &...) { }
  51. template <typename, typename, typename... Args> void vector_if_equal_operator(const Args &...) { }
  52. template <typename, typename, typename... Args> void vector_if_insertion_operator(const Args &...) { }
  53. template <typename, typename, typename... Args> void vector_modifiers(const Args &...) { }
  54. template<typename Vector, typename Class_>
  55. void vector_if_copy_constructible(enable_if_t<is_copy_constructible<Vector>::value, Class_> &cl) {
  56. cl.def(init<const Vector &>(), "Copy constructor");
  57. }
  58. template<typename Vector, typename Class_>
  59. void vector_if_equal_operator(enable_if_t<is_comparable<Vector>::value, Class_> &cl) {
  60. using T = typename Vector::value_type;
  61. cl.def(self == self);
  62. cl.def(self != self);
  63. cl.def("count",
  64. [](const Vector &v, const T &x) {
  65. return std::count(v.begin(), v.end(), x);
  66. },
  67. arg("x"),
  68. "Return the number of times ``x`` appears in the list"
  69. );
  70. cl.def("remove", [](Vector &v, const T &x) {
  71. auto p = std::find(v.begin(), v.end(), x);
  72. if (p != v.end())
  73. v.erase(p);
  74. else
  75. throw value_error();
  76. },
  77. arg("x"),
  78. "Remove the first item from the list whose value is x. "
  79. "It is an error if there is no such item."
  80. );
  81. cl.def("__contains__",
  82. [](const Vector &v, const T &x) {
  83. return std::find(v.begin(), v.end(), x) != v.end();
  84. },
  85. arg("x"),
  86. "Return true the container contains ``x``"
  87. );
  88. }
  89. // Vector modifiers -- requires a copyable vector_type:
  90. // (Technically, some of these (pop and __delitem__) don't actually require copyability, but it seems
  91. // silly to allow deletion but not insertion, so include them here too.)
  92. template <typename Vector, typename Class_>
  93. void vector_modifiers(enable_if_t<is_copy_constructible<typename Vector::value_type>::value, Class_> &cl) {
  94. using T = typename Vector::value_type;
  95. using SizeType = typename Vector::size_type;
  96. using DiffType = typename Vector::difference_type;
  97. auto wrap_i = [](DiffType i, SizeType n) {
  98. if (i < 0)
  99. i += n;
  100. if (i < 0 || (SizeType)i >= n)
  101. throw index_error();
  102. return i;
  103. };
  104. cl.def("append",
  105. [](Vector &v, const T &value) { v.push_back(value); },
  106. arg("x"),
  107. "Add an item to the end of the list");
  108. cl.def(init([](iterable it) {
  109. auto v = std::unique_ptr<Vector>(new Vector());
  110. v->reserve(len_hint(it));
  111. for (handle h : it)
  112. v->push_back(h.cast<T>());
  113. return v.release();
  114. }));
  115. cl.def("clear",
  116. [](Vector &v) {
  117. v.clear();
  118. },
  119. "Clear the contents"
  120. );
  121. cl.def("extend",
  122. [](Vector &v, const Vector &src) {
  123. v.insert(v.end(), src.begin(), src.end());
  124. },
  125. arg("L"),
  126. "Extend the list by appending all the items in the given list"
  127. );
  128. cl.def("extend",
  129. [](Vector &v, iterable it) {
  130. const size_t old_size = v.size();
  131. v.reserve(old_size + len_hint(it));
  132. try {
  133. for (handle h : it) {
  134. v.push_back(h.cast<T>());
  135. }
  136. } catch (const cast_error &) {
  137. v.erase(v.begin() + static_cast<typename Vector::difference_type>(old_size), v.end());
  138. try {
  139. v.shrink_to_fit();
  140. } catch (const std::exception &) {
  141. // Do nothing
  142. }
  143. throw;
  144. }
  145. },
  146. arg("L"),
  147. "Extend the list by appending all the items in the given list"
  148. );
  149. cl.def("insert",
  150. [](Vector &v, DiffType i, const T &x) {
  151. // Can't use wrap_i; i == v.size() is OK
  152. if (i < 0)
  153. i += v.size();
  154. if (i < 0 || (SizeType)i > v.size())
  155. throw index_error();
  156. v.insert(v.begin() + i, x);
  157. },
  158. arg("i") , arg("x"),
  159. "Insert an item at a given position."
  160. );
  161. cl.def("pop",
  162. [](Vector &v) {
  163. if (v.empty())
  164. throw index_error();
  165. T t = v.back();
  166. v.pop_back();
  167. return t;
  168. },
  169. "Remove and return the last item"
  170. );
  171. cl.def("pop",
  172. [wrap_i](Vector &v, DiffType i) {
  173. i = wrap_i(i, v.size());
  174. T t = v[(SizeType) i];
  175. v.erase(v.begin() + i);
  176. return t;
  177. },
  178. arg("i"),
  179. "Remove and return the item at index ``i``"
  180. );
  181. cl.def("__setitem__",
  182. [wrap_i](Vector &v, DiffType i, const T &t) {
  183. i = wrap_i(i, v.size());
  184. v[(SizeType)i] = t;
  185. }
  186. );
  187. /// Slicing protocol
  188. cl.def("__getitem__",
  189. [](const Vector &v, slice slice) -> Vector * {
  190. size_t start, stop, step, slicelength;
  191. if (!slice.compute(v.size(), &start, &stop, &step, &slicelength))
  192. throw error_already_set();
  193. auto *seq = new Vector();
  194. seq->reserve((size_t) slicelength);
  195. for (size_t i=0; i<slicelength; ++i) {
  196. seq->push_back(v[start]);
  197. start += step;
  198. }
  199. return seq;
  200. },
  201. arg("s"),
  202. "Retrieve list elements using a slice object"
  203. );
  204. cl.def("__setitem__",
  205. [](Vector &v, slice slice, const Vector &value) {
  206. size_t start, stop, step, slicelength;
  207. if (!slice.compute(v.size(), &start, &stop, &step, &slicelength))
  208. throw error_already_set();
  209. if (slicelength != value.size())
  210. throw std::runtime_error("Left and right hand size of slice assignment have different sizes!");
  211. for (size_t i=0; i<slicelength; ++i) {
  212. v[start] = value[i];
  213. start += step;
  214. }
  215. },
  216. "Assign list elements using a slice object"
  217. );
  218. cl.def("__delitem__",
  219. [wrap_i](Vector &v, DiffType i) {
  220. i = wrap_i(i, v.size());
  221. v.erase(v.begin() + i);
  222. },
  223. "Delete the list elements at index ``i``"
  224. );
  225. cl.def("__delitem__",
  226. [](Vector &v, slice slice) {
  227. size_t start, stop, step, slicelength;
  228. if (!slice.compute(v.size(), &start, &stop, &step, &slicelength))
  229. throw error_already_set();
  230. if (step == 1 && false) {
  231. v.erase(v.begin() + (DiffType) start, v.begin() + DiffType(start + slicelength));
  232. } else {
  233. for (size_t i = 0; i < slicelength; ++i) {
  234. v.erase(v.begin() + DiffType(start));
  235. start += step - 1;
  236. }
  237. }
  238. },
  239. "Delete list elements using a slice object"
  240. );
  241. }
  242. // If the type has an operator[] that doesn't return a reference (most notably std::vector<bool>),
  243. // we have to access by copying; otherwise we return by reference.
  244. template <typename Vector> using vector_needs_copy = negation<
  245. std::is_same<decltype(std::declval<Vector>()[typename Vector::size_type()]), typename Vector::value_type &>>;
  246. // The usual case: access and iterate by reference
  247. template <typename Vector, typename Class_>
  248. void vector_accessor(enable_if_t<!vector_needs_copy<Vector>::value, Class_> &cl) {
  249. using T = typename Vector::value_type;
  250. using SizeType = typename Vector::size_type;
  251. using DiffType = typename Vector::difference_type;
  252. using ItType = typename Vector::iterator;
  253. auto wrap_i = [](DiffType i, SizeType n) {
  254. if (i < 0)
  255. i += n;
  256. if (i < 0 || (SizeType)i >= n)
  257. throw index_error();
  258. return i;
  259. };
  260. cl.def("__getitem__",
  261. [wrap_i](Vector &v, DiffType i) -> T & {
  262. i = wrap_i(i, v.size());
  263. return v[(SizeType)i];
  264. },
  265. return_value_policy::reference_internal // ref + keepalive
  266. );
  267. cl.def("__iter__",
  268. [](Vector &v) {
  269. return make_iterator<
  270. return_value_policy::reference_internal, ItType, ItType, T&>(
  271. v.begin(), v.end());
  272. },
  273. keep_alive<0, 1>() /* Essential: keep list alive while iterator exists */
  274. );
  275. }
  276. // The case for special objects, like std::vector<bool>, that have to be returned-by-copy:
  277. template <typename Vector, typename Class_>
  278. void vector_accessor(enable_if_t<vector_needs_copy<Vector>::value, Class_> &cl) {
  279. using T = typename Vector::value_type;
  280. using SizeType = typename Vector::size_type;
  281. using DiffType = typename Vector::difference_type;
  282. using ItType = typename Vector::iterator;
  283. cl.def("__getitem__",
  284. [](const Vector &v, DiffType i) -> T {
  285. if (i < 0 && (i += v.size()) < 0)
  286. throw index_error();
  287. if ((SizeType)i >= v.size())
  288. throw index_error();
  289. return v[(SizeType)i];
  290. }
  291. );
  292. cl.def("__iter__",
  293. [](Vector &v) {
  294. return make_iterator<
  295. return_value_policy::copy, ItType, ItType, T>(
  296. v.begin(), v.end());
  297. },
  298. keep_alive<0, 1>() /* Essential: keep list alive while iterator exists */
  299. );
  300. }
  301. template <typename Vector, typename Class_> auto vector_if_insertion_operator(Class_ &cl, std::string const &name)
  302. -> decltype(std::declval<std::ostream&>() << std::declval<typename Vector::value_type>(), void()) {
  303. using size_type = typename Vector::size_type;
  304. cl.def("__repr__",
  305. [name](Vector &v) {
  306. std::ostringstream s;
  307. s << name << '[';
  308. for (size_type i=0; i < v.size(); ++i) {
  309. s << v[i];
  310. if (i != v.size() - 1)
  311. s << ", ";
  312. }
  313. s << ']';
  314. return s.str();
  315. },
  316. "Return the canonical string representation of this list."
  317. );
  318. }
  319. // Provide the buffer interface for vectors if we have data() and we have a format for it
  320. // GCC seems to have "void std::vector<bool>::data()" - doing SFINAE on the existence of data() is insufficient, we need to check it returns an appropriate pointer
  321. template <typename Vector, typename = void>
  322. struct vector_has_data_and_format : std::false_type {};
  323. template <typename Vector>
  324. struct vector_has_data_and_format<Vector, enable_if_t<std::is_same<decltype(format_descriptor<typename Vector::value_type>::format(), std::declval<Vector>().data()), typename Vector::value_type*>::value>> : std::true_type {};
  325. // [workaround(intel)] Separate function required here
  326. // Workaround as the Intel compiler does not compile the enable_if_t part below
  327. // (tested with icc (ICC) 2021.1 Beta 20200827)
  328. template <typename... Args>
  329. constexpr bool args_any_are_buffer() {
  330. return detail::any_of<std::is_same<Args, buffer_protocol>...>::value;
  331. }
  332. // [workaround(intel)] Separate function required here
  333. // [workaround(msvc)] Can't use constexpr bool in return type
  334. // Add the buffer interface to a vector
  335. template <typename Vector, typename Class_, typename... Args>
  336. void vector_buffer_impl(Class_& cl, std::true_type) {
  337. using T = typename Vector::value_type;
  338. static_assert(vector_has_data_and_format<Vector>::value, "There is not an appropriate format descriptor for this vector");
  339. // numpy.h declares this for arbitrary types, but it may raise an exception and crash hard at runtime if PYBIND11_NUMPY_DTYPE hasn't been called, so check here
  340. format_descriptor<T>::format();
  341. cl.def_buffer([](Vector& v) -> buffer_info {
  342. return buffer_info(v.data(), static_cast<ssize_t>(sizeof(T)), format_descriptor<T>::format(), 1, {v.size()}, {sizeof(T)});
  343. });
  344. cl.def(init([](buffer buf) {
  345. auto info = buf.request();
  346. if (info.ndim != 1 || info.strides[0] % static_cast<ssize_t>(sizeof(T)))
  347. throw type_error("Only valid 1D buffers can be copied to a vector");
  348. if (!detail::compare_buffer_info<T>::compare(info) || (ssize_t) sizeof(T) != info.itemsize)
  349. throw type_error("Format mismatch (Python: " + info.format + " C++: " + format_descriptor<T>::format() + ")");
  350. T *p = static_cast<T*>(info.ptr);
  351. ssize_t step = info.strides[0] / static_cast<ssize_t>(sizeof(T));
  352. T *end = p + info.shape[0] * step;
  353. if (step == 1) {
  354. return Vector(p, end);
  355. }
  356. else {
  357. Vector vec;
  358. vec.reserve((size_t) info.shape[0]);
  359. for (; p != end; p += step)
  360. vec.push_back(*p);
  361. return vec;
  362. }
  363. }));
  364. return;
  365. }
  366. template <typename Vector, typename Class_, typename... Args>
  367. void vector_buffer_impl(Class_&, std::false_type) {}
  368. template <typename Vector, typename Class_, typename... Args>
  369. void vector_buffer(Class_& cl) {
  370. vector_buffer_impl<Vector, Class_, Args...>(cl, detail::any_of<std::is_same<Args, buffer_protocol>...>{});
  371. }
  372. PYBIND11_NAMESPACE_END(detail)
  373. //
  374. // std::vector
  375. //
  376. template <typename Vector, typename holder_type = std::unique_ptr<Vector>, typename... Args>
  377. class_<Vector, holder_type> bind_vector(handle scope, std::string const &name, Args&&... args) {
  378. using Class_ = class_<Vector, holder_type>;
  379. // If the value_type is unregistered (e.g. a converting type) or is itself registered
  380. // module-local then make the vector binding module-local as well:
  381. using vtype = typename Vector::value_type;
  382. auto vtype_info = detail::get_type_info(typeid(vtype));
  383. bool local = !vtype_info || vtype_info->module_local;
  384. Class_ cl(scope, name.c_str(), pybind11::module_local(local), std::forward<Args>(args)...);
  385. // Declare the buffer interface if a buffer_protocol() is passed in
  386. detail::vector_buffer<Vector, Class_, Args...>(cl);
  387. cl.def(init<>());
  388. // Register copy constructor (if possible)
  389. detail::vector_if_copy_constructible<Vector, Class_>(cl);
  390. // Register comparison-related operators and functions (if possible)
  391. detail::vector_if_equal_operator<Vector, Class_>(cl);
  392. // Register stream insertion operator (if possible)
  393. detail::vector_if_insertion_operator<Vector, Class_>(cl, name);
  394. // Modifiers require copyable vector value type
  395. detail::vector_modifiers<Vector, Class_>(cl);
  396. // Accessor and iterator; return by value if copyable, otherwise we return by ref + keep-alive
  397. detail::vector_accessor<Vector, Class_>(cl);
  398. cl.def("__bool__",
  399. [](const Vector &v) -> bool {
  400. return !v.empty();
  401. },
  402. "Check whether the list is nonempty"
  403. );
  404. cl.def("__len__", &Vector::size);
  405. #if 0
  406. // C++ style functions deprecated, leaving it here as an example
  407. cl.def(init<size_type>());
  408. cl.def("resize",
  409. (void (Vector::*) (size_type count)) & Vector::resize,
  410. "changes the number of elements stored");
  411. cl.def("erase",
  412. [](Vector &v, SizeType i) {
  413. if (i >= v.size())
  414. throw index_error();
  415. v.erase(v.begin() + i);
  416. }, "erases element at index ``i``");
  417. cl.def("empty", &Vector::empty, "checks whether the container is empty");
  418. cl.def("size", &Vector::size, "returns the number of elements");
  419. cl.def("push_back", (void (Vector::*)(const T&)) &Vector::push_back, "adds an element to the end");
  420. cl.def("pop_back", &Vector::pop_back, "removes the last element");
  421. cl.def("max_size", &Vector::max_size, "returns the maximum possible number of elements");
  422. cl.def("reserve", &Vector::reserve, "reserves storage");
  423. cl.def("capacity", &Vector::capacity, "returns the number of elements that can be held in currently allocated storage");
  424. cl.def("shrink_to_fit", &Vector::shrink_to_fit, "reduces memory usage by freeing unused memory");
  425. cl.def("clear", &Vector::clear, "clears the contents");
  426. cl.def("swap", &Vector::swap, "swaps the contents");
  427. cl.def("front", [](Vector &v) {
  428. if (v.size()) return v.front();
  429. else throw index_error();
  430. }, "access the first element");
  431. cl.def("back", [](Vector &v) {
  432. if (v.size()) return v.back();
  433. else throw index_error();
  434. }, "access the last element ");
  435. #endif
  436. return cl;
  437. }
  438. //
  439. // std::map, std::unordered_map
  440. //
  441. PYBIND11_NAMESPACE_BEGIN(detail)
  442. /* Fallback functions */
  443. template <typename, typename, typename... Args> void map_if_insertion_operator(const Args &...) { }
  444. template <typename, typename, typename... Args> void map_assignment(const Args &...) { }
  445. // Map assignment when copy-assignable: just copy the value
  446. template <typename Map, typename Class_>
  447. void map_assignment(enable_if_t<is_copy_assignable<typename Map::mapped_type>::value, Class_> &cl) {
  448. using KeyType = typename Map::key_type;
  449. using MappedType = typename Map::mapped_type;
  450. cl.def("__setitem__",
  451. [](Map &m, const KeyType &k, const MappedType &v) {
  452. auto it = m.find(k);
  453. if (it != m.end()) it->second = v;
  454. else m.emplace(k, v);
  455. }
  456. );
  457. }
  458. // Not copy-assignable, but still copy-constructible: we can update the value by erasing and reinserting
  459. template<typename Map, typename Class_>
  460. void map_assignment(enable_if_t<
  461. !is_copy_assignable<typename Map::mapped_type>::value &&
  462. is_copy_constructible<typename Map::mapped_type>::value,
  463. Class_> &cl) {
  464. using KeyType = typename Map::key_type;
  465. using MappedType = typename Map::mapped_type;
  466. cl.def("__setitem__",
  467. [](Map &m, const KeyType &k, const MappedType &v) {
  468. // We can't use m[k] = v; because value type might not be default constructable
  469. auto r = m.emplace(k, v);
  470. if (!r.second) {
  471. // value type is not copy assignable so the only way to insert it is to erase it first...
  472. m.erase(r.first);
  473. m.emplace(k, v);
  474. }
  475. }
  476. );
  477. }
  478. template <typename Map, typename Class_> auto map_if_insertion_operator(Class_ &cl, std::string const &name)
  479. -> decltype(std::declval<std::ostream&>() << std::declval<typename Map::key_type>() << std::declval<typename Map::mapped_type>(), void()) {
  480. cl.def("__repr__",
  481. [name](Map &m) {
  482. std::ostringstream s;
  483. s << name << '{';
  484. bool f = false;
  485. for (auto const &kv : m) {
  486. if (f)
  487. s << ", ";
  488. s << kv.first << ": " << kv.second;
  489. f = true;
  490. }
  491. s << '}';
  492. return s.str();
  493. },
  494. "Return the canonical string representation of this map."
  495. );
  496. }
  497. PYBIND11_NAMESPACE_END(detail)
  498. template <typename Map, typename holder_type = std::unique_ptr<Map>, typename... Args>
  499. class_<Map, holder_type> bind_map(handle scope, const std::string &name, Args&&... args) {
  500. using KeyType = typename Map::key_type;
  501. using MappedType = typename Map::mapped_type;
  502. using Class_ = class_<Map, holder_type>;
  503. // If either type is a non-module-local bound type then make the map binding non-local as well;
  504. // otherwise (e.g. both types are either module-local or converting) the map will be
  505. // module-local.
  506. auto tinfo = detail::get_type_info(typeid(MappedType));
  507. bool local = !tinfo || tinfo->module_local;
  508. if (local) {
  509. tinfo = detail::get_type_info(typeid(KeyType));
  510. local = !tinfo || tinfo->module_local;
  511. }
  512. Class_ cl(scope, name.c_str(), pybind11::module_local(local), std::forward<Args>(args)...);
  513. cl.def(init<>());
  514. // Register stream insertion operator (if possible)
  515. detail::map_if_insertion_operator<Map, Class_>(cl, name);
  516. cl.def("__bool__",
  517. [](const Map &m) -> bool { return !m.empty(); },
  518. "Check whether the map is nonempty"
  519. );
  520. cl.def("__iter__",
  521. [](Map &m) { return make_key_iterator(m.begin(), m.end()); },
  522. keep_alive<0, 1>() /* Essential: keep list alive while iterator exists */
  523. );
  524. cl.def("items",
  525. [](Map &m) { return make_iterator(m.begin(), m.end()); },
  526. keep_alive<0, 1>() /* Essential: keep list alive while iterator exists */
  527. );
  528. cl.def("__getitem__",
  529. [](Map &m, const KeyType &k) -> MappedType & {
  530. auto it = m.find(k);
  531. if (it == m.end())
  532. throw key_error();
  533. return it->second;
  534. },
  535. return_value_policy::reference_internal // ref + keepalive
  536. );
  537. cl.def("__contains__",
  538. [](Map &m, const KeyType &k) -> bool {
  539. auto it = m.find(k);
  540. if (it == m.end())
  541. return false;
  542. return true;
  543. }
  544. );
  545. // Assignment provided only if the type is copyable
  546. detail::map_assignment<Map, Class_>(cl);
  547. cl.def("__delitem__",
  548. [](Map &m, const KeyType &k) {
  549. auto it = m.find(k);
  550. if (it == m.end())
  551. throw key_error();
  552. m.erase(it);
  553. }
  554. );
  555. cl.def("__len__", &Map::size);
  556. return cl;
  557. }
  558. PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)