From 9d92081d1e6387c5ea79371beeabb8181845e5e7 Mon Sep 17 00:00:00 2001 From: taltenbach <92919739+taltenbach@users.noreply.github.com> Date: Tue, 4 Aug 2026 09:01:42 +0200 Subject: [PATCH] Fix operator[] for const iota_view and repeat_view (#1525) * Fix missing operator[] for iota_iterator and repeat_iterator The iterators of etl::ranges::iota_view and etl::ranges::repeat_view are random access iterators but they did not define any operator[]. This did not cause any issues when using mutable views since the implementation of operator[] provided by view_interface for random access views was hidden by another implementation using etl::advance. However, this was not the case for 'operator[] const', which resulted in a build error when using constant views. This commit ensures that the operator[] implementation for random access views is no longer hidden by another implementation in view_interface, and adds operator[] to both iterators. * Fix sign conversion error on operator[] for some views The operator[] definitions provided by view_interface were accepting size_t arguments. This was causing a compile-time warning (Wsign-conversion) for the random access views using an iterator with a signed difference type. This has been observed on etl::ranges::iota_view and etl::ranges::repeat_view. No test is added since the tests provided by the previous commit already produce the warning, causing a build error. --------- Co-authored-by: John Wellbelove --- include/etl/ranges.h | 17 ++++++++++++++--- test/test_ranges.cpp | 26 ++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/include/etl/ranges.h b/include/etl/ranges.h index b502f82d..9ab8b1a6 100644 --- a/include/etl/ranges.h +++ b/include/etl/ranges.h @@ -150,7 +150,8 @@ namespace etl return *etl::prev(cend()); } - constexpr decltype(auto) operator[](size_t i) + template < typename D2 = D, etl::enable_if_t().begin())>::value, int> = 0> + constexpr decltype(auto) operator[](range_difference_t i) { auto it{static_cast(this)->begin()}; etl::advance(it, i); @@ -158,13 +159,13 @@ namespace etl } template < typename D2 = D, etl::enable_if_t().begin())>::value, int> = 0> - constexpr decltype(auto) operator[](size_t i) + constexpr decltype(auto) operator[](range_difference_t i) { return static_cast(this)->begin()[i]; } template < typename D2 = D, etl::enable_if_t().begin())>::value, int> = 0> - constexpr decltype(auto) operator[](size_t i) const + constexpr decltype(auto) operator[](range_difference_t i) const { return cbegin()[i]; } @@ -502,6 +503,11 @@ namespace etl return _i; } + constexpr value_type operator[](difference_type n) const + { + return *(*this + n); + } + private: value_type _i; @@ -673,6 +679,11 @@ namespace etl return _value; } + constexpr value_type operator[](difference_type n) const + { + return *(*this + n); + } + private: value_type _value; diff --git a/test/test_ranges.cpp b/test/test_ranges.cpp index efe64148..cab77148 100644 --- a/test/test_ranges.cpp +++ b/test/test_ranges.cpp @@ -473,6 +473,20 @@ namespace CHECK_EQUAL(iv3.empty(), true); } + TEST(test_ranges_iota_view_const) + { + const auto iv = etl::ranges::iota_view(1, 7); + + int compare = 1; + for (auto i : iv) + { + CHECK_EQUAL(i, compare); + ++compare; + } + + CHECK_EQUAL(iv[4], 5); + } + TEST(test_ranges_views_iota) { auto iv = etl::ranges::views::iota(1, 7); @@ -540,6 +554,18 @@ namespace CHECK_EQUAL(iv3.empty(), true); } + TEST(test_ranges_repeat_view_const) + { + const auto rv = etl::ranges::repeat_view(1, 7); + + for (auto i : rv) + { + CHECK_EQUAL(i, 1); + } + + CHECK_EQUAL(rv[4], 1); + } + TEST(test_ranges_views_repeat) { auto iv = etl::ranges::views::repeat(1, 7);