Merge branch 'development' into feature/floating-macro-format

This commit is contained in:
John Wellbelove 2026-03-06 21:38:37 +00:00 committed by GitHub
commit 8cc53bb8af
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 213 additions and 17 deletions

View File

@ -34,7 +34,7 @@ SOFTWARE.
#define ETL_ALGORITHM_INCLUDED
///\defgroup algorithm algorithm
/// Including reverse engineered algorithms from C++ 0x11, 0x14, 0x17
/// Including reverse engineered algorithms from C++11, 14, 17
/// Additional new variants of certain algorithms.
///\ingroup utilities
@ -1193,7 +1193,12 @@ namespace etl
typename etl::enable_if<etl::is_random_access_iterator<TIterator>::value, TIterator>::type
rotate_general(TIterator first, TIterator middle, TIterator last)
{
if (first == middle || middle == last)
if (first == middle)
{
return last;
}
if (middle == last)
{
return first;
}
@ -1242,7 +1247,12 @@ namespace etl
typename etl::enable_if<etl::is_random_access_iterator<TIterator>::value, TIterator>::type
rotate_general(TIterator first, TIterator middle, TIterator last)
{
if (first == middle || middle == last)
if (first == middle)
{
return last;
}
if (middle == last)
{
return first;
}
@ -1292,7 +1302,12 @@ namespace etl
typename etl::enable_if<etl::is_bidirectional_iterator<TIterator>::value, TIterator>::type
rotate_general(TIterator first, TIterator middle, TIterator last)
{
if (first == middle || middle == last)
if (first == middle)
{
return last;
}
if (middle == last)
{
return first;
}
@ -1314,7 +1329,12 @@ namespace etl
typename etl::enable_if<etl::is_forward_iterator<TIterator>::value, TIterator>::type
rotate_general(TIterator first, TIterator middle, TIterator last)
{
if (first == middle || middle == last)
if (first == middle)
{
return last;
}
if (middle == last)
{
return first;
}

View File

@ -46,7 +46,7 @@ SOFTWARE.
#include <stddef.h>
///\defgroup array array
/// A replacement for std::array if you haven't got C++0x11.
/// A replacement for std::array if you haven't got C++11.
///\ingroup containers
namespace etl
@ -81,7 +81,7 @@ namespace etl
//***************************************************************************
///\ingroup array
/// A replacement for std::array if you haven't got C++0x11.
/// A replacement for std::array if you haven't got C++11.
//***************************************************************************
template <typename T, size_t SIZE_>
class array
@ -646,7 +646,7 @@ namespace etl
//***************************************************************************
///\ingroup array
/// A replacement for std::array if you haven't got C++0x11.
/// A replacement for std::array if you haven't got C++11.
/// Specialisation for zero sized array.
//***************************************************************************
template <typename T>

View File

@ -43,7 +43,7 @@ SOFTWARE.
namespace etl
{
//***************************************************************************
/// A definition of reference_wrapper for those that don't have C++ 0x11 support.
/// A definition of reference_wrapper for those that don't have C++11 support.
///\ingroup reference
//***************************************************************************
template <typename T>
@ -224,9 +224,9 @@ namespace etl
typedef int is_transparent;
template <typename T1, typename T2>
constexpr auto operator()(T1&& lhs, T2&& rhs) const -> decltype(static_cast<T1&&>(lhs) < static_cast<T2&&>(rhs))
constexpr auto operator()(T1&& lhs, T2&& rhs) const -> decltype(!(static_cast<T2&&>(rhs) < static_cast<T1&&>(lhs)))
{
return !(static_cast<T1&&>(lhs) < static_cast<T2&&>(rhs));
return !(static_cast<T2&&>(rhs) < static_cast<T1&&>(lhs));
}
};
#endif
@ -250,7 +250,7 @@ namespace etl
typedef int is_transparent;
template <typename T1, typename T2>
constexpr auto operator()(T1&& lhs, T2&& rhs) const -> decltype(static_cast<T1&&>(lhs) < static_cast<T2&&>(rhs))
constexpr auto operator()(T1&& lhs, T2&& rhs) const -> decltype(static_cast<T2&&>(rhs) < static_cast<T1&&>(lhs))
{
return static_cast<T2&&>(rhs) < static_cast<T1&&>(lhs);
}
@ -276,9 +276,9 @@ namespace etl
typedef int is_transparent;
template <typename T1, typename T2>
constexpr auto operator()(T1&& lhs, T2&& rhs) const -> decltype(static_cast<T1&&>(lhs) < static_cast<T2&&>(rhs))
constexpr auto operator()(T1&& lhs, T2&& rhs) const -> decltype(!(static_cast<T1&&>(lhs) < static_cast<T2&&>(rhs)))
{
return static_cast<T1&&>(rhs) < static_cast<T2&&>(lhs);
return !(static_cast<T1&&>(lhs) < static_cast<T2&&>(rhs));
}
};
#endif
@ -303,7 +303,7 @@ namespace etl
typedef int is_transparent;
template <typename T1, typename T2>
constexpr auto operator()(T1&& lhs, T2&& rhs) const -> decltype(static_cast<T1&&>(lhs) < static_cast<T2&&>(rhs))
constexpr auto operator()(T1&& lhs, T2&& rhs) const -> decltype(static_cast<T1&&>(lhs) == static_cast<T2&&>(rhs))
{
return static_cast<T1&&>(lhs) == static_cast<T2&&>(rhs);
}
@ -329,7 +329,7 @@ namespace etl
typedef int is_transparent;
template <typename T1, typename T2>
constexpr auto operator()(T1&& lhs, T2&& rhs) const -> decltype(static_cast<T1&&>(lhs) < static_cast<T2&&>(rhs))
constexpr auto operator()(T1&& lhs, T2&& rhs) const -> decltype(!(static_cast<T1&&>(lhs) == static_cast<T2&&>(rhs)))
{
return !(static_cast<T1&&>(lhs) == static_cast<T2&&>(rhs));
}

View File

@ -47,7 +47,7 @@ namespace etl
{
//***************************************************************************
/// iota
/// Reverse engineered version of std::iota for non C++ 0x11 compilers.
/// Reverse engineered version of std::iota for non C++11 compilers.
/// Fills a range of elements with sequentially increasing values starting with <b>value</b>.
///\param first An iterator to the first position to fill.
///\param last An iterator to the last + 1 position.

View File

@ -86,6 +86,7 @@ add_executable(etl_tests
test_closure.cpp
test_closure_constexpr.cpp
test_compare.cpp
test_concepts.cpp
test_constant.cpp
test_const_map.cpp
test_const_map_constexpr.cpp
@ -172,6 +173,7 @@ add_executable(etl_tests
test_endian.cpp
test_enum_type.cpp
test_error_handler.cpp
test_etl_assert.cpp
test_etl_traits.cpp
test_exception.cpp
test_expected.cpp
@ -183,6 +185,7 @@ add_executable(etl_tests
test_flat_multiset.cpp
test_flat_set.cpp
test_fnv_1.cpp
test_format.cpp
test_format_spec.cpp
test_forward_list.cpp
test_forward_list_shared_pool.cpp
@ -194,10 +197,12 @@ add_executable(etl_tests
test_hash.cpp
test_hfsm.cpp
test_hfsm_recurse_to_inner_state_on_start.cpp
test_hfsm_transition_on_enter.cpp
test_histogram.cpp
test_index_of_type.cpp
test_indirect_vector.cpp
test_indirect_vector_external_buffer.cpp
test_inplace_function.cpp
test_instance_count.cpp
test_integral_limits.cpp
test_intrusive_forward_list.cpp
@ -206,7 +211,9 @@ add_executable(etl_tests
test_intrusive_queue.cpp
test_intrusive_stack.cpp
test_invert.cpp
test_invoke.cpp
test_io_port.cpp
test_is_invocable.cpp
test_iterator.cpp
test_jenkins.cpp
test_largest.cpp
@ -259,6 +266,7 @@ add_executable(etl_tests
test_pool.cpp
test_pool_external_buffer.cpp
test_priority_queue.cpp
test_print.cpp
test_pseudo_moving_average.cpp
test_quantize.cpp
test_queue.cpp
@ -286,6 +294,7 @@ add_executable(etl_tests
test_scaled_rounding.cpp
test_set.cpp
test_shared_message.cpp
test_signal.cpp
test_singleton.cpp
test_singleton_base.cpp
test_smallest.cpp

View File

@ -113,6 +113,12 @@ struct non_random_iterator : public etl::iterator<ETL_OR_STD::bidirectional_iter
T* ptr;
};
template <typename T>
bool operator ==(const non_random_iterator<T>& lhs, const non_random_iterator<T>& rhs)
{
return lhs.ptr == rhs.ptr;
}
template <typename T>
bool operator !=(const non_random_iterator<T>& lhs, const non_random_iterator<T>& rhs)
{

View File

@ -1236,6 +1236,93 @@ namespace
}
}
//*************************************************************************
TEST(rotate_return_value)
{
// Verify that etl::rotate returns the same iterator as std::rotate
// in all cases, including the degenerate first==middle and middle==last cases.
std::vector<int> initial_data = { 1, 2, 3, 4, 5 };
for (size_t i = 0UL; i <= initial_data.size(); ++i)
{
std::vector<int> data1(initial_data);
std::vector<int> data2(initial_data);
auto std_result = std::rotate(data1.data(), data1.data() + i, data1.data() + data1.size());
auto etl_result = etl::rotate(data2.data(), data2.data() + i, data2.data() + data2.size());
// Check that the return value offset matches
ptrdiff_t std_offset = std_result - data1.data();
ptrdiff_t etl_offset = etl_result - data2.data();
CHECK_EQUAL(std_offset, etl_offset);
}
// Explicitly test first == middle (empty left half): should return last
{
std::vector<int> data = { 1, 2, 3 };
auto result = etl::rotate(data.data(), data.data(), data.data() + data.size());
CHECK(result == data.data() + data.size());
}
// Explicitly test middle == last (empty right half): should return first
{
std::vector<int> data = { 1, 2, 3 };
auto result = etl::rotate(data.data(), data.data() + data.size(), data.data() + data.size());
CHECK(result == data.data());
}
}
//*************************************************************************
TEST(rotate_return_value_non_random_iterator)
{
// Verify that etl::rotate returns the correct iterator when called with
// non-random (bidirectional) iterators, exercising rotate_general for
// bidirectional iterators rather than the random-access overload.
std::vector<int> initial_data = { 1, 2, 3, 4, 5 };
for (size_t i = 0UL; i <= initial_data.size(); ++i)
{
std::vector<int> data1(initial_data);
std::vector<int> data2(initial_data);
auto std_result = std::rotate(data1.data(), data1.data() + i, data1.data() + data1.size());
non_random_iterator<int> nr_first(data2.data());
non_random_iterator<int> nr_middle(data2.data() + i);
non_random_iterator<int> nr_last(data2.data() + data2.size());
auto etl_result = etl::rotate(nr_first, nr_middle, nr_last);
// Check that the data was rotated correctly
bool isEqual = std::equal(std::begin(data1), std::end(data1), std::begin(data2));
CHECK(isEqual);
// Check that the return value offset matches
ptrdiff_t std_offset = std_result - data1.data();
ptrdiff_t etl_offset = etl_result.ptr - data2.data();
CHECK_EQUAL(std_offset, etl_offset);
}
// Explicitly test first == middle (empty left half): should return last
{
std::vector<int> data = { 1, 2, 3 };
non_random_iterator<int> nr_first(data.data());
non_random_iterator<int> nr_middle(data.data());
non_random_iterator<int> nr_last(data.data() + data.size());
auto result = etl::rotate(nr_first, nr_middle, nr_last);
CHECK(result.ptr == data.data() + data.size());
}
// Explicitly test middle == last (empty right half): should return first
{
std::vector<int> data = { 1, 2, 3 };
non_random_iterator<int> nr_first(data.data());
non_random_iterator<int> nr_middle(data.data() + data.size());
non_random_iterator<int> nr_last(data.data() + data.size());
auto result = etl::rotate(nr_first, nr_middle, nr_last);
CHECK(result.ptr == data.data());
}
}
//*************************************************************************
TEST(any_of)
{

View File

@ -34,6 +34,8 @@ SOFTWARE.
#include "etl/error_handler.h"
#include "etl/exception.h"
#include <cstring>
namespace
{
class TestException1 : public etl::exception

View File

@ -85,6 +85,24 @@ namespace
mutable std::string result;
};
#if ETL_USING_CPP11
// Lightweight type used to verify transparent heterogeneous comparison.
// Only operator<(int, Wrapper) is defined; operator<(Wrapper, int) is
// intentionally absent. less_equal<void> is implemented as
// !(rhs < lhs), so less_equal<void>{}(Wrapper, int) needs
// operator<(int, Wrapper) which IS provided.
struct Wrapper
{
int value;
constexpr explicit Wrapper(int v) : value(v) {}
};
// int < Wrapper -- defined
constexpr bool operator<(int lhs, const Wrapper& rhs) { return lhs < rhs.value; }
// Wrapper < int -- intentionally NOT defined
#endif
SUITE(test_functional)
{
//*************************************************************************
@ -101,6 +119,32 @@ namespace
CHECK((compare<etl::less_equal<int>>(1, 2)));
CHECK(!(compare<etl::less_equal<int>>(2, 1)));
CHECK((compare<etl::less_equal<int>>(1, 1)));
#if ETL_USING_CPP11
CHECK((compare<etl::less_equal<void>>(1, 2)));
CHECK(!(compare<etl::less_equal<void>>(2, 1)));
CHECK((compare<etl::less_equal<void>>(1, 1)));
#endif
}
//*************************************************************************
TEST(test_less_equal_void_heterogeneous)
{
#if ETL_USING_CPP11
// less_equal<void>{}(lhs, rhs) is !(rhs < lhs).
// With only operator<(int, Wrapper) defined, we can call
// less_equal<void>{}(Wrapper, int) because the implementation
// evaluates !(int < Wrapper).
// Wrapper(1) <= 2 → !(2 < Wrapper(1)) → !(2 < 1) → !false → true
CHECK((etl::less_equal<void>{}(Wrapper(1), 2)));
// Wrapper(2) <= 1 → !(1 < Wrapper(2)) → !(1 < 2) → !true → false
CHECK(!(etl::less_equal<void>{}(Wrapper(2), 1)));
// Wrapper(3) <= 3 → !(3 < Wrapper(3)) → !(3 < 3) → !false → true
CHECK((etl::less_equal<void>{}(Wrapper(3), 3)));
#endif
}
//*************************************************************************
@ -117,6 +161,32 @@ namespace
CHECK(!(compare<etl::greater_equal<int>>(1, 2)));
CHECK((compare<etl::greater_equal<int>>(2, 1)));
CHECK((compare<etl::greater_equal<int>>(1, 1)));
#if ETL_USING_CPP11
CHECK(!(compare<etl::greater_equal<void>>(1, 2)));
CHECK((compare<etl::greater_equal<void>>(2, 1)));
CHECK((compare<etl::greater_equal<void>>(1, 1)));
#endif
}
//*************************************************************************
TEST(test_greater_equal_void_heterogeneous)
{
#if ETL_USING_CPP11
// greater_equal<void>{}(lhs, rhs) is !(lhs < rhs).
// With only operator<(int, Wrapper) defined, we can call
// greater_equal<void>{}(int, Wrapper) because the implementation
// evaluates !(int < Wrapper).
// 2 >= Wrapper(1) → !(2 < Wrapper(1)) → !(2 < 1) → !false → true
CHECK((etl::greater_equal<void>{}(2, Wrapper(1))));
// 1 >= Wrapper(2) → !(1 < Wrapper(2)) → !(1 < 2) → !true → false
CHECK(!(etl::greater_equal<void>{}(1, Wrapper(2))));
// 3 >= Wrapper(3) → !(3 < Wrapper(3)) → !(3 < 3) → !false → true
CHECK((etl::greater_equal<void>{}(3, Wrapper(3))));
#endif
}
//*************************************************************************

View File

@ -3552,6 +3552,7 @@
<ClInclude Include="..\..\include\etl\monostate.h" />
<ClInclude Include="..\..\include\etl\not_null.h" />
<ClInclude Include="..\..\include\etl\poly_span.h" />
<ClInclude Include="..\..\include\etl\print.h" />
<ClInclude Include="..\..\include\etl\private\bitset_legacy.h" />
<ClInclude Include="..\..\include\etl\private\bitset_new.h" />
<ClInclude Include="..\..\include\etl\private\chrono\day.h" />
@ -10362,6 +10363,7 @@
<ClCompile Include="..\test_not_null_unique_pointer.cpp" />
<ClCompile Include="..\test_poly_span_dynamic_extent.cpp" />
<ClCompile Include="..\test_poly_span_fixed_extent.cpp" />
<ClCompile Include="..\test_print.cpp" />
<ClCompile Include="..\test_pseudo_moving_average.cpp" />
<ClCompile Include="..\test_delegate.cpp" />
<ClCompile Include="..\test_delegate_cpp03.cpp" />