14#include <lagrange/python/binding.h>
27#define LA_SAFE_VECTOR_SETTER(prop, arg_type) \
28 nanobind::for_setter(nanobind::sig("def " prop "(self, arg: " arg_type ", /) -> None"))
30NAMESPACE_BEGIN(NB_NAMESPACE)
32template <
typename Vector, rv_policy Policy = rv_policy::automatic_reference,
typename...
Args>
33class_<Vector> bind_safe_vector(handle scope,
const char* name,
Args&&... args)
35 using ValueRef =
typename detail::iterator_access<typename Vector::iterator>::result_type;
36 using Value = std::decay_t<ValueRef>;
37 using ValueType =
typename Value::element_type;
40 std::is_same_v<std::shared_ptr<ValueType>,
Value>,
41 "bind_safe_vector(): Value type must be a std::shared_ptr<>");
44 !detail::is_base_caster_v<detail::make_caster<Value>> ||
45 detail::is_copy_constructible_v<Value> ||
46 (Policy != rv_policy::automatic_reference && Policy != rv_policy::copy),
47 "bind_safe_vector(): the generated __getitem__ would copy elements, so the "
48 "element type must be copy-constructible");
50 handle cl_cur = type<Vector>();
51 if (cl_cur.is_valid()) {
53 return borrow<class_<Vector>>(cl_cur);
56 auto cl = class_<Vector>(scope, name, std::forward<Args>(args)...)
57 .def(init<>(),
"Default constructor")
59 .def(
"__len__", [](
const Vector& v) {
return v.size(); })
63 [](
const Vector& v) {
return !v.empty(); },
64 "Check whether the vector is nonempty")
68 [](handle_t<Vector> h) {
return steal<str>(detail::repr_list(h.ptr())); })
73 return make_iterator<Policy>(
76 v.Vector::Super::begin(),
77 v.Vector::Super::end());
83 [](Vector& v, Py_ssize_t i) -> ValueRef {
84 return v.Vector::Super::operator[](detail::wrap(i, v.size()));
88 .def(
"clear", [](Vector& v) { v.clear(); },
"Remove all items from list.");
90 if constexpr (detail::is_copy_constructible_v<Value>) {
91 cl.def(init<const Vector&>(),
"Copy constructor");
95 [](Vector* v, typed<iterable, Value> seq) {
97 v->reserve(len_hint(seq));
98 for (handle h : seq) v->Vector::Super::push_back(cast<Value>(h));
100 "Construct from an iterable object");
102 implicitly_convertible<iterable, Vector>();
106 [](Vector& v,
const Value& value) { v.Vector::Super::push_back(value); },
107 "Append `arg` to the end of the list.")
111 [](Vector& v, Py_ssize_t i,
const Value& x) {
112 if (i < 0) i += (Py_ssize_t)v.size();
113 if (i < 0 || (
size_t)i > v.size())
throw index_error();
114 v.insert(v.Vector::Super::begin() + i, x);
116 "Insert object `arg1` before index `arg0`.")
120 [](Vector& v, Py_ssize_t i) {
121 size_t index = detail::wrap(i, v.size());
122 Value result = std::move(v.Vector::Super::operator[](index));
123 v.erase(v.Vector::Super::begin() + index);
127 "Remove and return item at `index` (default last).")
131 [](Vector& v,
const Vector& src) {
133 v.Vector::Super::end(),
134 src.Vector::Super::begin(),
135 src.Vector::Super::end());
137 "Extend `self` by appending elements from `arg`.")
141 [](Vector& v, Py_ssize_t i,
const Value& value) {
142 v.Vector::Super::operator[](detail::wrap(i, v.size())) = value;
147 [](Vector& v, Py_ssize_t i) {
148 v.erase(v.Vector::Super::begin() + detail::wrap(i, v.size()));
153 [](
const Vector& v,
const slice& slice) -> Vector* {
154 auto [start, stop, step, length] = slice.compute(v.size());
156 seq->reserve(length);
158 for (
size_t i = 0; i < length; ++i) {
159 seq->Vector::Super::push_back(v.Vector::Super::operator[](start));
168 [](Vector& v,
const slice& slice,
const Vector& value) {
169 auto [start, stop, step, length] = slice.compute(v.size());
171 if (length != value.size())
173 "The left and right hand side of the slice "
174 "assignment have mismatched sizes!");
176 for (
size_t i = 0; i < length; ++i) {
177 v.Vector::Super::operator[](start) = value.Vector::Super::operator[](i);
182 .def(
"__delitem__", [](Vector& v,
const slice& slice) {
183 auto [start, stop, step, length] = slice.compute(v.size());
184 if (length == 0)
return;
186 stop = start + (length - 1) * step;
188 std::swap(start, stop);
193 v.erase(v.Vector::Super::begin() + start, v.Vector::Super::begin() + stop + 1);
195 for (
size_t i = 0; i < length; ++i) {
196 v.erase(v.Vector::Super::begin() + stop);
203 if constexpr (detail::is_equality_comparable_v<Value>) {
204 cl.def(self == self, sig(
"def __eq__(self, arg: object, /) -> bool"))
205 .def(self != self, sig(
"def __ne__(self, arg: object, /) -> bool"))
209 [](
const Vector& v,
const Value& x) {
210 return std::find(v.Vector::Super::begin(), v.Vector::Super::end(), x) !=
211 v.Vector::Super::end();
216 [](
const Vector&, handle) {
return false; })
220 [](
const Vector& v,
const Value& x) {
221 return std::count(v.Vector::Super::begin(), v.Vector::Super::end(), x);
223 "Return number of occurrences of `arg`.")
227 [](Vector& v,
const Value& x) {
228 auto p = std::find(v.Vector::Super::begin(), v.Vector::Super::end(), x);
229 if (p != v.Vector::Super::end())
234 "Remove first occurrence of `arg`.");
240NAMESPACE_END(NB_NAMESPACE)
@ Value
Values that are not attached to a specific element.
Definition AttributeFwd.h:42
Eigen::Matrix< Scalar, Eigen::Dynamic, 1 > Vector
Type alias for one-dimensional column Eigen vectors.
Definition views.h:79
Definition project.cpp:27