Skip to content

Commit

Permalink
Make row iterator a proper random_access_iterator.
Browse files Browse the repository at this point in the history
Fixes: #846

This involves defining `operator[]` on the iterator, which indexes
at an offset: `i[n] == *(i + n)`.

Unfortunately I can't do the same for the _result_ iterator.  Way back
when, unaware of this requirement, I defined array indexing on a result
iterator as `i[n] == (*i)[n]`.  It made some code a lot more convenient
and seemed very logical.
  • Loading branch information
jtv committed Jul 5, 2024
1 parent f9e9f56 commit 251ca24
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 3 deletions.
6 changes: 3 additions & 3 deletions include/pqxx/internal/result_iterator.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ public:
* @name Dereferencing operators
*
* An iterator "points to" its own row, which is also itself. This makes it
* easy to address a @ref result as a two-dimensional container, without
* going through the intermediate step of dereferencing the iterator. It
* makes the interface similar to C pointer/array semantics.
* easy to address a @ref pqxx::result as a two-dimensional container,
* without going through the intermediate step of dereferencing the iterator.
* It makes the interface similar to C pointer/array semantics.
*
* IIRC Alex Stepanov, the inventor of the STL, once remarked that having
* this as standard behaviour for pointers would be useful in some
Expand Down
5 changes: 5 additions & 0 deletions include/pqxx/row.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,9 @@ public:
operator-(difference_type) const noexcept;
[[nodiscard]] inline difference_type
operator-(const_row_iterator const &) const noexcept;

[[nodiscard]] inline field operator[](difference_type offset) const noexcept
{ return *(*this + offset); }
//@}
};

Expand Down Expand Up @@ -487,6 +490,8 @@ public:
{
return rhs.const_row_iterator::operator-(*this);
}
[[nodiscard]] inline field operator[](difference_type offset) const noexcept
{ return *(*this + offset); }
//@}

/**
Expand Down
12 changes: 12 additions & 0 deletions test/unit/test_row.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,19 @@ void test_row_as()
}


// In a random access iterator i, i[n] == *(i + n).
void test_row_iterator_array_index_offsets_iterator()

Check notice

Code scanning / CodeQL

Unused static function Note test

Static function test_row_iterator_array_index_offsets_iterator is unreachable (
tst_test_row_iterator_array_index_offsets_iterator
must be removed at the same time)
{
pqxx::connection conn;
pqxx::work tx{conn};
auto const row{tx.exec1("SELECT 5, 4, 3, 2")};
PQXX_CHECK_EQUAL(row.begin()[1].as<std::string>(), "4", "Row iterator indexing went wrong.");
PQXX_CHECK_EQUAL(row.rbegin()[1].as<std::string>(), "3", "Reverse row iterator indexing went wrong.");
}


PQXX_REGISTER_TEST(test_row);
PQXX_REGISTER_TEST(test_row_iterator);
PQXX_REGISTER_TEST(test_row_as);
PQXX_REGISTER_TEST(test_row_iterator_array_index_offsets_iterator);
} // namespace

0 comments on commit 251ca24

Please sign in to comment.