using SizeType = typename Vector::size_type;
using DiffType = typename Vector::difference_type;
+ auto wrap_i = [](DiffType i, SizeType n) {
+ if (i < 0)
+ i += n;
+ if (i < 0 || (SizeType)i >= n)
+ throw index_error();
+ return i;
+ };
+
cl.def("append",
[](Vector &v, const T &value) { v.push_back(value); },
arg("x"),
cl.def(init([](iterable it) {
auto v = std::unique_ptr<Vector>(new Vector());
- v->reserve(len(it));
+ v->reserve(len_hint(it));
for (handle h : it)
v->push_back(h.cast<T>());
return v.release();
}));
+ cl.def("clear",
+ [](Vector &v) {
+ v.clear();
+ },
+ "Clear the contents"
+ );
+
cl.def("extend",
[](Vector &v, const Vector &src) {
v.insert(v.end(), src.begin(), src.end());
"Extend the list by appending all the items in the given list"
);
+ cl.def("extend",
+ [](Vector &v, iterable it) {
+ const size_t old_size = v.size();
+ v.reserve(old_size + len_hint(it));
+ try {
+ for (handle h : it) {
+ v.push_back(h.cast<T>());
+ }
+ } catch (const cast_error &) {
+ v.erase(v.begin() + static_cast<typename Vector::difference_type>(old_size), v.end());
+ try {
+ v.shrink_to_fit();
+ } catch (const std::exception &) {
+ // Do nothing
+ }
+ throw;
+ }
+ },
+ arg("L"),
+ "Extend the list by appending all the items in the given list"
+ );
+
cl.def("insert",
- [](Vector &v, SizeType i, const T &x) {
- if (i > v.size())
+ [](Vector &v, DiffType i, const T &x) {
+ // Can't use wrap_i; i == v.size() is OK
+ if (i < 0)
+ i += v.size();
+ if (i < 0 || (SizeType)i > v.size())
throw index_error();
- v.insert(v.begin() + (DiffType) i, x);
+ v.insert(v.begin() + i, x);
},
arg("i") , arg("x"),
"Insert an item at a given position."
);
cl.def("pop",
- [](Vector &v, SizeType i) {
- if (i >= v.size())
- throw index_error();
- T t = v[i];
- v.erase(v.begin() + (DiffType) i);
+ [wrap_i](Vector &v, DiffType i) {
+ i = wrap_i(i, v.size());
+ T t = v[(SizeType) i];
+ v.erase(v.begin() + i);
return t;
},
arg("i"),
);
cl.def("__setitem__",
- [](Vector &v, SizeType i, const T &t) {
- if (i >= v.size())
- throw index_error();
- v[i] = t;
+ [wrap_i](Vector &v, DiffType i, const T &t) {
+ i = wrap_i(i, v.size());
+ v[(SizeType)i] = t;
}
);
);
cl.def("__delitem__",
- [](Vector &v, SizeType i) {
- if (i >= v.size())
- throw index_error();
- v.erase(v.begin() + DiffType(i));
+ [wrap_i](Vector &v, DiffType i) {
+ i = wrap_i(i, v.size());
+ v.erase(v.begin() + i);
},
"Delete the list elements at index ``i``"
);
void vector_accessor(enable_if_t<!vector_needs_copy<Vector>::value, Class_> &cl) {
using T = typename Vector::value_type;
using SizeType = typename Vector::size_type;
+ using DiffType = typename Vector::difference_type;
using ItType = typename Vector::iterator;
+ auto wrap_i = [](DiffType i, SizeType n) {
+ if (i < 0)
+ i += n;
+ if (i < 0 || (SizeType)i >= n)
+ throw index_error();
+ return i;
+ };
+
cl.def("__getitem__",
- [](Vector &v, SizeType i) -> T & {
- if (i >= v.size())
- throw index_error();
- return v[i];
+ [wrap_i](Vector &v, DiffType i) -> T & {
+ i = wrap_i(i, v.size());
+ return v[(SizeType)i];
},
return_value_policy::reference_internal // ref + keepalive
);
void vector_accessor(enable_if_t<vector_needs_copy<Vector>::value, Class_> &cl) {
using T = typename Vector::value_type;
using SizeType = typename Vector::size_type;
+ using DiffType = typename Vector::difference_type;
using ItType = typename Vector::iterator;
cl.def("__getitem__",
- [](const Vector &v, SizeType i) -> T {
- if (i >= v.size())
+ [](const Vector &v, DiffType i) -> T {
+ if (i < 0 && (i += v.size()) < 0)
+ throw index_error();
+ if ((SizeType)i >= v.size())
throw index_error();
- return v[i];
+ return v[(SizeType)i];
}
);
// Map assignment when copy-assignable: just copy the value
template <typename Map, typename Class_>
-void map_assignment(enable_if_t<std::is_copy_assignable<typename Map::mapped_type>::value, Class_> &cl) {
+void map_assignment(enable_if_t<is_copy_assignable<typename Map::mapped_type>::value, Class_> &cl) {
using KeyType = typename Map::key_type;
using MappedType = typename Map::mapped_type;
// Not copy-assignable, but still copy-constructible: we can update the value by erasing and reinserting
template<typename Map, typename Class_>
void map_assignment(enable_if_t<
- !std::is_copy_assignable<typename Map::mapped_type>::value &&
+ !is_copy_assignable<typename Map::mapped_type>::value &&
is_copy_constructible<typename Map::mapped_type>::value,
Class_> &cl) {
using KeyType = typename Map::key_type;
return_value_policy::reference_internal // ref + keepalive
);
+ cl.def("__contains__",
+ [](Map &m, const KeyType &k) -> bool {
+ auto it = m.find(k);
+ if (it == m.end())
+ return false;
+ return true;
+ }
+ );
+
// Assignment provided only if the type is copyable
detail::map_assignment<Map, Class_>(cl);