etl/docs/utilities/cyclic-value.md
John Wellbelove a2da3ed940
Optimise cyclic value (#1607)
* Updated ignore for hard link for CLion

* Initial working version

* Optimised advance template call

* Further optimsed advance

Updated docs and tests

* Moved comparison operators out of the class.

* Implement spaceship operator <=> for No-STL case (#1604)

This was disabled explicitly in recent commit
232c948674cff1b4b72c2d6b3acfa7342d096dd1 to prevent using
the <compare> header from STL.

Now, re-enabling by implementing an ETL version of it in compare.h

* Sponsorship message updates

* Fix duplicated check runs

* Refactored the advance function to fix issues with signed unsigned mod operations.

* clang-format

* Updated documentation for cyclic_value

* Modified code comments

* Fixed a logic issue in advance() where a less than maximum step from the minimum value for a cyclic value covering the full type's range would take the wrong logical path (Step would roll over), although calculating the correct result.

This could be cofusing to someone debugging cyclc_value.

* Added runtime ans static asserts for reverse ordered limts.

* clang-format

* Spelling fix 'fast' -> 'last'

* Code review updates

* clang-format

* Code review updates

* Code review updates

---------

Co-authored-by: John Wellbelove <john.wellbelove@etlcpp.com>
Co-authored-by: Roland Reichwein <Roland.Reichwein@bmw.de>
2026-10-09 17:39:04 +01:00

5.9 KiB

title
cyclic_value

{{< callout type="info">}} Header: cyclic_value.h
Since: TBC
{{< /callout >}}

Provides a value that cycles between two limits.
Supports increments, decrements and arbitrary advance.
Supports compile time and runtime variants.

template <typename T, const T First = 0, const T Last = 0>
class cyclic_value

Static asserts if Last < First.

Example

etl::cyclic_value<int, 2, 7> value_ct; // Compile time. Fixed range of 2 to 7 inclusive.

etl::cyclic_value<int> value_rt(2, 7); // Run time. Modifiable range.
value_rt.set(3, 8);

Constructor

Run time limits

cyclic_value<T>() noexcept;

Constructs a cyclic value of type T with an initial value of first.
constexpr from C++11.


cyclic_value<T>(T first, T last);

Constructs a run time cyclic value of type T with limits of first and last and an initial value of first.
Asserts an etl::cyclic_value_reversed_limits if last < first.
constexpr from C++11.


cyclic_value<T>(T first, T last, T initial);

Constructs a cyclic value of type T with limits of first and last 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

cyclic_value<T, First, Last>() noexcept;

Constructs a cyclic value of type T default constructed with an initial value of First.
constexpr from C++11.


cyclic_value<T, First, Last>(T initial) noexcept;

Constructs a cyclic value of type T constructed with an initial.
initial will be clamped to be in the range (First, Last).
constexpr from C++11.

Modifiers

cyclic_value& operator ++() noexcept;
cyclic_value& operator ++(int) noexcept;

Increments the value. If the value is at the last value then is set to the first.
constexpr from C++14.


cyclic_value& operator --() noexcept;
cyclic_value& operator --(int) noexcept;

Decrements the value. If the value is at the first value then is set to the last.
constexpr from C++14.


template <typename TStep>
void advance(TStep n) noexcept;

Advances the value by the specified amount, wrapping if necessary.
constexpr from C++14.


template <typename TStep>
cyclic_value& operator +=(TStep n) noexcept;

Advances the value by the specified amount, wrapping if necessary.
constexpr from C++14.


template <typename TStep>
cyclic_value& operator -=(TStep n) noexcept;

Decrements the value by the specified amount, wrapping if necessary.
constexpr from C++14.

Access

T get() const;

Gets the current value.
constexpr from C++11.


T first() const noexcept;

Gets the first value.
constexpr from C++11.


T last() const noexcept;

Gets the last value.
constexpr from C++11.


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.


void set(T value) noexcept;

Sets the current value.
constexpr from C++14.


void to_first() noexcept;

Sets the current value to the first value.
constexpr from C++14.


void to_last() noexcept;

Sets the current value to the last value.
constexpr from C++14.

Operations

void swap(cyclic_value<T, FIRST, LAST>& other) noexcept;

Swaps with another cyclic value.
constexpr from C++14.

Operators

operator T() noexcept;
operator const T() const noexcept;

Conversion operators to T.
constexpr from C++11.


cyclic_value& operator =(T t) noexcept;

Sets the current value to t.
constexpr from C++14.

Non-member functions

template <typename T, const T FIRST, const T LAST>
void swap(cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs) noexcept

Swaps two cyclic values.


template <typename T, const T FIRST, const T LAST>
bool operator == (cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs) noexcept

Checks equality of two cyclic values.
constexpr from C++11.

{{< callout type="warning">}} After version 20.49.0 equality is judged only by the current value.
Previously the first and last limits were also considered.

<= 20.49.0
etl::cyclic_value<2, 7>(3) != etl::cyclic_value<2, 6>(3)

> 20.49.0
etl::cyclic_value<2, 7>(3) == etl::cyclic_value<2, 6>(3) {{< /callout >}}


template <typename T, const T FIRST, const T LAST>
bool operator != (cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs) noexcept

Checks inequality of two cyclic values.
constexpr from C++11.


template <typename T, const T FIRST, const T LAST>
bool operator < (cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs) noexcept

Checks if the current value of lhs is less than the current value of rhs.
constexpr from C++11.


template <typename T, const T FIRST, const T LAST>
bool operator <= (cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs) noexcept

Checks if the current value of lhs is less than or equal the current value of rhs.
constexpr from C++11.


template <typename T, const T FIRST, const T LAST>
bool operator > (cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs) noexcept

Checks if the current value of lhs is greater than the current value of rhs.
constexpr from C++11.


template <typename T, const T FIRST, const T LAST>
bool operator >= (cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs) noexcept

Checks if the current value of lhs is greater than or equal the current value of rhs.
constexpr from C++11.