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