| 314 | // The usual case: access and iterate by reference |
| 315 | template <typename Vector, typename Class_> |
| 316 | void vector_accessor(enable_if_t<!vector_needs_copy<Vector>::value, Class_> &cl) { |
| 317 | using T = typename Vector::value_type; |
| 318 | using SizeType = typename Vector::size_type; |
| 319 | using DiffType = typename Vector::difference_type; |
| 320 | using ItType = typename Vector::iterator; |
| 321 | |
| 322 | auto wrap_i = [](DiffType i, SizeType n) { |
| 323 | if (i < 0) { |
| 324 | i += n; |
| 325 | } |
| 326 | if (i < 0 || (SizeType) i >= n) { |
| 327 | throw index_error(); |
| 328 | } |
| 329 | return i; |
| 330 | }; |
| 331 | |
| 332 | cl.def( |
| 333 | "__getitem__", |
| 334 | [wrap_i](Vector &v, DiffType i) -> T & { |
| 335 | i = wrap_i(i, v.size()); |
| 336 | return v[(SizeType) i]; |
| 337 | }, |
| 338 | return_value_policy::reference_internal // ref + keepalive |
| 339 | ); |
| 340 | |
| 341 | cl.def( |
| 342 | "__iter__", |
| 343 | [](Vector &v) { |
| 344 | return make_iterator<return_value_policy::reference_internal, ItType, ItType, T &>( |
| 345 | v.begin(), v.end()); |
| 346 | }, |
| 347 | keep_alive<0, 1>() /* Essential: keep list alive while iterator exists */ |
| 348 | ); |
| 349 | } |
| 350 | |
| 351 | // The case for special objects, like std::vector<bool>, that have to be returned-by-copy: |
| 352 | template <typename Vector, typename Class_> |