File tree 3 files changed +32
-5
lines changed
3 files changed +32
-5
lines changed Original file line number Diff line number Diff line change @@ -1470,27 +1470,30 @@ class iterator : public object {
1470
1470
PYBIND11_OBJECT_DEFAULT (iterator, object, PyIter_Check)
1471
1471
1472
1472
iterator &operator ++() {
1473
+ init ();
1473
1474
advance ();
1474
1475
return *this ;
1475
1476
}
1476
1477
1477
1478
iterator operator ++(int ) {
1479
+ // Note: We must call init() first so that rv.value is
1480
+ // the same as this->value just before calling advance().
1481
+ // Otherwise, dereferencing the returned iterator may call
1482
+ // advance() again and return the 3rd item instead of the 1st.
1483
+ init ();
1478
1484
auto rv = *this ;
1479
1485
advance ();
1480
1486
return rv;
1481
1487
}
1482
1488
1483
1489
// NOLINTNEXTLINE(readability-const-return-type) // PR #3263
1484
1490
reference operator *() const {
1485
- if (m_ptr && !value.ptr ()) {
1486
- auto &self = const_cast <iterator &>(*this );
1487
- self.advance ();
1488
- }
1491
+ init ();
1489
1492
return value;
1490
1493
}
1491
1494
1492
1495
pointer operator ->() const {
1493
- operator * ();
1496
+ init ();
1494
1497
return &value;
1495
1498
}
1496
1499
@@ -1513,6 +1516,13 @@ class iterator : public object {
1513
1516
friend bool operator !=(const iterator &a, const iterator &b) { return a->ptr () != b->ptr (); }
1514
1517
1515
1518
private:
1519
+ void init () const {
1520
+ if (m_ptr && !value.ptr ()) {
1521
+ auto &self = const_cast <iterator &>(*this );
1522
+ self.advance ();
1523
+ }
1524
+ }
1525
+
1516
1526
void advance () {
1517
1527
value = reinterpret_steal<object>(PyIter_Next (m_ptr));
1518
1528
if (value.ptr () == nullptr && PyErr_Occurred ()) {
Original file line number Diff line number Diff line change @@ -150,6 +150,18 @@ TEST_SUBMODULE(pytypes, m) {
150
150
m.def (" get_iterator" , [] { return py::iterator (); });
151
151
// test_iterable
152
152
m.def (" get_iterable" , [] { return py::iterable (); });
153
+ m.def (" get_first_item_from_iterable" , [](const py::iterable &iter) {
154
+ // This tests the postfix increment operator
155
+ py::iterator it = iter.begin ();
156
+ py::iterator it2 = it++;
157
+ return *it2;
158
+ });
159
+ m.def (" get_second_item_from_iterable" , [](const py::iterable &iter) {
160
+ // This tests the prefix increment operator
161
+ py::iterator it = iter.begin ();
162
+ ++it;
163
+ return *it;
164
+ });
153
165
m.def (" get_frozenset_from_iterable" ,
154
166
[](const py::iterable &iter) { return py::frozenset (iter); });
155
167
m.def (" get_list_from_iterable" , [](const py::iterable &iter) { return py::list (iter); });
Original file line number Diff line number Diff line change @@ -52,6 +52,11 @@ def test_from_iterable(pytype, from_iter_func):
52
52
53
53
def test_iterable (doc ):
54
54
assert doc (m .get_iterable ) == "get_iterable() -> Iterable"
55
+ lins = [1 , 2 , 3 ]
56
+ i = m .get_first_item_from_iterable (lins )
57
+ assert i == 1
58
+ i = m .get_second_item_from_iterable (lins )
59
+ assert i == 2
55
60
56
61
57
62
def test_float (doc ):
You can’t perform that action at this time.
0 commit comments