From af8ec168c44d50a3e3fe20e8cdd2a8e7f618677e Mon Sep 17 00:00:00 2001 From: Nik Delgado <84356491+nikdelgado@users.noreply.github.com> Date: Fri, 26 Dec 2025 00:01:58 -0700 Subject: [PATCH] implement .begin() and .end() for etl::optional (#1246) Co-authored-by: nikdelgado --- include/etl/optional.h | 38 +++++++++++++++++++ test/test_optional.cpp | 84 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) diff --git a/include/etl/optional.h b/include/etl/optional.h index 3b565c5b..ec998479 100644 --- a/include/etl/optional.h +++ b/include/etl/optional.h @@ -1326,6 +1326,8 @@ namespace etl public: typedef T value_type; + typedef T* iterator; + typedef const T* const_iterator; #if ETL_USING_CPP11 //*************************************************************************** @@ -1698,6 +1700,42 @@ namespace etl return *this; } #endif + + //*************************************************************************** + /// Returns an iterator to the beginning of the optional. + //*************************************************************************** + ETL_CONSTEXPR20_STL + iterator begin() ETL_NOEXCEPT + { + return this->has_value() ? this->operator->() : ETL_NULLPTR; + } + + //*************************************************************************** + /// Returns a const iterator to the beginning of the optional. + //*************************************************************************** + ETL_CONSTEXPR20_STL + const_iterator begin() const ETL_NOEXCEPT + { + return this->has_value() ? this->operator->() : ETL_NULLPTR; + } + + //*************************************************************************** + /// Returns an iterator to the end of the optional. + //*************************************************************************** + ETL_CONSTEXPR20_STL + iterator end() ETL_NOEXCEPT + { + return this->has_value() ? this->operator->() + 1 : ETL_NULLPTR; + } + + //*************************************************************************** + /// Returns a const iterator to the end of the optional. + //*************************************************************************** + ETL_CONSTEXPR20_STL + const_iterator end() const ETL_NOEXCEPT + { + return this->has_value() ? this->operator->() + 1 : ETL_NULLPTR; + } }; #include "private/diagnostic_uninitialized_push.h" diff --git a/test/test_optional.cpp b/test/test_optional.cpp index 99d8a312..6ca762a9 100644 --- a/test/test_optional.cpp +++ b/test/test_optional.cpp @@ -1034,5 +1034,89 @@ namespace CHECK_EQUAL(1, (*opt3)[0]); CHECK_EQUAL(20, (*opt3)[1]); } + + //************************************************************************* + TEST(test_begin_end_with_value) + { + etl::optional opt = 4; + + CHECK(opt.begin() != opt.end()); + CHECK_EQUAL(4, *opt.begin()); + CHECK_EQUAL(1, std::distance(opt.begin(), opt.end())); + } + + TEST(test_begin_end_empty) + { + etl::optional opt; + + CHECK(opt.begin() == ETL_NULLPTR); + CHECK(opt.begin() == opt.end()); + } + + TEST(test_const_begin_end_with_value) + { + const etl::optional opt = 4; + + CHECK(opt.begin() != opt.end()); + CHECK_EQUAL(4, *opt.begin()); + CHECK_EQUAL(1, std::distance(opt.begin(), opt.end())); + } + + TEST(test_const_begin_end_empty) + { + const etl::optional opt; + + CHECK(opt.begin() == ETL_NULLPTR); + CHECK(opt.begin() == opt.end()); + } + + TEST(range_based_for_loop_with_value) + { + etl::optional opt = 4; + + int sum = 0; + for (int value : opt) + { + sum += value; + } + + CHECK_EQUAL(4, sum); + } + + TEST(range_based_for_loop_empty) + { + etl::optional opt; + + int sum = 0; + for (int value : opt) + { + sum += value; + } + + CHECK_EQUAL(0, sum); + } + + TEST(test_range_based_for_loop_non_trivial) + { + etl::optional opt = Data("TEST"); + int count= 0; + + for (const Data& value : opt) + { + CHECK_EQUAL(Data("TEST"), value); + count++; + } + + CHECK_EQUAL(1, count); + } + + TEST(test_begin_end_modify_value) + { + etl::optional opt = 4; + + *opt.begin() = 42; + + CHECK_EQUAL(42, *opt); + } } }