File indexing completed on 2025-01-18 10:06:18
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #pragma once
0011
0012 #include "detail/common.h"
0013 #include "detail/type_caster_base.h"
0014 #include "cast.h"
0015 #include "operators.h"
0016
0017 #include <algorithm>
0018 #include <sstream>
0019 #include <type_traits>
0020
0021 PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
0022 PYBIND11_NAMESPACE_BEGIN(detail)
0023
0024
0025 template <typename T>
0026 struct container_traits {
0027 template <typename T2>
0028 static std::true_type
0029 test_comparable(decltype(std::declval<const T2 &>() == std::declval<const T2 &>()) *);
0030 template <typename T2>
0031 static std::false_type test_comparable(...);
0032 template <typename T2>
0033 static std::true_type test_value(typename T2::value_type *);
0034 template <typename T2>
0035 static std::false_type test_value(...);
0036 template <typename T2>
0037 static std::true_type test_pair(typename T2::first_type *, typename T2::second_type *);
0038 template <typename T2>
0039 static std::false_type test_pair(...);
0040
0041 static constexpr const bool is_comparable
0042 = std::is_same<std::true_type, decltype(test_comparable<T>(nullptr))>::value;
0043 static constexpr const bool is_pair
0044 = std::is_same<std::true_type, decltype(test_pair<T>(nullptr, nullptr))>::value;
0045 static constexpr const bool is_vector
0046 = std::is_same<std::true_type, decltype(test_value<T>(nullptr))>::value;
0047 static constexpr const bool is_element = !is_pair && !is_vector;
0048 };
0049
0050
0051 template <typename T, typename SFINAE = void>
0052 struct is_comparable : std::false_type {};
0053
0054
0055 template <typename T>
0056 struct is_comparable<
0057 T,
0058 enable_if_t<container_traits<T>::is_element && container_traits<T>::is_comparable>>
0059 : std::true_type {};
0060
0061
0062
0063 template <typename T>
0064 struct is_comparable<T, enable_if_t<container_traits<T>::is_vector>>
0065 : is_comparable<typename recursive_container_traits<T>::type_to_check_recursively> {};
0066
0067 template <>
0068 struct is_comparable<recursive_bottom> : std::true_type {};
0069
0070
0071 template <typename T>
0072 struct is_comparable<T, enable_if_t<container_traits<T>::is_pair>> {
0073 static constexpr const bool value = is_comparable<typename T::first_type>::value
0074 && is_comparable<typename T::second_type>::value;
0075 };
0076
0077
0078 template <typename, typename, typename... Args>
0079 void vector_if_copy_constructible(const Args &...) {}
0080 template <typename, typename, typename... Args>
0081 void vector_if_equal_operator(const Args &...) {}
0082 template <typename, typename, typename... Args>
0083 void vector_if_insertion_operator(const Args &...) {}
0084 template <typename, typename, typename... Args>
0085 void vector_modifiers(const Args &...) {}
0086
0087 template <typename Vector, typename Class_>
0088 void vector_if_copy_constructible(enable_if_t<is_copy_constructible<Vector>::value, Class_> &cl) {
0089 cl.def(init<const Vector &>(), "Copy constructor");
0090 }
0091
0092 template <typename Vector, typename Class_>
0093 void vector_if_equal_operator(enable_if_t<is_comparable<Vector>::value, Class_> &cl) {
0094 using T = typename Vector::value_type;
0095
0096 cl.def(self == self);
0097 cl.def(self != self);
0098
0099 cl.def(
0100 "count",
0101 [](const Vector &v, const T &x) { return std::count(v.begin(), v.end(), x); },
0102 arg("x"),
0103 "Return the number of times ``x`` appears in the list");
0104
0105 cl.def(
0106 "remove",
0107 [](Vector &v, const T &x) {
0108 auto p = std::find(v.begin(), v.end(), x);
0109 if (p != v.end()) {
0110 v.erase(p);
0111 } else {
0112 throw value_error();
0113 }
0114 },
0115 arg("x"),
0116 "Remove the first item from the list whose value is x. "
0117 "It is an error if there is no such item.");
0118
0119 cl.def(
0120 "__contains__",
0121 [](const Vector &v, const T &x) { return std::find(v.begin(), v.end(), x) != v.end(); },
0122 arg("x"),
0123 "Return true the container contains ``x``");
0124 }
0125
0126
0127
0128
0129 template <typename Vector, typename Class_>
0130 void vector_modifiers(
0131 enable_if_t<is_copy_constructible<typename Vector::value_type>::value, Class_> &cl) {
0132 using T = typename Vector::value_type;
0133 using SizeType = typename Vector::size_type;
0134 using DiffType = typename Vector::difference_type;
0135
0136 auto wrap_i = [](DiffType i, SizeType n) {
0137 if (i < 0) {
0138 i += n;
0139 }
0140 if (i < 0 || (SizeType) i >= n) {
0141 throw index_error();
0142 }
0143 return i;
0144 };
0145
0146 cl.def(
0147 "append",
0148 [](Vector &v, const T &value) { v.push_back(value); },
0149 arg("x"),
0150 "Add an item to the end of the list");
0151
0152 cl.def(init([](const iterable &it) {
0153 auto v = std::unique_ptr<Vector>(new Vector());
0154 v->reserve(len_hint(it));
0155 for (handle h : it) {
0156 v->push_back(h.cast<T>());
0157 }
0158 return v.release();
0159 }));
0160
0161 cl.def("clear", [](Vector &v) { v.clear(); }, "Clear the contents");
0162
0163 cl.def(
0164 "extend",
0165 [](Vector &v, const Vector &src) { v.insert(v.end(), src.begin(), src.end()); },
0166 arg("L"),
0167 "Extend the list by appending all the items in the given list");
0168
0169 cl.def(
0170 "extend",
0171 [](Vector &v, const iterable &it) {
0172 const size_t old_size = v.size();
0173 v.reserve(old_size + len_hint(it));
0174 try {
0175 for (handle h : it) {
0176 v.push_back(h.cast<T>());
0177 }
0178 } catch (const cast_error &) {
0179 v.erase(v.begin() + static_cast<typename Vector::difference_type>(old_size),
0180 v.end());
0181 try {
0182 v.shrink_to_fit();
0183 } catch (const std::exception &) {
0184
0185 }
0186 throw;
0187 }
0188 },
0189 arg("L"),
0190 "Extend the list by appending all the items in the given list");
0191
0192 cl.def(
0193 "insert",
0194 [](Vector &v, DiffType i, const T &x) {
0195
0196 if (i < 0) {
0197 i += v.size();
0198 }
0199 if (i < 0 || (SizeType) i > v.size()) {
0200 throw index_error();
0201 }
0202 v.insert(v.begin() + i, x);
0203 },
0204 arg("i"),
0205 arg("x"),
0206 "Insert an item at a given position.");
0207
0208 cl.def(
0209 "pop",
0210 [](Vector &v) {
0211 if (v.empty()) {
0212 throw index_error();
0213 }
0214 T t = std::move(v.back());
0215 v.pop_back();
0216 return t;
0217 },
0218 "Remove and return the last item");
0219
0220 cl.def(
0221 "pop",
0222 [wrap_i](Vector &v, DiffType i) {
0223 i = wrap_i(i, v.size());
0224 T t = std::move(v[(SizeType) i]);
0225 v.erase(std::next(v.begin(), i));
0226 return t;
0227 },
0228 arg("i"),
0229 "Remove and return the item at index ``i``");
0230
0231 cl.def("__setitem__", [wrap_i](Vector &v, DiffType i, const T &t) {
0232 i = wrap_i(i, v.size());
0233 v[(SizeType) i] = t;
0234 });
0235
0236
0237 cl.def(
0238 "__getitem__",
0239 [](const Vector &v, const slice &slice) -> Vector * {
0240 size_t start = 0, stop = 0, step = 0, slicelength = 0;
0241
0242 if (!slice.compute(v.size(), &start, &stop, &step, &slicelength)) {
0243 throw error_already_set();
0244 }
0245
0246 auto *seq = new Vector();
0247 seq->reserve((size_t) slicelength);
0248
0249 for (size_t i = 0; i < slicelength; ++i) {
0250 seq->push_back(v[start]);
0251 start += step;
0252 }
0253 return seq;
0254 },
0255 arg("s"),
0256 "Retrieve list elements using a slice object");
0257
0258 cl.def(
0259 "__setitem__",
0260 [](Vector &v, const slice &slice, const Vector &value) {
0261 size_t start = 0, stop = 0, step = 0, slicelength = 0;
0262 if (!slice.compute(v.size(), &start, &stop, &step, &slicelength)) {
0263 throw error_already_set();
0264 }
0265
0266 if (slicelength != value.size()) {
0267 throw std::runtime_error(
0268 "Left and right hand size of slice assignment have different sizes!");
0269 }
0270
0271 for (size_t i = 0; i < slicelength; ++i) {
0272 v[start] = value[i];
0273 start += step;
0274 }
0275 },
0276 "Assign list elements using a slice object");
0277
0278 cl.def(
0279 "__delitem__",
0280 [wrap_i](Vector &v, DiffType i) {
0281 i = wrap_i(i, v.size());
0282 v.erase(v.begin() + i);
0283 },
0284 "Delete the list elements at index ``i``");
0285
0286 cl.def(
0287 "__delitem__",
0288 [](Vector &v, const slice &slice) {
0289 size_t start = 0, stop = 0, step = 0, slicelength = 0;
0290
0291 if (!slice.compute(v.size(), &start, &stop, &step, &slicelength)) {
0292 throw error_already_set();
0293 }
0294
0295 if (step == 1 && false) {
0296 v.erase(v.begin() + (DiffType) start, v.begin() + DiffType(start + slicelength));
0297 } else {
0298 for (size_t i = 0; i < slicelength; ++i) {
0299 v.erase(v.begin() + DiffType(start));
0300 start += step - 1;
0301 }
0302 }
0303 },
0304 "Delete list elements using a slice object");
0305 }
0306
0307
0308
0309 template <typename Vector>
0310 using vector_needs_copy
0311 = negation<std::is_same<decltype(std::declval<Vector>()[typename Vector::size_type()]),
0312 typename Vector::value_type &>>;
0313
0314
0315 template <typename Vector, typename Class_>
0316 void vector_accessor(enable_if_t<!vector_needs_copy<Vector>::value, Class_> &cl) {
0317 using T = typename Vector::value_type;
0318 using SizeType = typename Vector::size_type;
0319 using DiffType = typename Vector::difference_type;
0320 using ItType = typename Vector::iterator;
0321
0322 auto wrap_i = [](DiffType i, SizeType n) {
0323 if (i < 0) {
0324 i += n;
0325 }
0326 if (i < 0 || (SizeType) i >= n) {
0327 throw index_error();
0328 }
0329 return i;
0330 };
0331
0332 cl.def(
0333 "__getitem__",
0334 [wrap_i](Vector &v, DiffType i) -> T & {
0335 i = wrap_i(i, v.size());
0336 return v[(SizeType) i];
0337 },
0338 return_value_policy::reference_internal
0339 );
0340
0341 cl.def(
0342 "__iter__",
0343 [](Vector &v) {
0344 return make_iterator<return_value_policy::reference_internal, ItType, ItType, T &>(
0345 v.begin(), v.end());
0346 },
0347 keep_alive<0, 1>()
0348 );
0349 }
0350
0351
0352 template <typename Vector, typename Class_>
0353 void vector_accessor(enable_if_t<vector_needs_copy<Vector>::value, Class_> &cl) {
0354 using T = typename Vector::value_type;
0355 using SizeType = typename Vector::size_type;
0356 using DiffType = typename Vector::difference_type;
0357 using ItType = typename Vector::iterator;
0358 cl.def("__getitem__", [](const Vector &v, DiffType i) -> T {
0359 if (i < 0) {
0360 i += v.size();
0361 if (i < 0) {
0362 throw index_error();
0363 }
0364 }
0365 auto i_st = static_cast<SizeType>(i);
0366 if (i_st >= v.size()) {
0367 throw index_error();
0368 }
0369 return v[i_st];
0370 });
0371
0372 cl.def(
0373 "__iter__",
0374 [](Vector &v) {
0375 return make_iterator<return_value_policy::copy, ItType, ItType, T>(v.begin(), v.end());
0376 },
0377 keep_alive<0, 1>()
0378 );
0379 }
0380
0381 template <typename Vector, typename Class_>
0382 auto vector_if_insertion_operator(Class_ &cl, std::string const &name)
0383 -> decltype(std::declval<std::ostream &>() << std::declval<typename Vector::value_type>(),
0384 void()) {
0385 using size_type = typename Vector::size_type;
0386
0387 cl.def(
0388 "__repr__",
0389 [name](Vector &v) {
0390 std::ostringstream s;
0391 s << name << '[';
0392 for (size_type i = 0; i < v.size(); ++i) {
0393 s << v[i];
0394 if (i != v.size() - 1) {
0395 s << ", ";
0396 }
0397 }
0398 s << ']';
0399 return s.str();
0400 },
0401 "Return the canonical string representation of this list.");
0402 }
0403
0404
0405
0406
0407 template <typename Vector, typename = void>
0408 struct vector_has_data_and_format : std::false_type {};
0409 template <typename Vector>
0410 struct vector_has_data_and_format<
0411 Vector,
0412 enable_if_t<std::is_same<decltype(format_descriptor<typename Vector::value_type>::format(),
0413 std::declval<Vector>().data()),
0414 typename Vector::value_type *>::value>> : std::true_type {};
0415
0416
0417
0418
0419 template <typename... Args>
0420 constexpr bool args_any_are_buffer() {
0421 return detail::any_of<std::is_same<Args, buffer_protocol>...>::value;
0422 }
0423
0424
0425
0426
0427
0428 template <typename Vector, typename Class_, typename... Args>
0429 void vector_buffer_impl(Class_ &cl, std::true_type) {
0430 using T = typename Vector::value_type;
0431
0432 static_assert(vector_has_data_and_format<Vector>::value,
0433 "There is not an appropriate format descriptor for this vector");
0434
0435
0436
0437 format_descriptor<T>::format();
0438
0439 cl.def_buffer([](Vector &v) -> buffer_info {
0440 return buffer_info(v.data(),
0441 static_cast<ssize_t>(sizeof(T)),
0442 format_descriptor<T>::format(),
0443 1,
0444 {v.size()},
0445 {sizeof(T)});
0446 });
0447
0448 cl.def(init([](const buffer &buf) {
0449 auto info = buf.request();
0450 if (info.ndim != 1 || info.strides[0] % static_cast<ssize_t>(sizeof(T))) {
0451 throw type_error("Only valid 1D buffers can be copied to a vector");
0452 }
0453 if (!detail::compare_buffer_info<T>::compare(info)
0454 || (ssize_t) sizeof(T) != info.itemsize) {
0455 throw type_error("Format mismatch (Python: " + info.format
0456 + " C++: " + format_descriptor<T>::format() + ")");
0457 }
0458
0459 T *p = static_cast<T *>(info.ptr);
0460 ssize_t step = info.strides[0] / static_cast<ssize_t>(sizeof(T));
0461 T *end = p + info.shape[0] * step;
0462 if (step == 1) {
0463 return Vector(p, end);
0464 }
0465 Vector vec;
0466 vec.reserve((size_t) info.shape[0]);
0467 for (; p != end; p += step) {
0468 vec.push_back(*p);
0469 }
0470 return vec;
0471 }));
0472
0473 return;
0474 }
0475
0476 template <typename Vector, typename Class_, typename... Args>
0477 void vector_buffer_impl(Class_ &, std::false_type) {}
0478
0479 template <typename Vector, typename Class_, typename... Args>
0480 void vector_buffer(Class_ &cl) {
0481 vector_buffer_impl<Vector, Class_, Args...>(
0482 cl, detail::any_of<std::is_same<Args, buffer_protocol>...>{});
0483 }
0484
0485 PYBIND11_NAMESPACE_END(detail)
0486
0487
0488
0489
0490 template <typename Vector, typename holder_type = std::unique_ptr<Vector>, typename... Args>
0491 class_<Vector, holder_type> bind_vector(handle scope, std::string const &name, Args &&...args) {
0492 using Class_ = class_<Vector, holder_type>;
0493
0494
0495
0496 using vtype = typename Vector::value_type;
0497 auto *vtype_info = detail::get_type_info(typeid(vtype));
0498 bool local = !vtype_info || vtype_info->module_local;
0499
0500 Class_ cl(scope, name.c_str(), pybind11::module_local(local), std::forward<Args>(args)...);
0501
0502
0503 detail::vector_buffer<Vector, Class_, Args...>(cl);
0504
0505 cl.def(init<>());
0506
0507
0508 detail::vector_if_copy_constructible<Vector, Class_>(cl);
0509
0510
0511 detail::vector_if_equal_operator<Vector, Class_>(cl);
0512
0513
0514 detail::vector_if_insertion_operator<Vector, Class_>(cl, name);
0515
0516
0517 detail::vector_modifiers<Vector, Class_>(cl);
0518
0519
0520 detail::vector_accessor<Vector, Class_>(cl);
0521
0522 cl.def(
0523 "__bool__",
0524 [](const Vector &v) -> bool { return !v.empty(); },
0525 "Check whether the list is nonempty");
0526
0527 cl.def("__len__", [](const Vector &vec) { return vec.size(); });
0528
0529 #if 0
0530
0531 cl.def(init<size_type>());
0532
0533 cl.def("resize",
0534 (void (Vector::*) (size_type count)) & Vector::resize,
0535 "changes the number of elements stored");
0536
0537 cl.def("erase",
0538 [](Vector &v, SizeType i) {
0539 if (i >= v.size())
0540 throw index_error();
0541 v.erase(v.begin() + i);
0542 }, "erases element at index ``i``");
0543
0544 cl.def("empty", &Vector::empty, "checks whether the container is empty");
0545 cl.def("size", &Vector::size, "returns the number of elements");
0546 cl.def("push_back", (void (Vector::*)(const T&)) &Vector::push_back, "adds an element to the end");
0547 cl.def("pop_back", &Vector::pop_back, "removes the last element");
0548
0549 cl.def("max_size", &Vector::max_size, "returns the maximum possible number of elements");
0550 cl.def("reserve", &Vector::reserve, "reserves storage");
0551 cl.def("capacity", &Vector::capacity, "returns the number of elements that can be held in currently allocated storage");
0552 cl.def("shrink_to_fit", &Vector::shrink_to_fit, "reduces memory usage by freeing unused memory");
0553
0554 cl.def("clear", &Vector::clear, "clears the contents");
0555 cl.def("swap", &Vector::swap, "swaps the contents");
0556
0557 cl.def("front", [](Vector &v) {
0558 if (v.size()) return v.front();
0559 else throw index_error();
0560 }, "access the first element");
0561
0562 cl.def("back", [](Vector &v) {
0563 if (v.size()) return v.back();
0564 else throw index_error();
0565 }, "access the last element ");
0566
0567 #endif
0568
0569 return cl;
0570 }
0571
0572
0573
0574
0575
0576 PYBIND11_NAMESPACE_BEGIN(detail)
0577
0578
0579 template <typename, typename, typename... Args>
0580 void map_if_insertion_operator(const Args &...) {}
0581 template <typename, typename, typename... Args>
0582 void map_assignment(const Args &...) {}
0583
0584
0585 template <typename Map, typename Class_>
0586 void map_assignment(
0587 enable_if_t<is_copy_assignable<typename Map::mapped_type>::value, Class_> &cl) {
0588 using KeyType = typename Map::key_type;
0589 using MappedType = typename Map::mapped_type;
0590
0591 cl.def("__setitem__", [](Map &m, const KeyType &k, const MappedType &v) {
0592 auto it = m.find(k);
0593 if (it != m.end()) {
0594 it->second = v;
0595 } else {
0596 m.emplace(k, v);
0597 }
0598 });
0599 }
0600
0601
0602
0603 template <typename Map, typename Class_>
0604 void map_assignment(enable_if_t<!is_copy_assignable<typename Map::mapped_type>::value
0605 && is_copy_constructible<typename Map::mapped_type>::value,
0606 Class_> &cl) {
0607 using KeyType = typename Map::key_type;
0608 using MappedType = typename Map::mapped_type;
0609
0610 cl.def("__setitem__", [](Map &m, const KeyType &k, const MappedType &v) {
0611
0612 auto r = m.emplace(k, v);
0613 if (!r.second) {
0614
0615
0616 m.erase(r.first);
0617 m.emplace(k, v);
0618 }
0619 });
0620 }
0621
0622 template <typename Map, typename Class_>
0623 auto map_if_insertion_operator(Class_ &cl, std::string const &name)
0624 -> decltype(std::declval<std::ostream &>() << std::declval<typename Map::key_type>()
0625 << std::declval<typename Map::mapped_type>(),
0626 void()) {
0627
0628 cl.def(
0629 "__repr__",
0630 [name](Map &m) {
0631 std::ostringstream s;
0632 s << name << '{';
0633 bool f = false;
0634 for (auto const &kv : m) {
0635 if (f) {
0636 s << ", ";
0637 }
0638 s << kv.first << ": " << kv.second;
0639 f = true;
0640 }
0641 s << '}';
0642 return s.str();
0643 },
0644 "Return the canonical string representation of this map.");
0645 }
0646
0647 struct keys_view {
0648 virtual size_t len() = 0;
0649 virtual iterator iter() = 0;
0650 virtual bool contains(const handle &k) = 0;
0651 virtual ~keys_view() = default;
0652 };
0653
0654 struct values_view {
0655 virtual size_t len() = 0;
0656 virtual iterator iter() = 0;
0657 virtual ~values_view() = default;
0658 };
0659
0660 struct items_view {
0661 virtual size_t len() = 0;
0662 virtual iterator iter() = 0;
0663 virtual ~items_view() = default;
0664 };
0665
0666 template <typename Map>
0667 struct KeysViewImpl : public detail::keys_view {
0668 explicit KeysViewImpl(Map &map) : map(map) {}
0669 size_t len() override { return map.size(); }
0670 iterator iter() override { return make_key_iterator(map.begin(), map.end()); }
0671 bool contains(const handle &k) override {
0672 try {
0673 return map.find(k.template cast<typename Map::key_type>()) != map.end();
0674 } catch (const cast_error &) {
0675 return false;
0676 }
0677 }
0678 Map ↦
0679 };
0680
0681 template <typename Map>
0682 struct ValuesViewImpl : public detail::values_view {
0683 explicit ValuesViewImpl(Map &map) : map(map) {}
0684 size_t len() override { return map.size(); }
0685 iterator iter() override { return make_value_iterator(map.begin(), map.end()); }
0686 Map ↦
0687 };
0688
0689 template <typename Map>
0690 struct ItemsViewImpl : public detail::items_view {
0691 explicit ItemsViewImpl(Map &map) : map(map) {}
0692 size_t len() override { return map.size(); }
0693 iterator iter() override { return make_iterator(map.begin(), map.end()); }
0694 Map ↦
0695 };
0696
0697 PYBIND11_NAMESPACE_END(detail)
0698
0699 template <typename Map, typename holder_type = std::unique_ptr<Map>, typename... Args>
0700 class_<Map, holder_type> bind_map(handle scope, const std::string &name, Args &&...args) {
0701 using KeyType = typename Map::key_type;
0702 using MappedType = typename Map::mapped_type;
0703 using KeysView = detail::keys_view;
0704 using ValuesView = detail::values_view;
0705 using ItemsView = detail::items_view;
0706 using Class_ = class_<Map, holder_type>;
0707
0708
0709
0710
0711 auto *tinfo = detail::get_type_info(typeid(MappedType));
0712 bool local = !tinfo || tinfo->module_local;
0713 if (local) {
0714 tinfo = detail::get_type_info(typeid(KeyType));
0715 local = !tinfo || tinfo->module_local;
0716 }
0717
0718 Class_ cl(scope, name.c_str(), pybind11::module_local(local), std::forward<Args>(args)...);
0719
0720
0721 if (!detail::get_type_info(typeid(KeysView))) {
0722 class_<KeysView> keys_view(scope, "KeysView", pybind11::module_local(local));
0723 keys_view.def("__len__", &KeysView::len);
0724 keys_view.def("__iter__",
0725 &KeysView::iter,
0726 keep_alive<0, 1>()
0727 );
0728 keys_view.def("__contains__", &KeysView::contains);
0729 }
0730
0731 if (!detail::get_type_info(typeid(ValuesView))) {
0732 class_<ValuesView> values_view(scope, "ValuesView", pybind11::module_local(local));
0733 values_view.def("__len__", &ValuesView::len);
0734 values_view.def("__iter__",
0735 &ValuesView::iter,
0736 keep_alive<0, 1>()
0737 );
0738 }
0739
0740 if (!detail::get_type_info(typeid(ItemsView))) {
0741 class_<ItemsView> items_view(scope, "ItemsView", pybind11::module_local(local));
0742 items_view.def("__len__", &ItemsView::len);
0743 items_view.def("__iter__",
0744 &ItemsView::iter,
0745 keep_alive<0, 1>()
0746 );
0747 }
0748
0749 cl.def(init<>());
0750
0751
0752 detail::map_if_insertion_operator<Map, Class_>(cl, name);
0753
0754 cl.def(
0755 "__bool__",
0756 [](const Map &m) -> bool { return !m.empty(); },
0757 "Check whether the map is nonempty");
0758
0759 cl.def(
0760 "__iter__",
0761 [](Map &m) { return make_key_iterator(m.begin(), m.end()); },
0762 keep_alive<0, 1>()
0763 );
0764
0765 cl.def(
0766 "keys",
0767 [](Map &m) { return std::unique_ptr<KeysView>(new detail::KeysViewImpl<Map>(m)); },
0768 keep_alive<0, 1>()
0769 );
0770
0771 cl.def(
0772 "values",
0773 [](Map &m) { return std::unique_ptr<ValuesView>(new detail::ValuesViewImpl<Map>(m)); },
0774 keep_alive<0, 1>()
0775 );
0776
0777 cl.def(
0778 "items",
0779 [](Map &m) { return std::unique_ptr<ItemsView>(new detail::ItemsViewImpl<Map>(m)); },
0780 keep_alive<0, 1>()
0781 );
0782
0783 cl.def(
0784 "__getitem__",
0785 [](Map &m, const KeyType &k) -> MappedType & {
0786 auto it = m.find(k);
0787 if (it == m.end()) {
0788 throw key_error();
0789 }
0790 return it->second;
0791 },
0792 return_value_policy::reference_internal
0793 );
0794
0795 cl.def("__contains__", [](Map &m, const KeyType &k) -> bool {
0796 auto it = m.find(k);
0797 if (it == m.end()) {
0798 return false;
0799 }
0800 return true;
0801 });
0802
0803 cl.def("__contains__", [](Map &, const object &) -> bool { return false; });
0804
0805
0806 detail::map_assignment<Map, Class_>(cl);
0807
0808 cl.def("__delitem__", [](Map &m, const KeyType &k) {
0809 auto it = m.find(k);
0810 if (it == m.end()) {
0811 throw key_error();
0812 }
0813 m.erase(it);
0814 });
0815
0816
0817 cl.def("__len__", [](const Map &m) { return m.size(); });
0818
0819 return cl;
0820 }
0821
0822 PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)