From 435b705c90151f3bc778f15a3157b7bf64dc7fed Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 20 Sep 2026 08:37:08 +0100 Subject: [PATCH] Added runtime ans static asserts for reverse ordered limts. --- docs/utilities/cyclic-value.md | 8 ++++++-- include/etl/cyclic_value.h | 29 +++++++++++++++++++++++++---- include/etl/file_error_numbers.h | 1 + test/test_cyclic_value.cpp | 11 +++++++++++ 4 files changed, 43 insertions(+), 6 deletions(-) diff --git a/docs/utilities/cyclic-value.md b/docs/utilities/cyclic-value.md index 77b13893..7b6aabb1 100644 --- a/docs/utilities/cyclic-value.md +++ b/docs/utilities/cyclic-value.md @@ -15,6 +15,7 @@ Supports compile time and runtime variants. template class cyclic_value ``` +Static asserts if `Last` < `First`. **Example** @@ -38,18 +39,20 @@ Constructs a cyclic value of type `T` with an initial value of `first`. --- ```cpp -cyclic_value(T first, T last) noexcept; +cyclic_value(T first, T last); ``` Constructs a *run time* cyclic value of type `T` with limits of `first` and `fast` and an initial value of `first`. +Asserts an `etl::cyclic_value_reversed_limits` if `last` < `first`. `constexpr` from C++11. --- ```cpp -cyclic_value(T first, T last, T initial) noexcept; +cyclic_value(T first, T last, T initial); ``` Constructs a cyclic value of type `T` with limits of `first` and `fast` and an initial value of `initial`. `initial` will be clamped to be in the range `(first, last)`. +Asserts an `etl::cyclic_value_reversed_limits` if `last` < `first`. `constexpr` from C++11. ### Compile time limits @@ -144,6 +147,7 @@ Gets the last value. void set(T first, T last) noexcept; ``` Sets the new *run time* `first` and `last` values. Sets the current value to `first`. +Asserts an `etl::cyclic_value_reversed_limits` if `last` < `first`. `constexpr` from C++14. --- diff --git a/include/etl/cyclic_value.h b/include/etl/cyclic_value.h index 36cf2f65..17636d77 100644 --- a/include/etl/cyclic_value.h +++ b/include/etl/cyclic_value.h @@ -155,6 +155,22 @@ namespace etl } } // namespace private_cyclic_value + struct cyclic_value_exception : etl::exception + { + cyclic_value_exception(string_type reason_, string_type file_, numeric_type line_) + : etl::exception(reason_, file_, line_) + { + } + }; + + struct cyclic_value_reversed_limits : cyclic_value_exception + { + cyclic_value_reversed_limits(string_type file_, numeric_type line_) + : cyclic_value_exception(ETL_ERROR_TEXT("cyclic_value_exception:reversed limits", ETL_CYCLIC_VALUE_FILE_ID"A"), file_, line_) + { + } + }; + //*************************************************************************** /// Provides a value that cycles between two limits. //*************************************************************************** @@ -179,6 +195,7 @@ namespace etl public: ETL_STATIC_ASSERT(etl::is_integral::value, "T must be an integral type"); + ETL_STATIC_ASSERT(First <= Last, "First is not <= Last"); //************************************************************************* /// Default constructor. @@ -431,7 +448,7 @@ namespace etl //************************************************************************* /// Constructor. - /// Sets 'first' and 'last' to the template parameter values. + /// Sets 'first' and 'last' to the template parameter values which will be zero. /// The initial value is set to the first value. //************************************************************************* ETL_CONSTEXPR cyclic_value() ETL_NOEXCEPT @@ -447,11 +464,12 @@ namespace etl ///\param first The first value in the range. ///\param last The last value in the range. //************************************************************************* - ETL_CONSTEXPR cyclic_value(T first_, T last_) ETL_NOEXCEPT + ETL_CONSTEXPR14 cyclic_value(T first_, T last_) : value(first_) , first_value(first_) , last_value(last_) { + ETL_ASSERT(first_ <= last_, ETL_ERROR(cyclic_value_reversed_limits)); } //************************************************************************* @@ -461,11 +479,12 @@ namespace etl ///\param first The first value in the range. ///\param last The last value in the range. //************************************************************************* - ETL_CONSTEXPR cyclic_value(T first_, T last_, T initial) ETL_NOEXCEPT + ETL_CONSTEXPR14 cyclic_value(T first_, T last_, T initial) : value(etl::clamp(initial, first_, last_)) , first_value(first_) , last_value(last_) { + ETL_ASSERT(first_ <= last_, ETL_ERROR(cyclic_value_reversed_limits)); } //************************************************************************* @@ -484,8 +503,10 @@ namespace etl ///\param first The first value in the range. ///\param last The last value in the range. //************************************************************************* - ETL_CONSTEXPR14 void set(T first_, T last_) ETL_NOEXCEPT + ETL_CONSTEXPR14 void set(T first_, T last_) { + ETL_ASSERT(first_ <= last_, ETL_ERROR(cyclic_value_reversed_limits)); + first_value = first_; last_value = last_; value = first_; diff --git a/include/etl/file_error_numbers.h b/include/etl/file_error_numbers.h index 945f1d87..1bcddc48 100644 --- a/include/etl/file_error_numbers.h +++ b/include/etl/file_error_numbers.h @@ -112,4 +112,5 @@ SOFTWARE. #define ETL_FORMAT_FILE_ID "79" #define ETL_INPLACE_FUNCTION_FILE_ID "80" #define ETL_INTRUSIVE_AVL_TREE_FILE_ID "81" +#define ETL_CYCLIC_VALUE_FILE_ID "82" #endif diff --git a/test/test_cyclic_value.cpp b/test/test_cyclic_value.cpp index 7a3a6f81..24e5a2b8 100644 --- a/test/test_cyclic_value.cpp +++ b/test/test_cyclic_value.cpp @@ -56,6 +56,15 @@ namespace CHECK_EQUAL(7, value.last()); } + //************************************************************************* + TEST(test_reversed_run_time_initialisation) + { + etl::cyclic_value value(1, 2); + + CHECK_THROW(etl::cyclic_value(7, 2), etl::cyclic_value_reversed_limits); + CHECK_THROW(value.set(7, 2), etl::cyclic_value_reversed_limits); + } + //************************************************************************* TEST(test_copy_constructor_compile_time) { @@ -707,6 +716,7 @@ namespace CHECK(true); } +#if ETL_USING_CPP14 //************************************************************************* TEST(test_cyclic_value_constexpr_ctor_with_range) { @@ -715,6 +725,7 @@ namespace static_assert(cv.last() == 9, "constexpr range ctor last"); CHECK(true); } +#endif //************************************************************************* TEST(test_cyclic_value_constexpr_copy_ctor)