mirror of
https://github.com/ETLCPP/etl.git
synced 2026-04-30 19:09:10 +08:00
Merge branch 'development' into feature/floating-macro-format
This commit is contained in:
commit
8cc53bb8af
@ -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;
|
||||
}
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -34,6 +34,8 @@ SOFTWARE.
|
||||
#include "etl/error_handler.h"
|
||||
#include "etl/exception.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace
|
||||
{
|
||||
class TestException1 : public etl::exception
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
|
||||
@ -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" />
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user