From 43d3f0e89ca54e860b993f03e569f490695b7bb8 Mon Sep 17 00:00:00 2001 From: Filipe Cuim <87344176+filipe-cuim@users.noreply.github.com> Date: Tue, 11 Nov 2025 19:12:39 +0000 Subject: [PATCH 001/298] Add const specialization for etl::get_object_at (#1217) Signed-off-by: Filipe Cuim --- include/etl/memory.h | 63 ++++++++++++++++++++++++++------------------ test/test_memory.cpp | 51 ++++++++++++++++++++++++++--------- 2 files changed, 76 insertions(+), 38 deletions(-) diff --git a/include/etl/memory.h b/include/etl/memory.h index c2e162bd..ffe7b7ef 100644 --- a/include/etl/memory.h +++ b/include/etl/memory.h @@ -60,8 +60,8 @@ namespace etl //***************************************************************************** template ETL_CONSTEXPR T* to_address(T* p) ETL_NOEXCEPT - { - return p; + { + return p; } //***************************************************************************** @@ -837,7 +837,7 @@ namespace etl std::uninitialized_value_construct(o_begin, o_end); } -#else +#else //***************************************************************************** /// Default initialises a range of objects to uninitialised memory. /// https://en.cppreference.com/w/cpp/memory/uninitialized_value_construct @@ -1264,7 +1264,7 @@ namespace etl //********************************* template - default_delete(const default_delete&) ETL_NOEXCEPT + default_delete(const default_delete&) ETL_NOEXCEPT { } @@ -1353,8 +1353,8 @@ namespace etl #endif //********************************* - unique_ptr(pointer p_, typename etl::conditional::value, - TDeleter, + unique_ptr(pointer p_, typename etl::conditional::value, + TDeleter, typename etl::add_lvalue_reference::type>::type deleter_) ETL_NOEXCEPT : p(p_) , deleter(deleter_) @@ -1557,7 +1557,7 @@ namespace etl #endif //********************************* - unique_ptr(pointer p_, + unique_ptr(pointer p_, typename etl::conditional::value, TDeleter, typename etl::add_lvalue_reference::type>::type deleter_) ETL_NOEXCEPT @@ -1614,7 +1614,7 @@ namespace etl { pointer value = p; p = ETL_NULLPTR; - return value; + return value; } //********************************* @@ -1709,7 +1709,7 @@ namespace etl unique_ptr(const unique_ptr&) ETL_DELETE; unique_ptr& operator =(const unique_ptr&) ETL_DELETE; - pointer p; + pointer p; TDeleter deleter; }; } @@ -2324,7 +2324,7 @@ namespace etl reinterpret_cast(sb), sizeof(T) * n); #endif - + return db; } @@ -2374,7 +2374,7 @@ namespace etl reinterpret_cast(sb), sizeof(T) * n); #endif - + return db; } @@ -2438,7 +2438,7 @@ namespace etl /// \return The destination //*************************************************************************** template - typename etl::enable_if::value && + typename etl::enable_if::value && !etl::is_const::value && etl::is_integral::value && sizeof(T) == 1, TPointer>::type @@ -2447,11 +2447,11 @@ namespace etl ETL_STATIC_ASSERT(etl::is_trivially_copyable::value_type>::value, "Cannot mem_set a non trivially copyable type"); #if ETL_USING_BUILTIN_MEMSET - __builtin_memset(reinterpret_cast(db), + __builtin_memset(reinterpret_cast(db), static_cast(value), sizeof(typename etl::iterator_traits::value_type) * static_cast(de - db)); #else - ::memset(reinterpret_cast(db), + ::memset(reinterpret_cast(db), static_cast(value), sizeof(typename etl::iterator_traits::value_type) * static_cast(de - db)); #endif @@ -2504,13 +2504,13 @@ namespace etl mem_char(TPointer sb, TPointer se, T value) ETL_NOEXCEPT { #if ETL_USING_BUILTIN_MEMCHR - void* result = __builtin_memchr(reinterpret_cast(sb), + void* result = __builtin_memchr(reinterpret_cast(sb), static_cast(value), sizeof(typename etl::iterator_traits::value_type) * static_cast(se - sb)); return (result == 0U) ? reinterpret_cast(se) : reinterpret_cast(result); #else - void* result = ::memchr(reinterpret_cast(sb), + void* result = ::memchr(reinterpret_cast(sb), static_cast(value), sizeof(typename etl::iterator_traits::value_type) * static_cast(se - sb)); @@ -2527,7 +2527,7 @@ namespace etl //*************************************************************************** template ETL_NODISCARD - typename etl::enable_if::value && + typename etl::enable_if::value && etl::is_const::type>::value && etl::is_integral::value && sizeof(T) == 1, const char*>::type @@ -2545,7 +2545,7 @@ namespace etl sizeof(typename etl::iterator_traits::value_type) * static_cast(se - sb)); return (result == 0U) ? reinterpret_cast(se) : reinterpret_cast(result); -#endif +#endif } //*************************************************************************** @@ -2557,25 +2557,25 @@ namespace etl //*************************************************************************** template ETL_NODISCARD - typename etl::enable_if::value && + typename etl::enable_if::value && !etl::is_const::type>::value && etl::is_integral::value && sizeof(T) == 1, char*>::type mem_char(TPointer sb, size_t n, T value) ETL_NOEXCEPT { #if ETL_USING_BUILTIN_MEMCHR - void* result = __builtin_memchr(reinterpret_cast(sb), + void* result = __builtin_memchr(reinterpret_cast(sb), static_cast(value), sizeof(typename etl::iterator_traits::value_type) * n); return (result == 0U) ? reinterpret_cast(sb + n) : reinterpret_cast(result); #else - void* result = ::memchr(reinterpret_cast(sb), + void* result = ::memchr(reinterpret_cast(sb), static_cast(value), sizeof(typename etl::iterator_traits::value_type) * n); return (result == 0U) ? reinterpret_cast(sb + n) : reinterpret_cast(result); -#endif +#endif } //*************************************************************************** @@ -2587,7 +2587,7 @@ namespace etl //*************************************************************************** template ETL_NODISCARD - typename etl::enable_if::value && + typename etl::enable_if::value && etl::is_const::type>::value && etl::is_integral::value && sizeof(T) == 1, const char*>::type @@ -2607,7 +2607,7 @@ namespace etl return (result == 0U) ? reinterpret_cast(sb + n) : reinterpret_cast(result); #endif - + } #if ETL_USING_CPP11 @@ -2687,9 +2687,20 @@ namespace etl ETL_ASSERT(is_aligned(p), ETL_ERROR(alignment_error)); #endif - TObject& v = *reinterpret_cast(p); + return *reinterpret_cast(p); + } - return v; + //***************************************************************************** + /// Get the container at const 'p'. + //***************************************************************************** + template + const TObject& get_object_at(const void* p) + { +#if ETL_IS_DEBUG_BUILD + ETL_ASSERT(is_aligned(p), ETL_ERROR(alignment_error)); +#endif + + return *reinterpret_cast(p); } //***************************************************************************** diff --git a/test/test_memory.cpp b/test/test_memory.cpp index 4b70f3fe..1b88c8a5 100644 --- a/test/test_memory.cpp +++ b/test/test_memory.cpp @@ -1256,7 +1256,7 @@ namespace uint32_t expected[8] = { 0x12345678, 0x76543210, 0x01452367, 0x23670145, 0x67234501, 0x45016723, 0x01324576, 0x76453201 }; uint32_t data[12] = { 0x12345678, 0x76543210, 0x01452367, 0x23670145, 0x67234501, 0x45016723, 0x01324576, 0x76453201, 0, 0, 0, 0 }; const uint32_t* data_begin = &data[0]; - + uint32_t* result = etl::mem_move(data_begin, 8, data + 4); CHECK(std::equal(expected, expected + 8, data + 4)); CHECK(result == data + 4); @@ -1269,7 +1269,7 @@ namespace uint32_t same[8] = { 0x12345678, 0x76543210, 0x01452367, 0x23670145, 0x67234501, 0x45016723, 0x01324576, 0x76453201 }; uint32_t grtr[8] = { 0x12345678, 0x76543210, 0x01452367, 0x23670145, 0x67235501, 0x45016723, 0x01324576, 0x76453201 }; uint32_t less[8] = { 0x12345678, 0x76543210, 0x01452367, 0x23670145, 0x67134501, 0x45016723, 0x01324576, 0x76453201 }; - + CHECK(etl::mem_compare(data, data + 8, same) == 0); CHECK(etl::mem_compare(data, data + 8, grtr) > 0); CHECK(etl::mem_compare(data, data + 8, less) < 0); @@ -1443,7 +1443,7 @@ namespace } //************************************************************************* - class Base + class Base { public: virtual ~Base() {}; @@ -1452,21 +1452,21 @@ namespace static bool function_was_called = false; - class Derived : public Base + class Derived : public Base { public: - Derived() + Derived() { function_was_called = false; } - void function() + void function() { function_was_called = true; } }; - void call(etl::unique_ptr ptr) + void call(etl::unique_ptr ptr) { ptr->function(); } @@ -1477,13 +1477,13 @@ namespace etl::unique_ptr ptr(new Derived()); CHECK(ptr.get() != ETL_NULLPTR); - + call(etl::move(ptr)); CHECK(function_was_called); CHECK(ptr.get() == ETL_NULLPTR); } - + struct Flags { Flags() @@ -1530,7 +1530,7 @@ namespace int a; int b; }; - + alignas(Data) char buffer1[sizeof(Data)]; char* pbuffer1 = buffer1; @@ -1581,14 +1581,14 @@ namespace CHECK_FALSE(flags.destructed); CHECK_EQUAL(1, rdata1b.a); CHECK_EQUAL(2, rdata1b.b); - + flags.Clear(); Data& rdata2b = etl::get_object_at(pbuffer2b); CHECK_FALSE(flags.constructed); CHECK_FALSE(flags.destructed); CHECK_EQUAL(data2.a, rdata2b.a); CHECK_EQUAL(data2.b, rdata2b.b); - + flags.Clear(); Data& rdata3b = etl::get_object_at(pbuffer3b); CHECK_FALSE(flags.constructed); @@ -1612,6 +1612,33 @@ namespace CHECK_TRUE(flags.destructed); } + TEST(test_get_object_at_const_specialization) + { + struct Data + { + Data() + : a(1) + , b(2) + { + flags.constructed = true; + } + + ~Data() = default; + + int a; + int b; + }; + + std::array buffer{}; + etl::construct_object_at(buffer.data(), Data()); + const void* bufferPointer = buffer.data(); + + const Data& rdata = etl::get_object_at(bufferPointer); + CHECK_TRUE(flags.constructed); + CHECK_TRUE(rdata.a == 1); + CHECK_TRUE(rdata.b == 2); + } + TEST(test_construct_get_destroy_object_misaligned) { struct Data From 2f535d385f4e6a29e3f1e6ef9d4c2f6cbb002a24 Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Wed, 12 Nov 2025 19:05:20 +0100 Subject: [PATCH 002/298] Add test for swap (#1221) --- test/test_utility.cpp | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/test/test_utility.cpp b/test/test_utility.cpp index 0a9559e6..60c5163c 100644 --- a/test/test_utility.cpp +++ b/test/test_utility.cpp @@ -788,6 +788,43 @@ namespace CHECK_EQUAL(9U, sizeof(packed)); } #endif + + //********************************* + TEST(test_swap) + { + uint32_t a = 0x12345678; + uint32_t b = 0x87654321; + + ETL_OR_STD::swap(a, b); + + CHECK_EQUAL(a, 0x87654321); + CHECK_EQUAL(b, 0x12345678); + + uint32_t* p_a = &a; + uint32_t* p_b = &b; + + ETL_OR_STD::swap(p_a, p_b); + + CHECK_EQUAL(a, 0x87654321); + CHECK_EQUAL(b, 0x12345678); + CHECK_EQUAL(p_a, &b); + CHECK_EQUAL(p_b, &a); + + uint32_t a_a[4] {0x12345678, 0x23456789, 0x34567890, 0x09876543}; + uint32_t a_b[4] {0x12abcd78, 0x23abcd89, 0x34abcd90, 0x09abcd43}; + + ETL_OR_STD::swap(a_a, a_b); + + CHECK_EQUAL(a_a[0], 0x12abcd78); + CHECK_EQUAL(a_a[1], 0x23abcd89); + CHECK_EQUAL(a_a[2], 0x34abcd90); + CHECK_EQUAL(a_a[3], 0x09abcd43); + + CHECK_EQUAL(a_b[0], 0x12345678); + CHECK_EQUAL(a_b[1], 0x23456789); + CHECK_EQUAL(a_b[2], 0x34567890); + CHECK_EQUAL(a_b[3], 0x09876543); + } }; #if ETL_USING_CPP17 && !defined(ETL_FORCE_CPP11_NONTYPE) From e5dd953c8b5a7792469259c25571a10401581f2c Mon Sep 17 00:00:00 2001 From: lschneidercor Date: Thu, 27 Nov 2025 09:47:50 +0100 Subject: [PATCH 003/298] Add missing include to optional (#1226) When the initializer list is not included, the default std::initializer list is used and ETL_NO_STL would be ignored. --- include/etl/optional.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/etl/optional.h b/include/etl/optional.h index 12d90239..45cb5f92 100644 --- a/include/etl/optional.h +++ b/include/etl/optional.h @@ -39,6 +39,7 @@ SOFTWARE. #include "error_handler.h" #include "utility.h" #include "placement_new.h" +#include "initializer_list.h" namespace etl { From 78f04ad2982a11a7a9f0166526726ca151c8fbef Mon Sep 17 00:00:00 2001 From: Helder Duarte Date: Thu, 27 Nov 2025 08:48:27 +0000 Subject: [PATCH 004/298] Fix value_or not taking const in optional (#1225) --- include/etl/optional.h | 8 ++++---- test/test_optional.cpp | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/include/etl/optional.h b/include/etl/optional.h index 45cb5f92..3b565c5b 100644 --- a/include/etl/optional.h +++ b/include/etl/optional.h @@ -471,7 +471,7 @@ namespace etl etl::enable_if_t::value, T> value_or(U&& default_value) const& { - return has_value() ? value() : etl::forward(default_value); + return has_value() ? value() : static_cast(etl::forward(default_value)); } //*************************************************************************** @@ -482,7 +482,7 @@ namespace etl etl::enable_if_t::value, T> value_or(U&& default_value)&& { - return has_value() ? etl::move(value()) : etl::forward(default_value); + return has_value() ? etl::move(value()) : static_cast(etl::forward(default_value)); } #endif @@ -1085,7 +1085,7 @@ namespace etl etl::enable_if_t::value, T> value_or(U&& default_value) const& { - return has_value() ? value() : etl::forward(default_value); + return has_value() ? value() : static_cast(etl::forward(default_value)); } //*************************************************************************** @@ -1096,7 +1096,7 @@ namespace etl etl::enable_if_t::value, T> value_or(U&& default_value)&& { - return has_value() ? etl::move(value()) : etl::forward(default_value); + return has_value() ? etl::move(value()) : static_cast(etl::forward(default_value)); } #endif diff --git a/test/test_optional.cpp b/test/test_optional.cpp index c5a34d08..42ab7199 100644 --- a/test/test_optional.cpp +++ b/test/test_optional.cpp @@ -298,6 +298,21 @@ namespace CHECK_EQUAL(Data("Value"), result); } + //************************************************************************* + TEST(test_value_or_const) + { + using FundamentalType = int; + using NonFundamentalType = std::string; + + const FundamentalType constFT{ 5 }; + int resultFT = etl::optional{}.value_or(constFT); + CHECK_EQUAL(5, resultFT); + + const NonFundamentalType constNFT{ "Default" }; + NonFundamentalType resultNFT = etl::optional{}.value_or(constNFT); + CHECK_EQUAL("Default", resultNFT); + } + //************************************************************************* struct github_bug_720_bug_helper { From 14e3b9d11edd80755e19d356df39905f16f7465f Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Thu, 27 Nov 2025 09:50:39 +0100 Subject: [PATCH 005/298] Cleanup platform.h includes, add missing test for unaligned_type (#1218) * platform.h include cleanup * Add test for implicit value conversion in unaligned_type --- include/etl/absolute.h | 1 + include/etl/callback_timer_deferred_locked.h | 1 + include/etl/gcd.h | 5 +++-- include/etl/lcm.h | 1 + include/etl/negative.h | 1 + include/etl/observer.h | 3 +-- include/etl/pseudo_moving_average.h | 1 + include/etl/rounded_integral_division.h | 1 + include/etl/scaled_rounding.h | 1 + test/test_unaligned_type.cpp | 3 +++ 10 files changed, 14 insertions(+), 4 deletions(-) diff --git a/include/etl/absolute.h b/include/etl/absolute.h index 316be415..cad11b7c 100644 --- a/include/etl/absolute.h +++ b/include/etl/absolute.h @@ -31,6 +31,7 @@ SOFTWARE. #ifndef ETL_ABSOLUTE_INCLUDED #define ETL_ABSOLUTE_INCLUDED +#include "platform.h" #include "type_traits.h" #include "integral_limits.h" diff --git a/include/etl/callback_timer_deferred_locked.h b/include/etl/callback_timer_deferred_locked.h index ce760648..c6914d6f 100644 --- a/include/etl/callback_timer_deferred_locked.h +++ b/include/etl/callback_timer_deferred_locked.h @@ -29,6 +29,7 @@ SOFTWARE. #ifndef ETL_CALLBACK_TIMER_DEFERRED_LOCKED_INCLUDED #define ETL_CALLBACK_TIMER_DEFERRED_LOCKED_INCLUDED +#include "platform.h" #include "callback_timer_locked.h" #include "etl/nullptr.h" #include "etl/optional.h" diff --git a/include/etl/gcd.h b/include/etl/gcd.h index 0926b2f0..185e5349 100644 --- a/include/etl/gcd.h +++ b/include/etl/gcd.h @@ -28,9 +28,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ******************************************************************************/ -#ifndef ETL_GDC_INCLUDED -#define ETL_GDC_INCLUDED +#ifndef ETL_GCD_INCLUDED +#define ETL_GCD_INCLUDED +#include "platform.h" #include "type_traits.h" #include "absolute.h" #include "static_assert.h" diff --git a/include/etl/lcm.h b/include/etl/lcm.h index 3ffc9821..bc73f566 100644 --- a/include/etl/lcm.h +++ b/include/etl/lcm.h @@ -31,6 +31,7 @@ SOFTWARE. #ifndef ETL_LCM_INCLUDED #define ETL_LCM_INCLUDED +#include "platform.h" #include "type_traits.h" #include "absolute.h" #include "static_assert.h" diff --git a/include/etl/negative.h b/include/etl/negative.h index 4563f4f2..537a51dd 100644 --- a/include/etl/negative.h +++ b/include/etl/negative.h @@ -31,6 +31,7 @@ SOFTWARE. #ifndef ETL_NEGATIVE_INCLUDED #define ETL_NEGATIVE_INCLUDED +#include "platform.h" #include "type_traits.h" namespace etl diff --git a/include/etl/observer.h b/include/etl/observer.h index 8d46f89d..3e915a59 100644 --- a/include/etl/observer.h +++ b/include/etl/observer.h @@ -51,9 +51,8 @@ SOFTWARE. ///\ingroup patterns //***************************************************************************** -#include "algorithm.h" - #include "platform.h" +#include "algorithm.h" #include "vector.h" #include "exception.h" #include "error_handler.h" diff --git a/include/etl/pseudo_moving_average.h b/include/etl/pseudo_moving_average.h index 60f27a38..4a53c0be 100644 --- a/include/etl/pseudo_moving_average.h +++ b/include/etl/pseudo_moving_average.h @@ -31,6 +31,7 @@ SOFTWARE. #ifndef ETL_CUMULATIVE_MOVING_AVERAGE_INCLUDED #define ETL_CUMULATIVE_MOVING_AVERAGE_INCLUDED +#include "platform.h" #include "type_traits.h" #include "iterator.h" diff --git a/include/etl/rounded_integral_division.h b/include/etl/rounded_integral_division.h index cdd0f16b..417b3143 100644 --- a/include/etl/rounded_integral_division.h +++ b/include/etl/rounded_integral_division.h @@ -31,6 +31,7 @@ SOFTWARE. #ifndef ETL_ROUNDED_INTEGRAL_DIVISION_INCLUDED #define ETL_ROUNDED_INTEGRAL_DIVISION_INCLUDED +#include "platform.h" #include "type_traits.h" #include "absolute.h" #include "utility.h" diff --git a/include/etl/scaled_rounding.h b/include/etl/scaled_rounding.h index 595f8ea6..be6a44f6 100644 --- a/include/etl/scaled_rounding.h +++ b/include/etl/scaled_rounding.h @@ -31,6 +31,7 @@ SOFTWARE. #ifndef ETL_SCALED_ROUNDING_INCLUDED #define ETL_SCALED_ROUNDING_INCLUDED +#include "platform.h" #include "static_assert.h" #include "type_traits.h" #include "absolute.h" diff --git a/test/test_unaligned_type.cpp b/test/test_unaligned_type.cpp index e80eeaeb..96827cba 100644 --- a/test/test_unaligned_type.cpp +++ b/test/test_unaligned_type.cpp @@ -1008,6 +1008,9 @@ namespace CHECK_EQUAL(0x1234, test_le.value()); CHECK_EQUAL(0x1234, test_be.value()); + + CHECK_EQUAL(0x1234, test_le); + CHECK_EQUAL(0x1234, test_be); } //************************************************************************* From a6f4c0b4d10fcd7831ee8fc7da6704b4e83175dd Mon Sep 17 00:00:00 2001 From: mike919192 <91038685+mike919192@users.noreply.github.com> Date: Thu, 27 Nov 2025 03:52:37 -0500 Subject: [PATCH 006/298] Basic string checks (#1222) * Add checks for index, front, back, and insert * Add erase checks * Add tests to string_char * Add u16 tests * Add tests to string u32 * Add u8 tests * Add wchar tests * Use size() for back functions. Fix some uses of buffer2 * Add assert for swapped insert iterators. Add tests --- include/etl/basic_string.h | 25 +++- test/test_string_char.cpp | 105 +++++++++++++++- test/test_string_char_external_buffer.cpp | 120 ++++++++++++++++++- test/test_string_u16.cpp | 105 +++++++++++++++- test/test_string_u16_external_buffer.cpp | 120 ++++++++++++++++++- test/test_string_u32.cpp | 105 +++++++++++++++- test/test_string_u32_external_buffer.cpp | 120 ++++++++++++++++++- test/test_string_u8.cpp | 107 ++++++++++++++++- test/test_string_u8_external_buffer.cpp | 120 ++++++++++++++++++- test/test_string_wchar_t.cpp | 107 ++++++++++++++++- test/test_string_wchar_t_external_buffer.cpp | 120 ++++++++++++++++++- 11 files changed, 1100 insertions(+), 54 deletions(-) diff --git a/include/etl/basic_string.h b/include/etl/basic_string.h index 462faec1..4d8157cf 100644 --- a/include/etl/basic_string.h +++ b/include/etl/basic_string.h @@ -560,6 +560,7 @@ namespace etl //********************************************************************* reference operator [](size_type i) { + ETL_ASSERT_CHECK_INDEX_OPERATOR(i < size(), ETL_ERROR(string_out_of_bounds)); return p_buffer[i]; } @@ -570,6 +571,7 @@ namespace etl //********************************************************************* const_reference operator [](size_type i) const { + ETL_ASSERT_CHECK_INDEX_OPERATOR(i < size(), ETL_ERROR(string_out_of_bounds)); return p_buffer[i]; } @@ -603,6 +605,7 @@ namespace etl //********************************************************************* reference front() { + ETL_ASSERT_CHECK_EXTRA(size() > 0, ETL_ERROR(string_out_of_bounds)); return p_buffer[0]; } @@ -612,6 +615,7 @@ namespace etl //********************************************************************* const_reference front() const { + ETL_ASSERT_CHECK_EXTRA(size() > 0, ETL_ERROR(string_out_of_bounds)); return p_buffer[0]; } @@ -621,7 +625,8 @@ namespace etl //********************************************************************* reference back() { - return p_buffer[current_size - 1]; + ETL_ASSERT_CHECK_EXTRA(size() > 0, ETL_ERROR(string_out_of_bounds)); + return p_buffer[size() - 1]; } //********************************************************************* @@ -630,7 +635,8 @@ namespace etl //********************************************************************* const_reference back() const { - return p_buffer[current_size - 1]; + ETL_ASSERT_CHECK_EXTRA(size() > 0, ETL_ERROR(string_out_of_bounds)); + return p_buffer[size() - 1]; } //********************************************************************* @@ -932,6 +938,8 @@ namespace etl //********************************************************************* iterator insert(const_iterator position, T value) { + ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(string_out_of_bounds)); + // Quick hack, as iterators are pointers. iterator insert_position = to_iterator(position); @@ -984,6 +992,8 @@ namespace etl //********************************************************************* iterator insert(const_iterator position, size_type n, T value) { + ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(string_out_of_bounds)); + iterator position_ = to_iterator(position); if (n == 0) @@ -1071,6 +1081,9 @@ namespace etl template iterator insert(const_iterator position, TIterator first, TIterator last) { + ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(string_out_of_bounds)); + ETL_ASSERT_CHECK_EXTRA(first <= last, ETL_ERROR(string_iterator)); + iterator position_ = to_iterator(position); if (first == last) @@ -1307,6 +1320,8 @@ namespace etl //********************************************************************* etl::ibasic_string& erase(size_type position, size_type length_ = npos) { + ETL_ASSERT_CHECK_EXTRA(position <= size(), ETL_ERROR(string_out_of_bounds)); + // Limit the length. length_ = etl::min(length_, size() - position); @@ -1322,6 +1337,8 @@ namespace etl //********************************************************************* iterator erase(iterator i_element) { + ETL_ASSERT_CHECK_EXTRA(cbegin() <= i_element && i_element < cend(), ETL_ERROR(string_out_of_bounds)); + etl::mem_move(i_element + 1, end(), i_element); p_buffer[--current_size] = 0; @@ -1335,6 +1352,8 @@ namespace etl //********************************************************************* iterator erase(const_iterator i_element) { + ETL_ASSERT_CHECK_EXTRA(cbegin() <= i_element && i_element < cend(), ETL_ERROR(string_out_of_bounds)); + iterator i_element_(to_iterator(i_element)); etl::mem_move(i_element + 1, end(), i_element_); @@ -1353,6 +1372,8 @@ namespace etl //********************************************************************* iterator erase(const_iterator first, const_iterator last) { + ETL_ASSERT_CHECK_EXTRA(cbegin() <= first && first <= last && last <= cend(), ETL_ERROR(string_out_of_bounds)); + iterator first_ = to_iterator(first); iterator last_ = to_iterator(last); diff --git a/test/test_string_char.cpp b/test/test_string_char.cpp index 7ee55e32..6cf70b28 100644 --- a/test/test_string_char.cpp +++ b/test/test_string_char.cpp @@ -614,8 +614,8 @@ namespace Text text(initial_text.c_str()); const Text constText(initial_text.c_str()); - CHECK_EQUAL(&text[initial_text.size()], text.end()); - CHECK_EQUAL(&constText[initial_text.size()], constText.end()); + CHECK_EQUAL(text.begin() + text.size(), text.end()); + CHECK_EQUAL(constText.begin() + constText.size(), constText.end()); } //************************************************************************* @@ -910,6 +910,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -924,6 +926,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -964,6 +968,9 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + Text emptyText; + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -974,6 +981,9 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + const Text emptyText; + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -984,6 +994,9 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + Text emptyText; + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -994,6 +1007,9 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + const Text emptyText; + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1327,6 +1343,20 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value_outofbounds) + { + const size_t INITIAL_SIZE = 5; + const value_t INITIAL_VALUE = STR('A'); + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_value_excess) { @@ -1402,6 +1432,21 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + const size_t INSERT_SIZE = 3UL; + const value_t INITIAL_VALUE = STR('A'); + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), INSERT_SIZE, INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_n_value_excess) { @@ -1501,6 +1546,30 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), insert_text.cbegin(), insert_text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_swapped_iterators) + { + const size_t INITIAL_SIZE = 5UL; + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + CHECK_THROW(text.insert(text.cbegin(), insert_text.cend(), insert_text.cbegin()), etl::string_iterator); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_range_excess) { @@ -3266,6 +3335,23 @@ namespace #endif } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_outofbounds) + { + Text text(initial_text.c_str()); + + CHECK_THROW(text.erase(text.end()), etl::string_out_of_bounds); + CHECK_THROW(text.erase(text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_position_outofbounds) + { + Text text(initial_text.c_str()); + + CHECK_THROW(text.erase(text.size() + 1), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_range) { @@ -3283,6 +3369,15 @@ namespace #endif } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range_outofbounds) + { + Text text(initial_text.c_str()); + Text text2(initial_text.c_str()); + + CHECK_THROW(text.erase(text2.begin(), text2.end()), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_clear) { @@ -5043,7 +5138,7 @@ namespace // Test with actual string type. Text text(STR("ABCDEFHIJKL")); size_t hash = etl::hash()(text); - size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(&text[0]), reinterpret_cast(&text[text.size()])); + size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(text.data()), reinterpret_cast(text.data_end())); CHECK_EQUAL(compare_hash, hash); // Test with interface string type. @@ -5305,7 +5400,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } @@ -5323,7 +5418,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } diff --git a/test/test_string_char_external_buffer.cpp b/test/test_string_char_external_buffer.cpp index 7346042b..e644f578 100644 --- a/test/test_string_char_external_buffer.cpp +++ b/test/test_string_char_external_buffer.cpp @@ -767,8 +767,8 @@ namespace TextBuffer buffer2{0}; const Text constText(initial_text.c_str(), buffer2.data(), buffer2.size()); - CHECK_EQUAL(&text[initial_text.size()], text.end()); - CHECK_EQUAL(&constText[initial_text.size()], constText.end()); + CHECK_EQUAL(text.begin() + text.size(), text.end()); + CHECK_EQUAL(constText.begin() + constText.size(), constText.end()); } //************************************************************************* @@ -1069,6 +1069,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -1085,6 +1087,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -1133,6 +1137,10 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1145,6 +1153,10 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + const Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1157,6 +1169,10 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1169,6 +1185,10 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + const Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1531,6 +1551,22 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value_outofbounds) + { + const size_t INITIAL_SIZE = 5; + const value_t INITIAL_VALUE = STR('A'); + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_value_excess) { @@ -1608,6 +1644,23 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + const size_t INSERT_SIZE = 3UL; + const value_t INITIAL_VALUE = STR('A'); + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), INSERT_SIZE, INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_n_value_excess) { @@ -1709,6 +1762,33 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), insert_text.cbegin(), insert_text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_swapped_iterators) + { + const size_t INITIAL_SIZE = 5UL; + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + CHECK_THROW(text.insert(text.cbegin(), insert_text.cend(), insert_text.cbegin()), etl::string_iterator); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_range_excess) { @@ -3442,6 +3522,25 @@ namespace CHECK_FALSE(text.is_truncated()); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + CHECK_THROW(text.erase(text.end()), etl::string_out_of_bounds); + CHECK_THROW(text.erase(text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_position_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + CHECK_THROW(text.erase(text.size() + 1), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_range) { @@ -3459,6 +3558,17 @@ namespace CHECK_FALSE(text.is_truncated()); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + TextBuffer buffer2{0}; + Text text2(initial_text.c_str(), buffer2.data(), buffer2.size()); + + CHECK_THROW(text.erase(text2.begin(), text2.end()), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_clear) { @@ -5302,7 +5412,7 @@ namespace TextBuffer buffer{0}; Text text(STR("ABCDEFHIJKL"), buffer.data(), buffer.size()); size_t hash = etl::hash()(text); - size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(&text[0]), reinterpret_cast(&text[text.size()])); + size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(text.data()), reinterpret_cast(text.data_end())); CHECK_EQUAL(compare_hash, hash); // Test with interface string type. @@ -5589,7 +5699,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } @@ -5609,7 +5719,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } diff --git a/test/test_string_u16.cpp b/test/test_string_u16.cpp index 6662a82c..a569d269 100644 --- a/test/test_string_u16.cpp +++ b/test/test_string_u16.cpp @@ -658,8 +658,8 @@ namespace Text text(initial_text.c_str()); const Text constText(initial_text.c_str()); - CHECK_EQUAL(&text[initial_text.size()], text.end()); - CHECK_EQUAL(&constText[initial_text.size()], constText.end()); + CHECK_EQUAL(text.begin() + text.size(), text.end()); + CHECK_EQUAL(constText.begin() + constText.size(), constText.end()); } //************************************************************************* @@ -954,6 +954,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -968,6 +970,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -1008,6 +1012,9 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + Text emptyText; + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1018,6 +1025,9 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + const Text emptyText; + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1028,6 +1038,9 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + Text emptyText; + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1038,6 +1051,9 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + const Text emptyText; + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1399,6 +1415,20 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value_outofbounds) + { + const size_t INITIAL_SIZE = 5; + const value_t INITIAL_VALUE = STR('A'); + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_value_excess) { @@ -1474,6 +1504,21 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + const size_t INSERT_SIZE = 3UL; + const value_t INITIAL_VALUE = STR('A'); + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), INSERT_SIZE, INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_n_value_excess) { @@ -1573,6 +1618,30 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), insert_text.cbegin(), insert_text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_swapped_iterators) + { + const size_t INITIAL_SIZE = 5UL; + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + CHECK_THROW(text.insert(text.cbegin(), insert_text.cend(), insert_text.cbegin()), etl::string_iterator); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_range_excess) { @@ -3338,6 +3407,23 @@ namespace #endif } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_outofbounds) + { + Text text(initial_text.c_str()); + + CHECK_THROW(text.erase(text.end()), etl::string_out_of_bounds); + CHECK_THROW(text.erase(text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_position_outofbounds) + { + Text text(initial_text.c_str()); + + CHECK_THROW(text.erase(text.size() + 1), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_range) { @@ -3355,6 +3441,15 @@ namespace #endif } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range_outofbounds) + { + Text text(initial_text.c_str()); + Text text2(initial_text.c_str()); + + CHECK_THROW(text.erase(text2.begin(), text2.end()), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_clear) { @@ -5115,7 +5210,7 @@ namespace // Test with actual string type. Text text(STR("ABCDEFHIJKL")); size_t hash = etl::hash()(text); - size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(&text[0]), reinterpret_cast(&text[text.size()])); + size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(text.data()), reinterpret_cast(text.data_end())); CHECK_EQUAL(compare_hash, hash); // Test with interface string type. @@ -5377,7 +5472,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } @@ -5395,7 +5490,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } diff --git a/test/test_string_u16_external_buffer.cpp b/test/test_string_u16_external_buffer.cpp index a7a3279c..41e60750 100644 --- a/test/test_string_u16_external_buffer.cpp +++ b/test/test_string_u16_external_buffer.cpp @@ -836,8 +836,8 @@ namespace TextBuffer buffer2{0}; const Text constText(initial_text.c_str(), buffer2.data(), buffer2.size()); - CHECK_EQUAL(&text[initial_text.size()], text.end()); - CHECK_EQUAL(&constText[initial_text.size()], constText.end()); + CHECK_EQUAL(text.begin() + text.size(), text.end()); + CHECK_EQUAL(constText.begin() + constText.size(), constText.end()); } //************************************************************************* @@ -1138,6 +1138,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -1154,6 +1156,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -1202,6 +1206,10 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1214,6 +1222,10 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + const Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1226,6 +1238,10 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1238,6 +1254,10 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + const Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1632,6 +1652,22 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value_outofbounds) + { + const size_t INITIAL_SIZE = 5; + const value_t INITIAL_VALUE = STR('A'); + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_value_excess) { @@ -1709,6 +1745,23 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + const size_t INSERT_SIZE = 3UL; + const value_t INITIAL_VALUE = STR('A'); + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), INSERT_SIZE, INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_n_value_excess) { @@ -1810,6 +1863,33 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), insert_text.cbegin(), insert_text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_swapped_iterators) + { + const size_t INITIAL_SIZE = 5UL; + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + CHECK_THROW(text.insert(text.cbegin(), insert_text.cend(), insert_text.cbegin()), etl::string_iterator); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_range_excess) { @@ -3542,6 +3622,25 @@ namespace CHECK_FALSE(text.is_truncated()); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + CHECK_THROW(text.erase(text.end()), etl::string_out_of_bounds); + CHECK_THROW(text.erase(text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_position_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + CHECK_THROW(text.erase(text.size() + 1), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_range) { @@ -3559,6 +3658,17 @@ namespace CHECK_FALSE(text.is_truncated()); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + TextBuffer buffer2{0}; + Text text2(initial_text.c_str(), buffer2.data(), buffer2.size()); + + CHECK_THROW(text.erase(text2.begin(), text2.end()), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_clear) { @@ -5402,7 +5512,7 @@ namespace TextBuffer buffer{0}; Text text(STR("ABCDEFHIJKL"), buffer.data(), buffer.size()); size_t hash = etl::hash()(text); - size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(&text[0]), reinterpret_cast(&text[text.size()])); + size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(text.data()), reinterpret_cast(text.data_end())); CHECK_EQUAL(compare_hash, hash); // Test with interface string type. @@ -5689,7 +5799,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } @@ -5709,7 +5819,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } diff --git a/test/test_string_u32.cpp b/test/test_string_u32.cpp index 7b6be11d..5201371e 100644 --- a/test/test_string_u32.cpp +++ b/test/test_string_u32.cpp @@ -658,8 +658,8 @@ namespace Text text(initial_text.c_str()); const Text constText(initial_text.c_str()); - CHECK_EQUAL(&text[initial_text.size()], text.end()); - CHECK_EQUAL(&constText[initial_text.size()], constText.end()); + CHECK_EQUAL(text.begin() + text.size(), text.end()); + CHECK_EQUAL(constText.begin() + constText.size(), constText.end()); } //************************************************************************* @@ -954,6 +954,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -968,6 +970,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -1008,6 +1012,9 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + Text emptyText; + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1018,6 +1025,9 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + const Text emptyText; + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1028,6 +1038,9 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + Text emptyText; + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1038,6 +1051,9 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + const Text emptyText; + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1399,6 +1415,20 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value_outofbounds) + { + const size_t INITIAL_SIZE = 5; + const value_t INITIAL_VALUE = STR('A'); + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_value_excess) { @@ -1474,6 +1504,21 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + const size_t INSERT_SIZE = 3UL; + const value_t INITIAL_VALUE = STR('A'); + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), INSERT_SIZE, INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_n_value_excess) { @@ -1573,6 +1618,30 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), insert_text.cbegin(), insert_text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_swapped_iterators) + { + const size_t INITIAL_SIZE = 5UL; + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + CHECK_THROW(text.insert(text.cbegin(), insert_text.cend(), insert_text.cbegin()), etl::string_iterator); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_range_excess) { @@ -3338,6 +3407,23 @@ namespace #endif } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_outofbounds) + { + Text text(initial_text.c_str()); + + CHECK_THROW(text.erase(text.end()), etl::string_out_of_bounds); + CHECK_THROW(text.erase(text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_position_outofbounds) + { + Text text(initial_text.c_str()); + + CHECK_THROW(text.erase(text.size() + 1), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_range) { @@ -3355,6 +3441,15 @@ namespace #endif } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range_outofbounds) + { + Text text(initial_text.c_str()); + Text text2(initial_text.c_str()); + + CHECK_THROW(text.erase(text2.begin(), text2.end()), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_clear) { @@ -5115,7 +5210,7 @@ namespace // Test with actual string type. Text text(STR("ABCDEFHIJKL")); size_t hash = etl::hash()(text); - size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(&text[0]), reinterpret_cast(&text[text.size()])); + size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(text.data()), reinterpret_cast(text.data_end())); CHECK_EQUAL(compare_hash, hash); // Test with interface string type. @@ -5377,7 +5472,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } @@ -5395,7 +5490,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } diff --git a/test/test_string_u32_external_buffer.cpp b/test/test_string_u32_external_buffer.cpp index fb7d2104..f02a460d 100644 --- a/test/test_string_u32_external_buffer.cpp +++ b/test/test_string_u32_external_buffer.cpp @@ -836,8 +836,8 @@ namespace TextBuffer buffer2{0}; const Text constText(initial_text.c_str(), buffer2.data(), buffer2.size()); - CHECK_EQUAL(&text[initial_text.size()], text.end()); - CHECK_EQUAL(&constText[initial_text.size()], constText.end()); + CHECK_EQUAL(text.begin() + text.size(), text.end()); + CHECK_EQUAL(constText.begin() + constText.size(), constText.end()); } //************************************************************************* @@ -1138,6 +1138,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -1154,6 +1156,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -1202,6 +1206,10 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1214,6 +1222,10 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + const Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1226,6 +1238,10 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1238,6 +1254,10 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + const Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1632,6 +1652,22 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value_outofbounds) + { + const size_t INITIAL_SIZE = 5; + const value_t INITIAL_VALUE = STR('A'); + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_value_excess) { @@ -1709,6 +1745,23 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + const size_t INSERT_SIZE = 3UL; + const value_t INITIAL_VALUE = STR('A'); + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), INSERT_SIZE, INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_n_value_excess) { @@ -1810,6 +1863,33 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), insert_text.cbegin(), insert_text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_swapped_iterators) + { + const size_t INITIAL_SIZE = 5UL; + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + CHECK_THROW(text.insert(text.cbegin(), insert_text.cend(), insert_text.cbegin()), etl::string_iterator); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_range_excess) { @@ -3542,6 +3622,25 @@ namespace CHECK_FALSE(text.is_truncated()); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + CHECK_THROW(text.erase(text.end()), etl::string_out_of_bounds); + CHECK_THROW(text.erase(text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_position_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + CHECK_THROW(text.erase(text.size() + 1), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_range) { @@ -3559,6 +3658,17 @@ namespace CHECK_FALSE(text.is_truncated()); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + TextBuffer buffer2{0}; + Text text2(initial_text.c_str(), buffer2.data(), buffer2.size()); + + CHECK_THROW(text.erase(text2.begin(), text2.end()), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_clear) { @@ -5402,7 +5512,7 @@ namespace TextBuffer buffer{0}; Text text(STR("ABCDEFHIJKL"), buffer.data(), buffer.size()); size_t hash = etl::hash()(text); - size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(&text[0]), reinterpret_cast(&text[text.size()])); + size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(text.data()), reinterpret_cast(text.data_end())); CHECK_EQUAL(compare_hash, hash); // Test with interface string type. @@ -5689,7 +5799,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } @@ -5709,7 +5819,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } diff --git a/test/test_string_u8.cpp b/test/test_string_u8.cpp index b01a67f2..65eeb767 100644 --- a/test/test_string_u8.cpp +++ b/test/test_string_u8.cpp @@ -631,8 +631,8 @@ namespace Text text(initial_text.c_str()); const Text constText(initial_text.c_str()); - CHECK_EQUAL(&text[initial_text.size()], text.end()); - CHECK_EQUAL(&constText[initial_text.size()], constText.end()); + CHECK_EQUAL(text.begin() + text.size(), text.end()); + CHECK_EQUAL(constText.begin() + constText.size(), constText.end()); } //************************************************************************* @@ -927,6 +927,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -941,6 +943,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -981,6 +985,9 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + Text emptyText; + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -991,6 +998,9 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + const Text emptyText; + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1001,6 +1011,9 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + Text emptyText; + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1011,6 +1024,9 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + const Text emptyText; + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1344,6 +1360,20 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value_outofbounds) + { + const size_t INITIAL_SIZE = 5; + const value_t INITIAL_VALUE = STR('A'); + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_value_excess) { @@ -1419,6 +1449,21 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + const size_t INSERT_SIZE = 3UL; + const value_t INITIAL_VALUE = STR('A'); + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), INSERT_SIZE, INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_n_value_excess) { @@ -1512,12 +1557,36 @@ namespace compare_text.insert(compare_text.cbegin() + offset, insert_text.cbegin(), insert_text.cend()); CHECK_FALSE(text.is_truncated()); -# + bool is_equal = Equal(compare_text, text); CHECK(is_equal); } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), insert_text.cbegin(), insert_text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_swapped_iterators) + { + const size_t INITIAL_SIZE = 5UL; + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + CHECK_THROW(text.insert(text.cbegin(), insert_text.cend(), insert_text.cbegin()), etl::string_iterator); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_range_excess) { @@ -3283,6 +3352,23 @@ namespace #endif } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_outofbounds) + { + Text text(initial_text.c_str()); + + CHECK_THROW(text.erase(text.end()), etl::string_out_of_bounds); + CHECK_THROW(text.erase(text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_position_outofbounds) + { + Text text(initial_text.c_str()); + + CHECK_THROW(text.erase(text.size() + 1), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_range) { @@ -3300,6 +3386,15 @@ namespace #endif } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range_outofbounds) + { + Text text(initial_text.c_str()); + Text text2(initial_text.c_str()); + + CHECK_THROW(text.erase(text2.begin(), text2.end()), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_clear) { @@ -5060,7 +5155,7 @@ namespace // Test with actual string type. Text text(STR("ABCDEFHIJKL")); size_t hash = etl::hash()(text); - size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(&text[0]), reinterpret_cast(&text[text.size()])); + size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(text.data()), reinterpret_cast(text.data_end())); CHECK_EQUAL(compare_hash, hash); // Test with interface string type. @@ -5322,7 +5417,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } @@ -5340,7 +5435,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } diff --git a/test/test_string_u8_external_buffer.cpp b/test/test_string_u8_external_buffer.cpp index fe79d570..6f4befa5 100644 --- a/test/test_string_u8_external_buffer.cpp +++ b/test/test_string_u8_external_buffer.cpp @@ -784,8 +784,8 @@ namespace TextBuffer buffer2{0}; const Text constText(initial_text.c_str(), buffer2.data(), buffer2.size()); - CHECK_EQUAL(&text[initial_text.size()], text.end()); - CHECK_EQUAL(&constText[initial_text.size()], constText.end()); + CHECK_EQUAL(text.begin() + text.size(), text.end()); + CHECK_EQUAL(constText.begin() + constText.size(), constText.end()); } //************************************************************************* @@ -1086,6 +1086,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -1102,6 +1104,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -1150,6 +1154,10 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1162,6 +1170,10 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + const Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1174,6 +1186,10 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1186,6 +1202,10 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + const Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1548,6 +1568,22 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value_outofbounds) + { + const size_t INITIAL_SIZE = 5; + const value_t INITIAL_VALUE = STR('A'); + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_value_excess) { @@ -1625,6 +1661,23 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + const size_t INSERT_SIZE = 3UL; + const value_t INITIAL_VALUE = STR('A'); + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), INSERT_SIZE, INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_n_value_excess) { @@ -1726,6 +1779,33 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), insert_text.cbegin(), insert_text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_swapped_iterators) + { + const size_t INITIAL_SIZE = 5UL; + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + CHECK_THROW(text.insert(text.cbegin(), insert_text.cend(), insert_text.cbegin()), etl::string_iterator); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_range_excess) { @@ -3458,6 +3538,25 @@ namespace CHECK_FALSE(text.is_truncated()); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + CHECK_THROW(text.erase(text.end()), etl::string_out_of_bounds); + CHECK_THROW(text.erase(text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_position_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + CHECK_THROW(text.erase(text.size() + 1), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_range) { @@ -3475,6 +3574,17 @@ namespace CHECK_FALSE(text.is_truncated()); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + TextBuffer buffer2{0}; + Text text2(initial_text.c_str(), buffer2.data(), buffer2.size()); + + CHECK_THROW(text.erase(text2.begin(), text2.end()), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_clear) { @@ -5321,7 +5431,7 @@ namespace TextBuffer buffer{0}; Text text(STR("ABCDEFHIJKL"), buffer.data(), buffer.size()); size_t hash = etl::hash()(text); - size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(&text[0]), reinterpret_cast(&text[text.size()])); + size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(text.data()), reinterpret_cast(text.data_end())); CHECK_EQUAL(compare_hash, hash); // Test with interface string type. @@ -5608,7 +5718,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } @@ -5628,7 +5738,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } diff --git a/test/test_string_wchar_t.cpp b/test/test_string_wchar_t.cpp index b269b70c..4ac88729 100644 --- a/test/test_string_wchar_t.cpp +++ b/test/test_string_wchar_t.cpp @@ -659,8 +659,8 @@ namespace Text text(initial_text.c_str()); const Text constText(initial_text.c_str()); - CHECK_EQUAL(&text[initial_text.size()], text.end()); - CHECK_EQUAL(&constText[initial_text.size()], constText.end()); + CHECK_EQUAL(text.begin() + text.size(), text.end()); + CHECK_EQUAL(constText.begin() + constText.size(), constText.end()); } //************************************************************************* @@ -955,6 +955,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -969,6 +971,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -1009,6 +1013,9 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + Text emptyText; + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1019,6 +1026,9 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + const Text emptyText; + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1029,6 +1039,9 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + Text emptyText; + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1039,6 +1052,9 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + const Text emptyText; + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1400,6 +1416,20 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value_outofbounds) + { + const size_t INITIAL_SIZE = 5; + const value_t INITIAL_VALUE = STR('A'); + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_value_excess) { @@ -1475,6 +1505,21 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + const size_t INSERT_SIZE = 3UL; + const value_t INITIAL_VALUE = STR('A'); + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), INSERT_SIZE, INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_n_value_excess) { @@ -1568,12 +1613,36 @@ namespace compare_text.insert(compare_text.cbegin() + offset, insert_text.cbegin(), insert_text.cend()); CHECK_FALSE(text.is_truncated()); -# + bool is_equal = Equal(compare_text, text); CHECK(is_equal); } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), insert_text.cbegin(), insert_text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_swapped_iterators) + { + const size_t INITIAL_SIZE = 5UL; + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + CHECK_THROW(text.insert(text.cbegin(), insert_text.cend(), insert_text.cbegin()), etl::string_iterator); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_range_excess) { @@ -3339,6 +3408,23 @@ namespace #endif } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_outofbounds) + { + Text text(initial_text.c_str()); + + CHECK_THROW(text.erase(text.end()), etl::string_out_of_bounds); + CHECK_THROW(text.erase(text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_position_outofbounds) + { + Text text(initial_text.c_str()); + + CHECK_THROW(text.erase(text.size() + 1), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_range) { @@ -3356,6 +3442,15 @@ namespace #endif } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range_outofbounds) + { + Text text(initial_text.c_str()); + Text text2(initial_text.c_str()); + + CHECK_THROW(text.erase(text2.begin(), text2.end()), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_clear) { @@ -5116,7 +5211,7 @@ namespace // Test with actual string type. Text text(STR("ABCDEFHIJKL")); size_t hash = etl::hash()(text); - size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(&text[0]), reinterpret_cast(&text[text.size()])); + size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(text.data()), reinterpret_cast(text.data_end())); CHECK_EQUAL(compare_hash, hash); // Test with interface string type. @@ -5378,7 +5473,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } @@ -5396,7 +5491,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } diff --git a/test/test_string_wchar_t_external_buffer.cpp b/test/test_string_wchar_t_external_buffer.cpp index 2926beb2..6b1b5e08 100644 --- a/test/test_string_wchar_t_external_buffer.cpp +++ b/test/test_string_wchar_t_external_buffer.cpp @@ -839,8 +839,8 @@ namespace TextBuffer buffer2{0}; const Text constText(initial_text.c_str(), buffer2.data(), buffer2.size()); - CHECK_EQUAL(&text[initial_text.size()], text.end()); - CHECK_EQUAL(&constText[initial_text.size()], constText.end()); + CHECK_EQUAL(text.begin() + text.size(), text.end()); + CHECK_EQUAL(constText.begin() + constText.size(), constText.end()); } //************************************************************************* @@ -1141,6 +1141,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -1157,6 +1159,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -1205,6 +1209,10 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1217,6 +1225,10 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + const Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1229,6 +1241,10 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1241,6 +1257,10 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + const Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1635,6 +1655,22 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value_outofbounds) + { + const size_t INITIAL_SIZE = 5; + const value_t INITIAL_VALUE = STR('A'); + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_value_excess) { @@ -1712,6 +1748,23 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + const size_t INSERT_SIZE = 3UL; + const value_t INITIAL_VALUE = STR('A'); + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), INSERT_SIZE, INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_n_value_excess) { @@ -1813,6 +1866,33 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), insert_text.cbegin(), insert_text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_swapped_iterators) + { + const size_t INITIAL_SIZE = 5UL; + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + CHECK_THROW(text.insert(text.cbegin(), insert_text.cend(), insert_text.cbegin()), etl::string_iterator); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_range_excess) { @@ -3545,6 +3625,25 @@ namespace CHECK_FALSE(text.is_truncated()); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + CHECK_THROW(text.erase(text.end()), etl::string_out_of_bounds); + CHECK_THROW(text.erase(text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_position_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + CHECK_THROW(text.erase(text.size() + 1), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_range) { @@ -3562,6 +3661,17 @@ namespace CHECK_FALSE(text.is_truncated()); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + TextBuffer buffer2{0}; + Text text2(initial_text.c_str(), buffer2.data(), buffer2.size()); + + CHECK_THROW(text.erase(text2.begin(), text2.end()), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_clear) { @@ -5405,7 +5515,7 @@ namespace TextBuffer buffer{0}; Text text(STR("ABCDEFHIJKL"), buffer.data(), buffer.size()); size_t hash = etl::hash()(text); - size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(&text[0]), reinterpret_cast(&text[text.size()])); + size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(text.data()), reinterpret_cast(text.data_end())); CHECK_EQUAL(compare_hash, hash); // Test with interface string type. @@ -5692,7 +5802,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } @@ -5712,7 +5822,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } From efd5c5741961ddb6b7f944dbd13d8606b44083d3 Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Thu, 27 Nov 2025 09:54:13 +0100 Subject: [PATCH 007/298] Change generators to reflect changes in fsm.h and type_traits.h (#1211) Previous changes were wrongfully made in fsm.h and type_traits.h instead of in their generator counterparts. Add CI check to ensure generated files are in sync. --- .devcontainer/Dockerfile | 4 ++- .github/workflows/generator.yml | 25 +++++++++++++++++ include/etl/generators/fsm_generator.h | 28 ++++++------------- .../etl/generators/type_traits_generator.h | 22 +++++++++++++++ 4 files changed, 58 insertions(+), 21 deletions(-) create mode 100644 .github/workflows/generator.yml diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 4cd52cc1..090b5302 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -10,7 +10,9 @@ COPY ./reinstall-cmake.sh /tmp/ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ && apt-get -y install --no-install-recommends \ git \ - wget + wget \ + python3-cogapp \ + && rm -rf /var/lib/apt/lists/* RUN if [ "${REINSTALL_CMAKE_VERSION_FROM_SOURCE}" != "none" ]; then \ chmod +x /tmp/reinstall-cmake.sh && /tmp/reinstall-cmake.sh ${REINSTALL_CMAKE_VERSION_FROM_SOURCE}; \ diff --git a/.github/workflows/generator.yml b/.github/workflows/generator.yml new file mode 100644 index 00000000..032ffd1e --- /dev/null +++ b/.github/workflows/generator.yml @@ -0,0 +1,25 @@ +name: generator checks +on: + push: + branches: [ master, development, pull-request/* ] + pull_request: + branches: [ master, pull-request/* ] + types: [opened, synchronize, reopened] + +jobs: + generator-run: + name: Header Generator + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Generate + run: | + sudo apt-get update + sudo apt-get install -y python3-cogapp + cd include/etl/generators && bash generate.bat + + - name: Check Generated Headers For Changes + run: | + git diff --exit-code diff --git a/include/etl/generators/fsm_generator.h b/include/etl/generators/fsm_generator.h index 161c413b..36ba80bb 100644 --- a/include/etl/generators/fsm_generator.h +++ b/include/etl/generators/fsm_generator.h @@ -179,18 +179,6 @@ namespace etl } }; - //*************************************************************************** - /// Exception for forbidden state changes. - //*************************************************************************** - class fsm_state_composite_state_change_forbidden : public etl::fsm_exception - { - public: - fsm_state_composite_state_change_forbidden(string_type file_name_, numeric_type line_number_) - : etl::fsm_exception(ETL_ERROR_TEXT("fsm:change in composite state forbidden", ETL_FSM_FILE_ID"E"), file_name_, line_number_) - { - } - }; - //*************************************************************************** /// Exception for message received but not started. //*************************************************************************** @@ -356,7 +344,6 @@ namespace etl if (p_default_child == ETL_NULLPTR) { - p_active_child = &state; p_default_child = &state; } } @@ -507,7 +494,7 @@ namespace etl virtual void start(bool call_on_enter_state = true) { // Can only be started once. - if (p_state == ETL_NULLPTR) + if (!is_started()) { p_state = state_list[0]; ETL_ASSERT(p_state != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception)); @@ -615,7 +602,7 @@ namespace etl //******************************************* virtual void reset(bool call_on_exit_state = false) { - if ((p_state != ETL_NULLPTR) && call_on_exit_state) + if (is_started() && call_on_exit_state) { p_state->on_exit_state(); } @@ -662,6 +649,12 @@ namespace etl //******************************************* virtual etl::fsm_state_id_t process_state_change(etl::fsm_state_id_t next_state_id) { + if (is_self_transition(next_state_id)) + { + p_state->on_exit_state(); + next_state_id = p_state->on_enter_state(); + } + if (have_changed_state(next_state_id)) { ETL_ASSERT_OR_RETURN_VALUE(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception), p_state->get_state_id()); @@ -681,11 +674,6 @@ namespace etl } } while (p_next_state != p_state); // Have we changed state again? } - else if (is_self_transition(next_state_id)) - { - p_state->on_exit_state(); - p_state->on_enter_state(); - } return p_state->get_state_id(); } diff --git a/include/etl/generators/type_traits_generator.h b/include/etl/generators/type_traits_generator.h index d47c14dc..a03242a9 100644 --- a/include/etl/generators/type_traits_generator.h +++ b/include/etl/generators/type_traits_generator.h @@ -2489,6 +2489,28 @@ typedef integral_constant true_type; template class Template> inline constexpr bool is_specialization_v = etl::is_specialization::value; #endif + + //********************************************* + // is_constant_evaluated + ETL_CONSTEXPR inline bool is_constant_evaluated() ETL_NOEXCEPT + { +#if ETL_USING_CPP23 + if consteval + { + return true; + } + else + { + return false; + } +#elif ETL_USING_BUILTIN_IS_CONSTANT_EVALUATED == 1 + // fallback for C++20 on supported compilers + return __builtin_is_constant_evaluated(); +#else + // default if unsupported + return false; +#endif + } } // Helper macros From 79b41c85afa9f46d554194c84e467876cf13052e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1nyi=20B=C3=A9la?= <91312503+ivanyib@users.noreply.github.com> Date: Sat, 29 Nov 2025 10:38:10 +0100 Subject: [PATCH 008/298] Fix is_truncated in basic_string (#1223) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Iványi Béla --- include/etl/basic_string.h | 8 ++++---- test/test_make_string.cpp | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/etl/basic_string.h b/include/etl/basic_string.h index 4d8157cf..c1775bc7 100644 --- a/include/etl/basic_string.h +++ b/include/etl/basic_string.h @@ -770,7 +770,7 @@ namespace etl set_truncated(n > CAPACITY); #if ETL_HAS_ERROR_ON_STRING_TRUNCATION - ETL_ASSERT(is_truncated == false, ETL_ERROR(string_truncation)); + ETL_ASSERT(is_truncated() == false, ETL_ERROR(string_truncation)); #endif #endif @@ -918,7 +918,7 @@ namespace etl set_truncated(n > free_space); #if ETL_HAS_ERROR_ON_STRING_TRUNCATION - ETL_ASSERT(is_truncated == false, ETL_ERROR(string_truncation)); + ETL_ASSERT(is_truncated() == false, ETL_ERROR(string_truncation)); #endif #endif @@ -2774,7 +2774,7 @@ namespace etl set_truncated((count > free_space) || this->is_truncated() || truncated); #if ETL_HAS_ERROR_ON_STRING_TRUNCATION - ETL_ASSERT(is_truncated == false, ETL_ERROR(string_truncation)); + ETL_ASSERT(is_truncated() == false, ETL_ERROR(string_truncation)); #endif #endif @@ -2820,7 +2820,7 @@ namespace etl #if ETL_HAS_STRING_TRUNCATION_CHECKS set_truncated(truncated); #if ETL_HAS_ERROR_ON_STRING_TRUNCATION - ETL_ASSERT(is_truncated == false, ETL_ERROR(string_truncation)); + ETL_ASSERT(is_truncated() == false, ETL_ERROR(string_truncation)); #endif #endif diff --git a/test/test_make_string.cpp b/test/test_make_string.cpp index 69468593..f24b95d9 100644 --- a/test/test_make_string.cpp +++ b/test/test_make_string.cpp @@ -141,7 +141,6 @@ namespace TEST_FIXTURE(SetupFixture, test_make_string_with_capacity_truncated) { constexpr size_t CAPACITY = 10UL; - size_t length = strlen("Hello World"); #if ETL_HAS_ERROR_ON_STRING_TRUNCATION CHECK_THROW(auto ctext = etl::make_string_with_capacity("Hello World"), etl::string_truncation); @@ -149,6 +148,8 @@ namespace CHECK_THROW(auto u16text = etl::make_string_with_capacity(u"Hello World"), etl::string_truncation);; CHECK_THROW(auto u32text = etl::make_string_with_capacity(U"Hello World"), etl::string_truncation);; #else + size_t length = strlen("Hello World"); + auto ctext = etl::make_string_with_capacity("Hello World"); auto wtext = etl::make_string_with_capacity(L"Hello World"); auto u16text = etl::make_string_with_capacity(u"Hello World"); From 81a643b9b53c20ee8626f27e06aa24a0ec434cae Mon Sep 17 00:00:00 2001 From: mike919192 <91038685+mike919192@users.noreply.github.com> Date: Sat, 29 Nov 2025 04:41:54 -0500 Subject: [PATCH 009/298] Bugfix: Fixed span reinterpret_as should return fixed span (#1210) * Fixed span reinterpret should also return fixed span * Use auto instead of CTAD --- include/etl/span.h | 4 ++-- test/test_span_fixed_extent.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/etl/span.h b/include/etl/span.h index e314029c..1e8d5be2 100644 --- a/include/etl/span.h +++ b/include/etl/span.h @@ -561,11 +561,11 @@ namespace etl /// Reinterpret the span as a span with different element type. //************************************************************************* template - ETL_NODISCARD ETL_CONSTEXPR14 etl::span reinterpret_as() const + ETL_NODISCARD ETL_CONSTEXPR14 etl::span reinterpret_as() const { ETL_ASSERT(etl::is_aligned::value>(pbegin), ETL_ERROR(span_alignment_exception)); - return etl::span(reinterpret_cast(pbegin), + return etl::span(reinterpret_cast(pbegin), Extent * sizeof(element_type) / sizeof(TNew)); } diff --git a/test/test_span_fixed_extent.cpp b/test/test_span_fixed_extent.cpp index 83c5f498..d2c7e2f3 100644 --- a/test/test_span_fixed_extent.cpp +++ b/test/test_span_fixed_extent.cpp @@ -1223,7 +1223,7 @@ namespace uint8_t data[] = { 0x01, 0x02, 0x03, 0x04, 0x05 }; etl::span data0 = data; - etl::span data1 = data0.reinterpret_as(); + auto data1 = data0.reinterpret_as(); CHECK_EQUAL(data1.size(), 2); CHECK(data1[0] == 0x102); @@ -1237,13 +1237,13 @@ namespace etl::span data0 = data; CHECK_EQUAL(data0.size(), 3); - etl::span data1 = data0.reinterpret_as(); + auto data1 = data0.reinterpret_as(); CHECK_EQUAL(data1.size(), 12); - etl::span data2 = data1.subspan(2).reinterpret_as(); + auto data2 = data1.subspan<2>().reinterpret_as(); CHECK_EQUAL(data2.size(), 5); - CHECK_THROW(data2 = data1.subspan(1).reinterpret_as(), etl::span_alignment_exception); + CHECK_THROW(data2 = data1.subspan<1>().reinterpret_as(), etl::span_alignment_exception); } //************************************************************************* From 79afa52c1e5245cdf2989a4859acb7c999c273e3 Mon Sep 17 00:00:00 2001 From: David Ockey <2897027+ockeydockey@users.noreply.github.com> Date: Sat, 29 Nov 2025 03:54:17 -0600 Subject: [PATCH 010/298] Catch reentrant calls to FSM and HFSM start, receive, etc. (#1202) * Added mechanism to catch reentrant calls to methods that could change states in FSM/HFSM * Added missing include for HFSM unit tests * Fixed error text spacing * Disabled move/copy semantics for reentrancy guard * Updated FSM generator * Made move semantics only available for C++11 and higher --------- Co-authored-by: John Wellbelove --- include/etl/fsm.h | 66 +++++++++++++++++++++++++- include/etl/generators/fsm_generator.h | 64 +++++++++++++++++++++++++ include/etl/hfsm.h | 4 ++ test/test_hfsm_transition_on_enter.cpp | 20 ++++++++ 4 files changed, 153 insertions(+), 1 deletion(-) diff --git a/include/etl/fsm.h b/include/etl/fsm.h index 6382884a..4eaa016a 100644 --- a/include/etl/fsm.h +++ b/include/etl/fsm.h @@ -172,6 +172,19 @@ namespace etl } }; + //*************************************************************************** + /// Exception for call to receive/start/etc. while receive/start/etc. is already happening. + /// A call like that could result in an infinite loop or landing in an incorrect state. + //*************************************************************************** + class fsm_reentrant_transition_forbidden : public etl::fsm_exception + { + public: + fsm_reentrant_transition_forbidden(string_type file_name_, numeric_type line_number_) + : etl::fsm_exception(ETL_ERROR_TEXT("fsm:reentrant calls to start/receive/etc. forbidden", ETL_FSM_FILE_ID"G"), file_name_, line_number_) + { + } + }; + namespace private_fsm { template @@ -208,7 +221,48 @@ namespace etl struct check_ids : etl::integral_constant::value> { - }; + }; + + //*************************************************************************** + /// RAII detection mechanism to catch reentrant calls to methods that might + /// transition the state machine to a different state. + /// This is not a mutex. + //*************************************************************************** + class fsm_reentrancy_guard + { + public: + //******************************************* + /// Constructor. + /// Checks if another method has locked reentrancy. + //******************************************* + fsm_reentrancy_guard(bool& transition_guard_flag) + : is_locked(transition_guard_flag) + { + ETL_ASSERT(!is_locked, ETL_ERROR(etl::fsm_reentrant_transition_forbidden)); + is_locked = true; + } + + //******************************************* + /// Destructor. + /// Releases lock on reentrancy. + //******************************************* + ~fsm_reentrancy_guard() ETL_NOEXCEPT + { + is_locked = false; + } + + private: + // Reference to the flag signifying a lock on the state machine. + bool& is_locked; + + // Copy & move semantics disabled since this is a guard. + fsm_reentrancy_guard(fsm_reentrancy_guard const&) ETL_DELETE; + fsm_reentrancy_guard& operator= (fsm_reentrancy_guard const&) ETL_DELETE; +#if ETL_USING_CPP11 + fsm_reentrancy_guard(fsm_reentrancy_guard&&) ETL_DELETE; + fsm_reentrancy_guard& operator= (fsm_reentrancy_guard&&) ETL_DELETE; +#endif + }; } class ifsm_state; @@ -417,6 +471,7 @@ namespace etl , p_state(ETL_NULLPTR) , state_list(ETL_NULLPTR) , number_of_states(0U) + , is_processing_state_change(false) { } @@ -467,6 +522,8 @@ namespace etl //******************************************* virtual void start(bool call_on_enter_state = true) { + private_fsm::fsm_reentrancy_guard transition_lock(is_processing_state_change); + // Can only be started once. if (!is_started()) { @@ -497,6 +554,8 @@ namespace etl //******************************************* void receive(const etl::imessage& message) ETL_OVERRIDE { + private_fsm::fsm_reentrancy_guard transition_lock(is_processing_state_change); + if (is_started()) { etl::fsm_state_id_t next_state_id = p_state->process_event(message); @@ -514,6 +573,8 @@ namespace etl //******************************************* etl::fsm_state_id_t transition_to(etl::fsm_state_id_t new_state_id) { + private_fsm::fsm_reentrancy_guard transition_lock(is_processing_state_change); + if (is_started()) { return process_state_change(new_state_id); @@ -576,6 +637,8 @@ namespace etl //******************************************* virtual void reset(bool call_on_exit_state = false) { + private_fsm::fsm_reentrancy_guard transition_lock(is_processing_state_change); + if (is_started() && call_on_exit_state) { p_state->on_exit_state(); @@ -655,6 +718,7 @@ namespace etl etl::ifsm_state* p_state; ///< A pointer to the current state. etl::ifsm_state** state_list; ///< The list of added states. etl::fsm_state_id_t number_of_states; ///< The number of states. + bool is_processing_state_change; ///< Whether a method call that could potentially trigger a state change is active }; //************************************************************************************************* diff --git a/include/etl/generators/fsm_generator.h b/include/etl/generators/fsm_generator.h index 36ba80bb..0887af6c 100644 --- a/include/etl/generators/fsm_generator.h +++ b/include/etl/generators/fsm_generator.h @@ -191,6 +191,19 @@ namespace etl } }; + //*************************************************************************** + /// Exception for call to receive/start/etc. while receive/start/etc. is already happening. + /// A call like that could result in an infinite loop or landing in an incorrect state. + //*************************************************************************** + class fsm_reentrant_transition_forbidden : public etl::fsm_exception + { + public: + fsm_reentrant_transition_forbidden(string_type file_name_, numeric_type line_number_) + : etl::fsm_exception(ETL_ERROR_TEXT("fsm:reentrant calls to start/receive/etc. forbidden", ETL_FSM_FILE_ID"G"), file_name_, line_number_) + { + } + }; + namespace private_fsm { template @@ -228,6 +241,47 @@ namespace etl : etl::integral_constant::value> { }; + + //*************************************************************************** + /// RAII detection mechanism to catch reentrant calls to methods that might + /// transition the state machine to a different state. + /// This is not a mutex. + //*************************************************************************** + class fsm_reentrancy_guard + { + public: + //******************************************* + /// Constructor. + /// Checks if another method has locked reentrancy. + //******************************************* + fsm_reentrancy_guard(bool& transition_guard_flag) + : is_locked(transition_guard_flag) + { + ETL_ASSERT(!is_locked, ETL_ERROR(etl::fsm_reentrant_transition_forbidden)); + is_locked = true; + } + + //******************************************* + /// Destructor. + /// Releases lock on reentrancy. + //******************************************* + ~fsm_reentrancy_guard() ETL_NOEXCEPT + { + is_locked = false; + } + + private: + // Reference to the flag signifying a lock on the state machine. + bool& is_locked; + + // Copy & move semantics disabled since this is a guard. + fsm_reentrancy_guard(fsm_reentrancy_guard const&) ETL_DELETE; + fsm_reentrancy_guard& operator= (fsm_reentrancy_guard const&) ETL_DELETE; +#if ETL_USING_CPP11 + fsm_reentrancy_guard(fsm_reentrancy_guard&&) ETL_DELETE; + fsm_reentrancy_guard& operator= (fsm_reentrancy_guard&&) ETL_DELETE; +#endif + }; } class ifsm_state; @@ -443,6 +497,7 @@ namespace etl , p_state(ETL_NULLPTR) , state_list(ETL_NULLPTR) , number_of_states(0U) + , is_processing_state_change(false) { } @@ -493,6 +548,8 @@ namespace etl //******************************************* virtual void start(bool call_on_enter_state = true) { + private_fsm::fsm_reentrancy_guard transition_lock(is_processing_state_change); + // Can only be started once. if (!is_started()) { @@ -523,6 +580,8 @@ namespace etl //******************************************* void receive(const etl::imessage& message) ETL_OVERRIDE { + private_fsm::fsm_reentrancy_guard transition_lock(is_processing_state_change); + if (is_started()) { etl::fsm_state_id_t next_state_id = p_state->process_event(message); @@ -540,6 +599,8 @@ namespace etl //******************************************* etl::fsm_state_id_t transition_to(etl::fsm_state_id_t new_state_id) { + private_fsm::fsm_reentrancy_guard transition_lock(is_processing_state_change); + if (is_started()) { return process_state_change(new_state_id); @@ -602,6 +663,8 @@ namespace etl //******************************************* virtual void reset(bool call_on_exit_state = false) { + private_fsm::fsm_reentrancy_guard transition_lock(is_processing_state_change); + if (is_started() && call_on_exit_state) { p_state->on_exit_state(); @@ -681,6 +744,7 @@ namespace etl etl::ifsm_state* p_state; ///< A pointer to the current state. etl::ifsm_state** state_list; ///< The list of added states. etl::fsm_state_id_t number_of_states; ///< The number of states. + bool is_processing_state_change; ///< Whether a method call that could potentially trigger a state change is active }; //************************************************************************************************* diff --git a/include/etl/hfsm.h b/include/etl/hfsm.h index c3f2062c..6db390f0 100644 --- a/include/etl/hfsm.h +++ b/include/etl/hfsm.h @@ -59,6 +59,8 @@ namespace etl //******************************************* void start(bool call_on_enter_state = true) ETL_OVERRIDE { + private_fsm::fsm_reentrancy_guard transition_lock(is_processing_state_change); + // Can only be started once. if (!is_started()) { @@ -98,6 +100,8 @@ namespace etl //******************************************* virtual void reset(bool call_on_exit_state = false) ETL_OVERRIDE { + private_fsm::fsm_reentrancy_guard transition_lock(is_processing_state_change); + if (is_started() && call_on_exit_state) { do_exits(ETL_NULLPTR, p_state); diff --git a/test/test_hfsm_transition_on_enter.cpp b/test/test_hfsm_transition_on_enter.cpp index ff994c10..a83c3d1a 100644 --- a/test/test_hfsm_transition_on_enter.cpp +++ b/test/test_hfsm_transition_on_enter.cpp @@ -31,6 +31,7 @@ SOFTWARE. #include "etl/hfsm.h" #include "etl/string.h" #include +#include // entry && mode=RxEventDeviation // ┌─────────────────────────────────────────────────────┐ @@ -358,6 +359,25 @@ namespace sm.reset(true); CHECK_EQUAL("X1X2X3", sm.test_data.c_str()); } + + //************************************************************************* + TEST(reentrant_receives) + { + EntryTestSM sm; + sm.start(false); + sm.receive(ToS5Event{}); + sm.test_data.clear(); + sm.runMode = EntryTestSM::RxEventDuringTransition; + CHECK_THROW(sm.receive(ToS6Event{}),etl::fsm_reentrant_transition_forbidden); + } + + //************************************************************************* + TEST(reentrant_receives_on_start) + { + EntryTestSM sm; + sm.runMode = EntryTestSM::RxEventDuringTransition; + CHECK_THROW(sm.start(true),etl::fsm_reentrant_transition_forbidden); + } } } // namespace From cb25fdfff5fd581af698f04587e883ea646552a5 Mon Sep 17 00:00:00 2001 From: mike919192 <91038685+mike919192@users.noreply.github.com> Date: Sat, 29 Nov 2025 04:41:54 -0500 Subject: [PATCH 011/298] Bugfix: Fixed span reinterpret_as should return fixed span (#1210) * Fixed span reinterpret should also return fixed span * Use auto instead of CTAD --- include/etl/span.h | 4 ++-- test/test_span_fixed_extent.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/etl/span.h b/include/etl/span.h index e314029c..1e8d5be2 100644 --- a/include/etl/span.h +++ b/include/etl/span.h @@ -561,11 +561,11 @@ namespace etl /// Reinterpret the span as a span with different element type. //************************************************************************* template - ETL_NODISCARD ETL_CONSTEXPR14 etl::span reinterpret_as() const + ETL_NODISCARD ETL_CONSTEXPR14 etl::span reinterpret_as() const { ETL_ASSERT(etl::is_aligned::value>(pbegin), ETL_ERROR(span_alignment_exception)); - return etl::span(reinterpret_cast(pbegin), + return etl::span(reinterpret_cast(pbegin), Extent * sizeof(element_type) / sizeof(TNew)); } diff --git a/test/test_span_fixed_extent.cpp b/test/test_span_fixed_extent.cpp index 83c5f498..d2c7e2f3 100644 --- a/test/test_span_fixed_extent.cpp +++ b/test/test_span_fixed_extent.cpp @@ -1223,7 +1223,7 @@ namespace uint8_t data[] = { 0x01, 0x02, 0x03, 0x04, 0x05 }; etl::span data0 = data; - etl::span data1 = data0.reinterpret_as(); + auto data1 = data0.reinterpret_as(); CHECK_EQUAL(data1.size(), 2); CHECK(data1[0] == 0x102); @@ -1237,13 +1237,13 @@ namespace etl::span data0 = data; CHECK_EQUAL(data0.size(), 3); - etl::span data1 = data0.reinterpret_as(); + auto data1 = data0.reinterpret_as(); CHECK_EQUAL(data1.size(), 12); - etl::span data2 = data1.subspan(2).reinterpret_as(); + auto data2 = data1.subspan<2>().reinterpret_as(); CHECK_EQUAL(data2.size(), 5); - CHECK_THROW(data2 = data1.subspan(1).reinterpret_as(), etl::span_alignment_exception); + CHECK_THROW(data2 = data1.subspan<1>().reinterpret_as(), etl::span_alignment_exception); } //************************************************************************* From ee820f07424b46a44525b792f543b2e5adbc581a Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 29 Nov 2025 09:29:12 +0000 Subject: [PATCH 012/298] #1228u nused parameter 'secure' Also fixed for 'truncated' --- include/etl/basic_string.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/etl/basic_string.h b/include/etl/basic_string.h index c1775bc7..9a39b078 100644 --- a/include/etl/basic_string.h +++ b/include/etl/basic_string.h @@ -2776,6 +2776,8 @@ namespace etl #if ETL_HAS_ERROR_ON_STRING_TRUNCATION ETL_ASSERT(is_truncated() == false, ETL_ERROR(string_truncation)); #endif +#else + (void)truncated; #endif #if ETL_HAS_STRING_CLEAR_AFTER_USE @@ -2783,6 +2785,8 @@ namespace etl { set_secure(); } +#else + (void)secure; #endif // Limit the actual distance to the capacity. @@ -2822,6 +2826,8 @@ namespace etl #if ETL_HAS_ERROR_ON_STRING_TRUNCATION ETL_ASSERT(is_truncated() == false, ETL_ERROR(string_truncation)); #endif +#else + (void)truncated; #endif #if ETL_HAS_STRING_CLEAR_AFTER_USE @@ -2829,6 +2835,8 @@ namespace etl { set_secure(); } +#else + (void)secure; #endif cleanup(); From ea73cde70b012ac31ce6b90e2253ad3d6cf1d089 Mon Sep 17 00:00:00 2001 From: raitraak-rrk Date: Tue, 2 Dec 2025 21:34:06 +1100 Subject: [PATCH 013/298] variant_legacy.h: Rename template parameters (#1229) * Bugfix: Fixed span reinterpret_as should return fixed span (#1210) * Fixed span reinterpret should also return fixed span * Use auto instead of CTAD * variant_legacy.h: Rename template parameters * Allows compatibility with legacy libraries defining U8 similar to uint8_t (e.g. Segger). --------- Co-authored-by: mike919192 <91038685+mike919192@users.noreply.github.com> --- include/etl/private/variant_legacy.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/include/etl/private/variant_legacy.h b/include/etl/private/variant_legacy.h index c32044af..a53e3602 100644 --- a/include/etl/private/variant_legacy.h +++ b/include/etl/private/variant_legacy.h @@ -159,7 +159,7 @@ namespace etl private: // All types of variant are friends. - template + template friend class variant; //*************************************************************************** @@ -668,21 +668,21 @@ namespace etl /// For variants with differing declarations. ///\return true if the types are the same, otherwise false. //*************************************************************************** - template - bool is_same_type(const variant& other) const + template + bool is_same_type(const variant& other) const { bool is_same = false; switch (other.type_id) { - case 0: is_same = (type_id == Type_Id_Lookup::type_id); break; - case 1: is_same = (type_id == Type_Id_Lookup::type_id); break; - case 2: is_same = (type_id == Type_Id_Lookup::type_id); break; - case 3: is_same = (type_id == Type_Id_Lookup::type_id); break; - case 4: is_same = (type_id == Type_Id_Lookup::type_id); break; - case 5: is_same = (type_id == Type_Id_Lookup::type_id); break; - case 6: is_same = (type_id == Type_Id_Lookup::type_id); break; - case 7: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 0: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 1: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 2: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 3: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 4: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 5: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 6: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 7: is_same = (type_id == Type_Id_Lookup::type_id); break; default: break; } From 34abed35b062a63c24f86e9c536203b69fbc2241 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 2 Dec 2025 17:13:10 +0000 Subject: [PATCH 014/298] Synchronised generators with source files --- include/etl/fsm.h | 2 +- .../etl/generators/type_traits_generator.h | 274 +++++++++++++++++- include/etl/type_traits.h | 274 +++++++++++++++++- test/vs2022/etl.vcxproj | 54 ++-- 4 files changed, 573 insertions(+), 31 deletions(-) diff --git a/include/etl/fsm.h b/include/etl/fsm.h index 4eaa016a..36130a47 100644 --- a/include/etl/fsm.h +++ b/include/etl/fsm.h @@ -221,7 +221,7 @@ namespace etl struct check_ids : etl::integral_constant::value> { - }; + }; //*************************************************************************** /// RAII detection mechanism to catch reentrant calls to methods that might diff --git a/include/etl/generators/type_traits_generator.h b/include/etl/generators/type_traits_generator.h index a03242a9..8d4753e6 100644 --- a/include/etl/generators/type_traits_generator.h +++ b/include/etl/generators/type_traits_generator.h @@ -800,6 +800,7 @@ namespace etl //*************************************************************************** /// is_convertible + ///\ingroup type_traits #if ETL_USING_CPP11 namespace private_type_traits { @@ -828,11 +829,34 @@ namespace etl decltype(private_type_traits::nonvoid_convertible(0))::value) || (etl::is_void::value && etl::is_void::value)> {}; #endif + + // Is convertible and the conversion is noexcept. + template + struct is_nothrow_convertible + { + private: + // Helper: a function taking TTo to require the conversion. + static void sink(TTo) noexcept; + + // Selected only if 'sink(declval())' is a valid expression. + template + static auto test(int) -> etl::bool_constant()))>; + + // Fallback if conversion is not viable. + template + static etl::false_type test(...); + + public: + static ETL_CONSTANT bool value = decltype(test(0))::value; + }; #endif #if ETL_USING_CPP17 template inline constexpr bool is_convertible_v = etl::is_convertible::value; + + template + inline constexpr bool is_nothrow_convertible_v = etl::is_nothrow_convertible::value; #endif //*************************************************************************** @@ -1353,11 +1377,34 @@ typedef integral_constant true_type; #if ETL_USING_CPP11 template struct is_convertible : std::is_convertible {}; + + // Is convertible and the conversion is noexcept. + template + struct is_nothrow_convertible + { + private: + // Helper: a function taking TTo to require the conversion. + static void sink(TTo) noexcept; + + // Selected only if 'sink(declval())' is a valid expression. + template + static auto test(int) -> etl::bool_constant()))>; + + // Fallback if conversion is not viable. + template + static etl::false_type test(...); + + public: + static ETL_CONSTANT bool value = decltype(test(0))::value; + }; #endif #if ETL_USING_CPP17 template inline constexpr bool is_convertible_v = std::is_convertible_v; + + template + inline constexpr bool is_nothrow_convertible_v = is_nothrow_convertible::value; #endif //*************************************************************************** @@ -2124,17 +2171,17 @@ typedef integral_constant true_type; /// is_constructible namespace private_type_traits { - template + template struct is_constructible_ : etl::false_type {}; - template - struct is_constructible_()...))>, T, Args...> : etl::true_type {}; + template + struct is_constructible_()...))>, T, TArgs...> : etl::true_type {}; } //********************************************* // is_constructible - template - using is_constructible = private_type_traits::is_constructible_, T, Args...>; + template + using is_constructible = private_type_traits::is_constructible_, T, TArgs...>; //********************************************* // is_copy_constructible @@ -2504,13 +2551,228 @@ typedef integral_constant true_type; return false; } #elif ETL_USING_BUILTIN_IS_CONSTANT_EVALUATED == 1 - // fallback for C++20 on supported compilers + // Fallback for C++20 on supported compilers return __builtin_is_constant_evaluated(); #else // default if unsupported return false; #endif } + +#if ETL_USING_CPP11 + //********************************* + /// Check if T is a function type + //********************************* + template + struct is_function : etl::false_type + { + }; + + // Plain / cv-qualified + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + + // Variadic + template + struct is_function : etl::true_type {}; + + // noexcept variants (if supported by the toolchain) +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; +#endif + +#if ETL_USING_CPP17 + template + inline constexpr bool is_function_v = etl::is_function::value; +#endif +#endif + +#if ETL_USING_CPP11 + //********************************* + /// Check for the presence of operator() + //********************************* + template >::value, int> = 0> + struct has_call_operator + { + template + static auto test(int) -> decltype(&U::operator(), etl::true_type()); + + template + static etl::false_type test(...); + + static const bool value = etl::is_same(0)), etl::true_type>::value; + }; + +#if ETL_USING_CPP17 + template + inline constexpr bool has_call_operator_v = etl::has_call_operator::value; +#endif +#endif + +#if ETL_USING_CPP11 + //*************************************************************************** + /// Check that there is only one operator() + //*************************************************************************** + template >::value, int> = 0> + struct has_unique_call_operator + { + //********************************* + // Test for presence of operator() + //********************************* + template + static auto test(int) -> decltype(&U::operator(), etl::true_type()); + + //********************************* + // Fallback + //********************************* + template + static auto test(...) -> etl::false_type; + + //********************************* + // true if operator() exists and is unique + //********************************* + static const bool value = decltype(test>(0))::value; + }; + +#if ETL_USING_CPP17 + template + inline constexpr bool has_unique_call_operator_v = etl::has_unique_call_operator::value; +#endif +#endif + + //*************************************************************************** + /// Is T a member pointer + //*************************************************************************** + namespace private_type_traits + { + template + struct is_member_pointer_helper : etl::false_type {}; + + template + struct is_member_pointer_helper : etl::true_type {}; + } + + template + struct is_member_pointer : private_type_traits::is_member_pointer_helper> {}; + +#if ETL_USING_CPP17 + template + inline constexpr bool is_member_pointer_v = etl::is_member_pointer::value; +#endif + + //*************************************************************************** + /// Is T a member function pointer + //*************************************************************************** + template struct is_member_function_pointer : etl::false_type {}; + + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; +#endif + + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer: etl::true_type {}; + +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer: etl::true_type {}; +#endif + + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; +#endif + + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer: etl::true_type {}; + +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer: etl::true_type {}; +#endif + +#if ETL_USING_CPP17 + template + inline constexpr bool is_member_function_pointer_v = etl::is_member_function_pointer::value; +#endif + + //*************************************************************************** + /// Is T a member object pointer + //*************************************************************************** + namespace private_type_traits + { + template + struct logical_not_t : etl::integral_constant {}; + + template + struct is_member_object_pointer_helper : public etl::false_type {}; + + template + struct is_member_object_pointer_helper : public logical_not_t>::type {}; + } + + template struct is_member_object_pointer : public private_type_traits::is_member_object_pointer_helper>::type {}; + +#if ETL_USING_CPP17 + template + inline constexpr bool is_member_object_pointer_v = etl::is_member_object_pointer::value; +#endif } // Helper macros diff --git a/include/etl/type_traits.h b/include/etl/type_traits.h index 3c9ac66b..44dccad6 100644 --- a/include/etl/type_traits.h +++ b/include/etl/type_traits.h @@ -788,6 +788,7 @@ namespace etl //*************************************************************************** /// is_convertible + ///\ingroup type_traits #if ETL_USING_CPP11 namespace private_type_traits { @@ -816,11 +817,34 @@ namespace etl decltype(private_type_traits::nonvoid_convertible(0))::value) || (etl::is_void::value && etl::is_void::value)> {}; #endif + + // Is convertible and the conversion is noexcept. + template + struct is_nothrow_convertible + { + private: + // Helper: a function taking TTo to require the conversion. + static void sink(TTo) noexcept; + + // Selected only if 'sink(declval())' is a valid expression. + template + static auto test(int) -> etl::bool_constant()))>; + + // Fallback if conversion is not viable. + template + static etl::false_type test(...); + + public: + static ETL_CONSTANT bool value = decltype(test(0))::value; + }; #endif #if ETL_USING_CPP17 template inline constexpr bool is_convertible_v = etl::is_convertible::value; + + template + inline constexpr bool is_nothrow_convertible_v = etl::is_nothrow_convertible::value; #endif //*************************************************************************** @@ -1341,11 +1365,34 @@ typedef integral_constant true_type; #if ETL_USING_CPP11 template struct is_convertible : std::is_convertible {}; + + // Is convertible and the conversion is noexcept. + template + struct is_nothrow_convertible + { + private: + // Helper: a function taking TTo to require the conversion. + static void sink(TTo) noexcept; + + // Selected only if 'sink(declval())' is a valid expression. + template + static auto test(int) -> etl::bool_constant()))>; + + // Fallback if conversion is not viable. + template + static etl::false_type test(...); + + public: + static ETL_CONSTANT bool value = decltype(test(0))::value; + }; #endif #if ETL_USING_CPP17 template inline constexpr bool is_convertible_v = std::is_convertible_v; + + template + inline constexpr bool is_nothrow_convertible_v = is_nothrow_convertible::value; #endif //*************************************************************************** @@ -2117,17 +2164,17 @@ typedef integral_constant true_type; /// is_constructible namespace private_type_traits { - template + template struct is_constructible_ : etl::false_type {}; - template - struct is_constructible_()...))>, T, Args...> : etl::true_type {}; + template + struct is_constructible_()...))>, T, TArgs...> : etl::true_type {}; } //********************************************* // is_constructible - template - using is_constructible = private_type_traits::is_constructible_, T, Args...>; + template + using is_constructible = private_type_traits::is_constructible_, T, TArgs...>; //********************************************* // is_copy_constructible @@ -2497,13 +2544,228 @@ typedef integral_constant true_type; return false; } #elif ETL_USING_BUILTIN_IS_CONSTANT_EVALUATED == 1 - // fallback for C++20 on supported compilers + // Fallback for C++20 on supported compilers return __builtin_is_constant_evaluated(); #else // default if unsupported return false; #endif } + +#if ETL_USING_CPP11 + //********************************* + /// Check if T is a function type + //********************************* + template + struct is_function : etl::false_type + { + }; + + // Plain / cv-qualified + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + + // Variadic + template + struct is_function : etl::true_type {}; + + // noexcept variants (if supported by the toolchain) +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; +#endif + +#if ETL_USING_CPP17 + template + inline constexpr bool is_function_v = etl::is_function::value; +#endif +#endif + +#if ETL_USING_CPP11 + //********************************* + /// Check for the presence of operator() + //********************************* + template >::value, int> = 0> + struct has_call_operator + { + template + static auto test(int) -> decltype(&U::operator(), etl::true_type()); + + template + static etl::false_type test(...); + + static const bool value = etl::is_same(0)), etl::true_type>::value; + }; + +#if ETL_USING_CPP17 + template + inline constexpr bool has_call_operator_v = etl::has_call_operator::value; +#endif +#endif + +#if ETL_USING_CPP11 + //*************************************************************************** + /// Check that there is only one operator() + //*************************************************************************** + template >::value, int> = 0> + struct has_unique_call_operator + { + //********************************* + // Test for presence of operator() + //********************************* + template + static auto test(int) -> decltype(&U::operator(), etl::true_type()); + + //********************************* + // Fallback + //********************************* + template + static auto test(...) -> etl::false_type; + + //********************************* + // true if operator() exists and is unique + //********************************* + static const bool value = decltype(test>(0))::value; + }; + +#if ETL_USING_CPP17 + template + inline constexpr bool has_unique_call_operator_v = etl::has_unique_call_operator::value; +#endif +#endif + + //*************************************************************************** + /// Is T a member pointer + //*************************************************************************** + namespace private_type_traits + { + template + struct is_member_pointer_helper : etl::false_type {}; + + template + struct is_member_pointer_helper : etl::true_type {}; + } + + template + struct is_member_pointer : private_type_traits::is_member_pointer_helper> {}; + +#if ETL_USING_CPP17 + template + inline constexpr bool is_member_pointer_v = etl::is_member_pointer::value; +#endif + + //*************************************************************************** + /// Is T a member function pointer + //*************************************************************************** + template struct is_member_function_pointer : etl::false_type {}; + + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; +#endif + + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer: etl::true_type {}; + +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer: etl::true_type {}; +#endif + + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; +#endif + + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer: etl::true_type {}; + +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer: etl::true_type {}; +#endif + +#if ETL_USING_CPP17 + template + inline constexpr bool is_member_function_pointer_v = etl::is_member_function_pointer::value; +#endif + + //*************************************************************************** + /// Is T a member object pointer + //*************************************************************************** + namespace private_type_traits + { + template + struct logical_not_t : etl::integral_constant {}; + + template + struct is_member_object_pointer_helper : public etl::false_type {}; + + template + struct is_member_object_pointer_helper : public logical_not_t>::type {}; + } + + template struct is_member_object_pointer : public private_type_traits::is_member_object_pointer_helper>::type {}; + +#if ETL_USING_CPP17 + template + inline constexpr bool is_member_object_pointer_v = etl::is_member_object_pointer::value; +#endif } // Helper macros diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index d2b13bec..095d407d 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -1003,87 +1003,104 @@ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ false @@ -1129,7 +1146,8 @@ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ false From 3c64940e909762ab38fbf953f61dba6651613fc7 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 3 Dec 2025 09:07:27 +0000 Subject: [PATCH 015/298] Fixed C++03 compatibility Updated type_traits generator --- .../etl/generators/type_traits_generator.h | 128 ++++++------------ include/etl/type_traits.h | 128 ++++++------------ 2 files changed, 84 insertions(+), 172 deletions(-) diff --git a/include/etl/generators/type_traits_generator.h b/include/etl/generators/type_traits_generator.h index 8d4753e6..9fd77c64 100644 --- a/include/etl/generators/type_traits_generator.h +++ b/include/etl/generators/type_traits_generator.h @@ -2569,31 +2569,31 @@ typedef integral_constant true_type; }; // Plain / cv-qualified - template - struct is_function : etl::true_type {}; - template - struct is_function : etl::true_type {}; - template - struct is_function : etl::true_type {}; - template - struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; // Variadic - template - struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; // noexcept variants (if supported by the toolchain) #if ETL_HAS_NOEXCEPT_FUNCTION_TYPE - template - struct is_function : etl::true_type {}; - template - struct is_function : etl::true_type {}; - template - struct is_function : etl::true_type {}; - template - struct is_function : etl::true_type {}; - template - struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; #endif #if ETL_USING_CPP17 @@ -2668,83 +2668,37 @@ typedef integral_constant true_type; } template - struct is_member_pointer : private_type_traits::is_member_pointer_helper> {}; + struct is_member_pointer : private_type_traits::is_member_pointer_helper::type> {}; #if ETL_USING_CPP17 template inline constexpr bool is_member_pointer_v = etl::is_member_pointer::value; #endif +#if ETL_USING_CPP11 //*************************************************************************** /// Is T a member function pointer //*************************************************************************** - template struct is_member_function_pointer : etl::false_type {}; + namespace private_type_traits + { + // Primary: not a member function pointer. + template + struct is_member_function_pointer_helper : etl::false_type + { + }; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; + // If the type is 'TMember TObject::*' then TMember is the member + // Uses etl::is_function to detect member function pointers. + template + struct is_member_function_pointer_helper : etl::is_function + { + }; + } -#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; -#endif - - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer: etl::true_type {}; - -#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer: etl::true_type {}; -#endif - - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - -#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; -#endif - - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer: etl::true_type {}; - -#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer: etl::true_type {}; + template + struct is_member_function_pointer : private_type_traits::is_member_function_pointer_helper> + { + }; #endif #if ETL_USING_CPP17 @@ -2752,6 +2706,7 @@ typedef integral_constant true_type; inline constexpr bool is_member_function_pointer_v = etl::is_member_function_pointer::value; #endif +#if ETL_USING_CPP11 //*************************************************************************** /// Is T a member object pointer //*************************************************************************** @@ -2768,6 +2723,7 @@ typedef integral_constant true_type; } template struct is_member_object_pointer : public private_type_traits::is_member_object_pointer_helper>::type {}; +#endif #if ETL_USING_CPP17 template diff --git a/include/etl/type_traits.h b/include/etl/type_traits.h index 44dccad6..0d32608e 100644 --- a/include/etl/type_traits.h +++ b/include/etl/type_traits.h @@ -2562,31 +2562,31 @@ typedef integral_constant true_type; }; // Plain / cv-qualified - template - struct is_function : etl::true_type {}; - template - struct is_function : etl::true_type {}; - template - struct is_function : etl::true_type {}; - template - struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; // Variadic - template - struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; // noexcept variants (if supported by the toolchain) #if ETL_HAS_NOEXCEPT_FUNCTION_TYPE - template - struct is_function : etl::true_type {}; - template - struct is_function : etl::true_type {}; - template - struct is_function : etl::true_type {}; - template - struct is_function : etl::true_type {}; - template - struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; #endif #if ETL_USING_CPP17 @@ -2661,83 +2661,37 @@ typedef integral_constant true_type; } template - struct is_member_pointer : private_type_traits::is_member_pointer_helper> {}; + struct is_member_pointer : private_type_traits::is_member_pointer_helper::type> {}; #if ETL_USING_CPP17 template inline constexpr bool is_member_pointer_v = etl::is_member_pointer::value; #endif +#if ETL_USING_CPP11 //*************************************************************************** /// Is T a member function pointer //*************************************************************************** - template struct is_member_function_pointer : etl::false_type {}; + namespace private_type_traits + { + // Primary: not a member function pointer. + template + struct is_member_function_pointer_helper : etl::false_type + { + }; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; + // If the type is 'TMember TObject::*' then TMember is the member + // Uses etl::is_function to detect member function pointers. + template + struct is_member_function_pointer_helper : etl::is_function + { + }; + } -#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; -#endif - - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer: etl::true_type {}; - -#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer: etl::true_type {}; -#endif - - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - -#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; -#endif - - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer: etl::true_type {}; - -#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer : etl::true_type {}; - template struct is_member_function_pointer: etl::true_type {}; + template + struct is_member_function_pointer : private_type_traits::is_member_function_pointer_helper> + { + }; #endif #if ETL_USING_CPP17 @@ -2745,6 +2699,7 @@ typedef integral_constant true_type; inline constexpr bool is_member_function_pointer_v = etl::is_member_function_pointer::value; #endif +#if ETL_USING_CPP11 //*************************************************************************** /// Is T a member object pointer //*************************************************************************** @@ -2761,6 +2716,7 @@ typedef integral_constant true_type; } template struct is_member_object_pointer : public private_type_traits::is_member_object_pointer_helper>::type {}; +#endif #if ETL_USING_CPP17 template From 7fd0360664637e4693b36d10f07c732dc3d46ef2 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 4 Dec 2025 07:47:39 +0000 Subject: [PATCH 016/298] Replaced locally defined logical_not_t with etl::negation --- include/etl/type_traits.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/include/etl/type_traits.h b/include/etl/type_traits.h index 0d32608e..76e6cae1 100644 --- a/include/etl/type_traits.h +++ b/include/etl/type_traits.h @@ -2705,14 +2705,11 @@ typedef integral_constant true_type; //*************************************************************************** namespace private_type_traits { - template - struct logical_not_t : etl::integral_constant {}; - template struct is_member_object_pointer_helper : public etl::false_type {}; template - struct is_member_object_pointer_helper : public logical_not_t>::type {}; + struct is_member_object_pointer_helper : public etl::negation> {}; } template struct is_member_object_pointer : public private_type_traits::is_member_object_pointer_helper>::type {}; From f5f76165ef6edb5569e5ee7476497cdb4c934e1d Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 4 Dec 2025 08:11:11 +0000 Subject: [PATCH 017/298] Replaced locally defined logical_not_t with etl::negation --- include/etl/type_traits.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/etl/type_traits.h b/include/etl/type_traits.h index 76e6cae1..bf285583 100644 --- a/include/etl/type_traits.h +++ b/include/etl/type_traits.h @@ -2639,7 +2639,7 @@ typedef integral_constant true_type; //********************************* // true if operator() exists and is unique //********************************* - static const bool value = decltype(test>(0))::value; + static constexpr bool value = decltype(test>(0))::value; }; #if ETL_USING_CPP17 From 1f15e86ebf16bc9ac97bf1e75fd5bd657faf8288 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 4 Dec 2025 08:11:50 +0000 Subject: [PATCH 018/298] Updated version and release notes --- arduino/library-arduino.json | 2 +- arduino/library-arduino.properties | 2 +- include/etl/version.h | 2 +- library.json | 2 +- library.properties | 2 +- support/Release notes.txt | 22 ++++++++++++++++++++++ version.txt | 2 +- 7 files changed, 28 insertions(+), 6 deletions(-) diff --git a/arduino/library-arduino.json b/arduino/library-arduino.json index 9288f7f6..1899443a 100644 --- a/arduino/library-arduino.json +++ b/arduino/library-arduino.json @@ -1,6 +1,6 @@ { "name": "Embedded Template Library ETL", - "version": "20.44.1", + "version": "20.44.2", "authors": { "name": "John Wellbelove", "email": "john.wellbelove@etlcpp.com" diff --git a/arduino/library-arduino.properties b/arduino/library-arduino.properties index 4dac09db..e4799f0e 100644 --- a/arduino/library-arduino.properties +++ b/arduino/library-arduino.properties @@ -1,5 +1,5 @@ name=Embedded Template Library ETL -version=20.44.1 +version=20.44.2 author= John Wellbelove maintainer=John Wellbelove license=MIT diff --git a/include/etl/version.h b/include/etl/version.h index 11790058..3309a7df 100644 --- a/include/etl/version.h +++ b/include/etl/version.h @@ -40,7 +40,7 @@ SOFTWARE. #define ETL_VERSION_MAJOR 20 #define ETL_VERSION_MINOR 44 -#define ETL_VERSION_PATCH 1 +#define ETL_VERSION_PATCH 2 #define ETL_VERSION ETL_STRING(ETL_VERSION_MAJOR) "." ETL_STRING(ETL_VERSION_MINOR) "." ETL_STRING(ETL_VERSION_PATCH) #define ETL_VERSION_W ETL_WIDE_STRING(ETL_VERSION_MAJOR) L"." ETL_WIDE_STRING(ETL_VERSION_MINOR) L"." ETL_WIDE_STRING(ETL_VERSION_PATCH) diff --git a/library.json b/library.json index 62519726..887a37f3 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "Embedded Template Library", - "version": "20.44.1", + "version": "20.44.2", "authors": { "name": "John Wellbelove", "email": "john.wellbelove@etlcpp.com" diff --git a/library.properties b/library.properties index f6e7bcd5..59a1888c 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library -version=20.44.1 +version=20.44.2 author= John Wellbelove maintainer=John Wellbelove license=MIT diff --git a/support/Release notes.txt b/support/Release notes.txt index 41731895..94f74931 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,4 +1,26 @@ =============================================================================== +20.44.2 + +Updates: +Replaced locally defined logical_not_t with etl::negation + +Fixes: +#1228 unused parameter 'secure' +#1224 Passing a const in optional::value_or() not compiling + +Pull Requests: +#1210 Fixed span reinterpret_as should return fixed span +#1211 Change generators to reflect changes in fsm.h and type_traits.h +#1217 Add const specialization for etl::get_object_at +#1218 Cleanup platform.h includes, add missing test for unaligned_type +#1221 Add test for swap +#1222 Basic string checks +#1223 Fix is_truncated in basic_string +#1225 Fix value_or not taking const in optional +#1226 Add missing include to optional +#1229 variant_legacy.h: Rename template parameters + +=============================================================================== 20.44.1 Updates: diff --git a/version.txt b/version.txt index 66252a79..3e132281 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -20.44.1 +20.44.2 From 1128414d21959f942f9df6f5ceb5ebf8bf6279ab Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 4 Dec 2025 08:15:24 +0000 Subject: [PATCH 019/298] Synced type_traits generator --- include/etl/generators/type_traits_generator.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/include/etl/generators/type_traits_generator.h b/include/etl/generators/type_traits_generator.h index 9fd77c64..c3a95f22 100644 --- a/include/etl/generators/type_traits_generator.h +++ b/include/etl/generators/type_traits_generator.h @@ -2646,7 +2646,7 @@ typedef integral_constant true_type; //********************************* // true if operator() exists and is unique //********************************* - static const bool value = decltype(test>(0))::value; + static constexpr bool value = decltype(test>(0))::value; }; #if ETL_USING_CPP17 @@ -2712,14 +2712,11 @@ typedef integral_constant true_type; //*************************************************************************** namespace private_type_traits { - template - struct logical_not_t : etl::integral_constant {}; - template struct is_member_object_pointer_helper : public etl::false_type {}; template - struct is_member_object_pointer_helper : public logical_not_t>::type {}; + struct is_member_object_pointer_helper : public etl::negation> {}; } template struct is_member_object_pointer : public private_type_traits::is_member_object_pointer_helper>::type {}; From 3525c63b54a68c80b155607b39fab97d9ae167c5 Mon Sep 17 00:00:00 2001 From: mike919192 <91038685+mike919192@users.noreply.github.com> Date: Mon, 8 Dec 2025 04:07:29 -0500 Subject: [PATCH 020/298] Bugfix: Issue 1212 span constructor (#1231) * Quick fix for issue 1212 * #if macro around std array uses * Fix macro placement * Maybe size_t * Maybe SIZE_ * Check if old boost style works * Fix angle brackets * Cleanup traits and add const constructors * Add traits to C++03 constructors --- include/etl/span.h | 60 ++++++++++++++++++++++++++++++++- test/test_span_fixed_extent.cpp | 3 ++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/include/etl/span.h b/include/etl/span.h index 1e8d5be2..c6f18799 100644 --- a/include/etl/span.h +++ b/include/etl/span.h @@ -55,6 +55,20 @@ SOFTWARE. namespace etl { + template struct is_std_array : etl::false_type {}; +#if ETL_USING_STL && ETL_USING_CPP11 + template struct is_std_array> : etl::true_type {}; +#endif + template struct is_std_array : is_std_array {}; + template struct is_std_array : is_std_array {}; + template struct is_std_array : is_std_array {}; + + template struct is_etl_array : etl::false_type {}; + template struct is_etl_array > : etl::true_type {}; + template struct is_etl_array : is_etl_array {}; + template struct is_etl_array : is_etl_array {}; + template struct is_etl_array : is_etl_array {}; + //*************************************************************************** // Tag to indicate a class is a span. //*************************************************************************** @@ -186,8 +200,10 @@ namespace etl /// data() and size() member functions. //************************************************************************* template >::value && + !etl::is_std_array>::value && + !etl::is_etl_array>::value && !etl::is_pointer>::value && - !etl::is_array>::value&& + !etl::is_array>::value && etl::is_same, etl::remove_cv_t::value_type>>::value, void>::type> ETL_CONSTEXPR span(TContainer&& a) ETL_NOEXCEPT : pbegin(a.data()) @@ -200,6 +216,8 @@ namespace etl //************************************************************************* template span(TContainer& a, typename etl::enable_if::type>::value && + !etl::is_std_array::type>::value && + !etl::is_etl_array::type>::value && !etl::is_pointer::type>::value && !etl::is_array::value && etl::is_same::type, typename etl::remove_cv::type::value_type>::type>::value, void>::type* = 0) ETL_NOEXCEPT @@ -213,6 +231,8 @@ namespace etl //************************************************************************* template span(const TContainer& a, typename etl::enable_if::type>::value && + !etl::is_std_array::type>::value && + !etl::is_etl_array::type>::value && !etl::is_pointer::type>::value && !etl::is_array::value&& etl::is_same::type, typename etl::remove_cv::type::value_type>::type>::value, void>::type* = 0) ETL_NOEXCEPT @@ -250,6 +270,44 @@ namespace etl ETL_ASSERT(other.size() == Extent, ETL_ERROR(span_size_mismatch)); } +#if ETL_USING_STL && ETL_USING_CPP11 + //************************************************************************* + /// Constructor from std array. + //************************************************************************* + template + ETL_CONSTEXPR span(std::array& other, typename etl::enable_if::type* = 0) ETL_NOEXCEPT + : pbegin(other.data()) + { + } + + //************************************************************************* + /// Constructor from const std array. + //************************************************************************* + template + ETL_CONSTEXPR span(const std::array& other, typename etl::enable_if::value, void>::type* = 0) ETL_NOEXCEPT + : pbegin(other.data()) + { + } +#endif + + //************************************************************************* + /// Constructor from etl array. + //************************************************************************* + template + ETL_CONSTEXPR span(etl::array& other, typename etl::enable_if::type* = 0) ETL_NOEXCEPT + : pbegin(other.data()) + { + } + + //************************************************************************* + /// Constructor from const etl array. + //************************************************************************* + template + ETL_CONSTEXPR span(const etl::array& other, typename etl::enable_if::value, void>::type* = 0) ETL_NOEXCEPT + : pbegin(other.data()) + { + } + //************************************************************************* /// Returns a reference to the first element. //************************************************************************* diff --git a/test/test_span_fixed_extent.cpp b/test/test_span_fixed_extent.cpp index d2c7e2f3..a70711a9 100644 --- a/test/test_span_fixed_extent.cpp +++ b/test/test_span_fixed_extent.cpp @@ -848,12 +848,15 @@ namespace TEST(test_issue_486) { //std::array c; + //etl::array c2; // Should not compile. //etl::span value(c); + //etl::span value2(c2); // Should not compile. //f_issue_486(c); + //f_issue_486(c2); } //************************************************************************* From 57c50fce8946bd012bf6895980fbb6230dc63d5f Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 8 Dec 2025 09:10:22 +0000 Subject: [PATCH 021/298] Updated misleading template parameter names --- include/etl/type_list.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/etl/type_list.h b/include/etl/type_list.h index eeea5052..84e241ec 100644 --- a/include/etl/type_list.h +++ b/include/etl/type_list.h @@ -185,7 +185,7 @@ namespace etl //*************************************************************************** /// Defines a bool constant that is true if the type_list contains the specified type, otherwise false. //*************************************************************************** - template + template struct type_list_contains; template @@ -208,7 +208,7 @@ namespace etl //*************************************************************************** /// Defines a bool constant that is true if the type_list has duplicates of the specified type, otherwise false. //*************************************************************************** - template + template struct type_list_has_duplicates_of; template @@ -231,7 +231,7 @@ namespace etl //*************************************************************************** /// Defines an integral constant that is the count of the number of times a type is in the type list. //*************************************************************************** - template + template struct type_list_count_of; template From 31b658ba81b4b6cc55d5d0e98cda7d2030f317d1 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 8 Dec 2025 09:11:17 +0000 Subject: [PATCH 022/298] Improve implementation of traits for functions --- include/etl/function_traits.h | 276 ++++++++++---- .../etl/generators/type_traits_generator.h | 112 +++++- include/etl/platform.h | 11 + include/etl/type_traits.h | 112 +++++- test/test_function_traits.cpp | 337 +++++++++++++++++- test/test_type_traits.cpp | 175 +++++++++ 6 files changed, 915 insertions(+), 108 deletions(-) diff --git a/include/etl/function_traits.h b/include/etl/function_traits.h index 5d30d684..48803656 100644 --- a/include/etl/function_traits.h +++ b/include/etl/function_traits.h @@ -21,7 +21,7 @@ copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +FITNESS FOR TArgs PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE @@ -36,101 +36,251 @@ SOFTWARE. #include "type_traits.h" #if ETL_USING_CPP11 + namespace etl { //*************************************************************************** - /// A template to extract the function type traits. + // Primary template (unspecialized) //*************************************************************************** - template + template struct function_traits; //*************************************************************************** - /// Specialisation for function pointers + // Base for plain function type TReturn(TArgs...) //*************************************************************************** template - struct function_traits + struct function_traits { - using function_type = TReturn(TArgs...); ///< The signature of the function. - using return_type = TReturn; ///< The return type. - using object_type = void; ///< The object type, if a member function. - using argument_types = etl::type_list; ///< An etl::type_list containing the function argument types. + public: - static constexpr bool is_function = true; ///< true if the type is a free, static or global function, otherwise false. - static constexpr bool is_member_function = false; ///< true if the type is a member function, otherwise false. - static constexpr bool is_const = false; ///< true if the type is a const member function, otherwise false. - static constexpr size_t argument_count = sizeof...(TArgs); ///< The number of arguments that the function takes. + using function_type = TReturn(TArgs...); + using return_type = TReturn; + using object_type = void; + using argument_types = etl::type_list; + + static constexpr bool is_function = true; + static constexpr bool is_member_function = false; + static constexpr bool is_functor = false; + static constexpr bool is_const = false; + static constexpr bool is_volatile = false; + static constexpr bool is_noexcept = false; + static constexpr size_t arity = sizeof...(TArgs); + + ETL_DEPRECATED_REASON("Use etl::function_traits::arity instead") + static constexpr size_t argument_count = arity; }; + //*************************************************************************** + // Free function pointer + //*************************************************************************** template - constexpr bool function_traits::is_function; - - template - constexpr bool function_traits::is_member_function; - - template - constexpr bool function_traits::is_const; - - template - constexpr size_t function_traits::argument_count; + struct function_traits : function_traits {}; //*************************************************************************** - /// Specialisation for member function pointers + // Free function reference //*************************************************************************** - template - struct function_traits + template + struct function_traits : function_traits {}; + +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + //*************************************************************************** + // Free noexcept function pointer + //*************************************************************************** + template + struct function_traits : function_traits { - using function_type = TReturn(TArgs...); ///< The signature of the function. - using return_type = TReturn; ///< The return type. - using object_type = TObject; ///< The object type, if a member function. - using argument_types = etl::type_list; ///< An etl::type_list containing the function argument types. - - static constexpr bool is_function = false; ///< true if the type is a free, static or global function, otherwise false. - static constexpr bool is_member_function = true; ///< true if the type is a member function, otherwise false. - static constexpr bool is_const = false; ///< true if the type is a const member function, otherwise false. - static constexpr size_t argument_count = sizeof...(TArgs); ///< The number of arguments that the function takes. + static constexpr bool is_noexcept = true; }; - template - constexpr bool function_traits::is_function; - - template - constexpr bool function_traits::is_member_function; - - template - constexpr bool function_traits::is_const; - - template - constexpr size_t function_traits::argument_count; - //*************************************************************************** - /// Specialisation for const member function pointers + // Free noexcept function reference. //*************************************************************************** - template - struct function_traits + template + struct function_traits : function_traits { - using function_type = TReturn(TArgs...); ///< The signature of the function. - using return_type = TReturn; ///< The return type. - using object_type = TObject; ///< The object type, if a member function. - using argument_types = etl::type_list; ///< An etl::type_list containing the function argument types. + static constexpr bool is_noexcept = true; + }; +#endif - static constexpr bool is_function = false; ///< true if the type is a free, static or global function, otherwise false. - static constexpr bool is_member_function = true; ///< true if the type is a member function, otherwise false. - static constexpr bool is_const = true; ///< true if the type is a const member function, otherwise false. - static constexpr size_t argument_count = sizeof...(TArgs); ///< The number of arguments that the function takes. + //*************************************************************************** + // Member function pointers + //*************************************************************************** + template + struct function_traits : function_traits + { + using object_type = TObject; + static constexpr bool is_function = false; + static constexpr bool is_member_function = true; }; + //*************************************************************************** + // Const member function pointers + //*************************************************************************** template - constexpr bool function_traits::is_function; + struct function_traits : function_traits + { + static constexpr bool is_const = true; + }; + + //*************************************************************************** + // Volatile member function pointers + //*************************************************************************** + template + struct function_traits : function_traits + { + static constexpr bool is_volatile = true; + }; + + //*************************************************************************** + // Const volatile member function pointers + //*************************************************************************** + template + struct function_traits : function_traits + { + static constexpr bool is_const = true; + static constexpr bool is_volatile = true; + }; + +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + //*************************************************************************** + // Noexcept member function pointers + //*************************************************************************** + template + struct function_traits : function_traits + { + static constexpr bool is_noexcept = true; + }; + + //*************************************************************************** + // Const noexcept member function pointers + //*************************************************************************** + template + struct function_traits : function_traits + { + static constexpr bool is_noexcept = true; + }; + + //*************************************************************************** + // Volatile noexcept member function pointers + //*************************************************************************** + template + struct function_traits : function_traits + { + static constexpr bool is_noexcept = true; + }; + + //*************************************************************************** + // Const volatile noexcept member function pointers + //*************************************************************************** + template + struct function_traits : function_traits + { + static constexpr bool is_noexcept = true; + }; +#endif + + //*************************************************************************** + // Forward cv/ref on the whole type to the unqualified type. + //*************************************************************************** + template + struct function_traits>::value && + !etl::is_class>::value>> + : function_traits> + { + }; + + //*************************************************************************** + // Functors / lambdas: enable only for class types that have a unique operator() + //*************************************************************************** + namespace private_function_traits + { + //********************************* + // Helper to get pointer to call operator + //********************************* + template + using call_operator_ptr_t = decltype(&U::operator()); + } + + //*************************************************************************** + /// Functors / lambdas specialisation + //*************************************************************************** + template + struct function_traits>::value&& + etl::has_unique_call_operator::value>> + : function_traits> > + { + static constexpr bool is_functor = true; + }; + + //*************************************************************************** + // Out-of-class definitions for the function_traits static members + //*************************************************************************** + // free/function primary template + template + constexpr bool function_traits::is_function; + + template + constexpr bool function_traits::is_member_function; + + template + constexpr bool function_traits::is_functor; + + template + constexpr bool function_traits::is_const; + + template + constexpr bool function_traits::is_volatile; + + template + constexpr bool function_traits::is_noexcept; + + template + constexpr size_t function_traits::arity; + + // member-function-pointer specialization + template + constexpr bool function_traits::is_function; template - constexpr bool function_traits::is_member_function; + constexpr bool function_traits::is_member_function; + + // cv/ref-qualified member-function pointer flags + template + constexpr bool function_traits::is_const; + + template + constexpr bool function_traits::is_volatile; + + template + constexpr bool function_traits::is_const; + + template + constexpr bool function_traits::is_volatile; + +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + template + constexpr bool function_traits::is_noexcept; template - constexpr bool function_traits::is_const; + constexpr bool function_traits::is_noexcept; template - constexpr size_t function_traits::argument_count; + constexpr bool function_traits::is_noexcept; + + template + constexpr bool function_traits::is_noexcept; + + template + constexpr bool function_traits::is_noexcept; +#endif + + //*************************************************************************** + // Functor / lambda specialisation: provide out-of-class definition for is_functor + //*************************************************************************** + template + constexpr bool function_traits>::value && + etl::has_unique_call_operator::value>>::is_functor; } -#endif #endif +#endif \ No newline at end of file diff --git a/include/etl/generators/type_traits_generator.h b/include/etl/generators/type_traits_generator.h index c3a95f22..43096f7b 100644 --- a/include/etl/generators/type_traits_generator.h +++ b/include/etl/generators/type_traits_generator.h @@ -2571,10 +2571,13 @@ typedef integral_constant true_type; // Plain / cv-qualified template struct is_function : etl::true_type {}; + template struct is_function : etl::true_type {}; + template struct is_function : etl::true_type {}; + template struct is_function : etl::true_type {}; @@ -2582,18 +2585,41 @@ typedef integral_constant true_type; template struct is_function : etl::true_type {}; - // noexcept variants (if supported by the toolchain) + template + struct is_function : etl::true_type {}; + + template + struct is_function : etl::true_type {}; + + template + struct is_function : etl::true_type {}; + + // noexcept variants (if supported) #if ETL_HAS_NOEXCEPT_FUNCTION_TYPE template struct is_function : etl::true_type {}; + template struct is_function : etl::true_type {}; + template struct is_function : etl::true_type {}; + template struct is_function : etl::true_type {}; + + template struct is_function : etl::true_type {}; + + template + struct is_function : etl::true_type {}; + + template + struct is_function : etl::true_type {}; + + template + struct is_function : etl::true_type {}; #endif #if ETL_USING_CPP17 @@ -2679,26 +2705,74 @@ typedef integral_constant true_type; //*************************************************************************** /// Is T a member function pointer //*************************************************************************** - namespace private_type_traits - { - // Primary: not a member function pointer. - template - struct is_member_function_pointer_helper : etl::false_type - { - }; + template struct is_member_function_pointer : etl::false_type {}; - // If the type is 'TMember TObject::*' then TMember is the member - // Uses etl::is_function to detect member function pointers. - template - struct is_member_function_pointer_helper : etl::is_function - { - }; - } + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; - template - struct is_member_function_pointer : private_type_traits::is_member_function_pointer_helper> - { - }; +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; +#endif + + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer: etl::true_type {}; + +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer: etl::true_type {}; +#endif + + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; +#endif + + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer: etl::true_type {}; + +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer: etl::true_type {}; +#endif #endif #if ETL_USING_CPP17 diff --git a/include/etl/platform.h b/include/etl/platform.h index a4710d09..89fafeef 100644 --- a/include/etl/platform.h +++ b/include/etl/platform.h @@ -325,6 +325,16 @@ SOFTWARE. #define ETL_HAS_CHRONO_LITERALS_DURATION 1 #endif +//************************************* +// Indicate if noexcept is part of the function type. +#if !defined(ETL_HAS_NOEXCEPT_FUNCTION_TYPE) + #if defined(__cpp_noexcept_function_type) && (__cpp_noexcept_function_type >= 201510) + #define ETL_HAS_NOEXCEPT_FUNCTION_TYPE 1 + #else + #define ETL_HAS_NOEXCEPT_FUNCTION_TYPE 0 + #endif +#endif + //************************************* // The macros below are dependent on the profile. // C++11 @@ -652,6 +662,7 @@ namespace etl static ETL_CONSTANT bool has_chrono_literals_microseconds = (ETL_HAS_CHRONO_LITERALS_DURATION == 1); static ETL_CONSTANT bool has_chrono_literals_nanoseconds = (ETL_HAS_CHRONO_LITERALS_DURATION == 1); static ETL_CONSTANT bool has_std_byteswap = (ETL_HAS_STD_BYTESWAP == 1); + static ETL_CONSTANT bool has_noexcept_function_type = (ETL_HAS_NOEXCEPT_FUNCTION_TYPE == 1); // Is... static ETL_CONSTANT bool is_debug_build = (ETL_IS_DEBUG_BUILD == 1); diff --git a/include/etl/type_traits.h b/include/etl/type_traits.h index bf285583..dbb56fc0 100644 --- a/include/etl/type_traits.h +++ b/include/etl/type_traits.h @@ -2564,10 +2564,13 @@ typedef integral_constant true_type; // Plain / cv-qualified template struct is_function : etl::true_type {}; + template struct is_function : etl::true_type {}; + template struct is_function : etl::true_type {}; + template struct is_function : etl::true_type {}; @@ -2575,18 +2578,41 @@ typedef integral_constant true_type; template struct is_function : etl::true_type {}; - // noexcept variants (if supported by the toolchain) + template + struct is_function : etl::true_type {}; + + template + struct is_function : etl::true_type {}; + + template + struct is_function : etl::true_type {}; + + // noexcept variants (if supported) #if ETL_HAS_NOEXCEPT_FUNCTION_TYPE template struct is_function : etl::true_type {}; + template struct is_function : etl::true_type {}; + template struct is_function : etl::true_type {}; + template struct is_function : etl::true_type {}; + + template struct is_function : etl::true_type {}; + + template + struct is_function : etl::true_type {}; + + template + struct is_function : etl::true_type {}; + + template + struct is_function : etl::true_type {}; #endif #if ETL_USING_CPP17 @@ -2672,26 +2698,74 @@ typedef integral_constant true_type; //*************************************************************************** /// Is T a member function pointer //*************************************************************************** - namespace private_type_traits - { - // Primary: not a member function pointer. - template - struct is_member_function_pointer_helper : etl::false_type - { - }; + template struct is_member_function_pointer : etl::false_type {}; - // If the type is 'TMember TObject::*' then TMember is the member - // Uses etl::is_function to detect member function pointers. - template - struct is_member_function_pointer_helper : etl::is_function - { - }; - } + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; - template - struct is_member_function_pointer : private_type_traits::is_member_function_pointer_helper> - { - }; +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; +#endif + + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer: etl::true_type {}; + +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer: etl::true_type {}; +#endif + + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; +#endif + + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer: etl::true_type {}; + +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer : etl::true_type {}; + template struct is_member_function_pointer: etl::true_type {}; +#endif #endif #if ETL_USING_CPP17 diff --git a/test/test_function_traits.cpp b/test/test_function_traits.cpp index 3e065f58..56024198 100644 --- a/test/test_function_traits.cpp +++ b/test/test_function_traits.cpp @@ -42,6 +42,13 @@ namespace { } + //***************************************************************************** + // The free noexcept function taking no parameters. + //***************************************************************************** + void free_void_noexcept() noexcept + { + } + //***************************************************************************** // The free function taking an int parameter. //***************************************************************************** @@ -67,6 +74,30 @@ namespace { } + void member_void_noexcept() noexcept + { + } + + void member_void_const_noexcept() const noexcept + { + } + + void member_void_volatile() volatile + { + } + + void member_void_volatile_noexcept() volatile noexcept + { + } + + void member_void_const_volatile() const volatile + { + } + + void member_void_const_volatile_noexcept() const volatile noexcept + { + } + //******************************************* // int int member_int(int i, int j) @@ -86,6 +117,16 @@ namespace (void)j; } }; + + //***************************************************************************** + // A functor with a unique operator() + //***************************************************************************** + struct Functor { int operator()(int x) { return x + 1; } }; + + //***************************************************************************** + // A functor with a unique operator() + //***************************************************************************** + struct FunctorConst { int operator()(int x) const { return x + 1; } }; } namespace @@ -106,8 +147,30 @@ namespace CHECK_TRUE(traits::is_function); CHECK_FALSE(traits::is_member_function); + CHECK_FALSE(traits::is_functor); CHECK_FALSE(traits::is_const); - CHECK_EQUAL(0, traits::argument_count); + CHECK_FALSE(traits::is_volatile); + CHECK_FALSE(traits::is_noexcept); + CHECK_EQUAL(0, traits::arity); + } + + //************************************************************************* + TEST(test_free_function_free_void_noexcept) + { + free_void_noexcept(); // Keep clang happy + + using traits = etl::function_traits; + + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same, traits::argument_types>::value)); + + CHECK_TRUE(traits::is_function); + CHECK_FALSE(traits::is_member_function); + CHECK_FALSE(traits::is_functor); + CHECK_FALSE(traits::is_const); + CHECK_FALSE(traits::is_volatile); } //************************************************************************* @@ -124,8 +187,11 @@ namespace CHECK_TRUE(traits::is_function); CHECK_FALSE(traits::is_member_function); + CHECK_FALSE(traits::is_functor); CHECK_FALSE(traits::is_const); - CHECK_EQUAL(2 , traits::argument_count); + CHECK_FALSE(traits::is_volatile); + CHECK_FALSE(traits::is_noexcept); + CHECK_EQUAL(2, traits::arity); } //************************************************************************* @@ -140,8 +206,11 @@ namespace CHECK_FALSE(traits::is_function); CHECK_TRUE(traits::is_member_function); + CHECK_FALSE(traits::is_functor); CHECK_FALSE(traits::is_const); - CHECK_EQUAL(0, traits::argument_count); + CHECK_FALSE(traits::is_volatile); + CHECK_FALSE(traits::is_noexcept); + CHECK_EQUAL(0, traits::arity); } //************************************************************************* @@ -156,8 +225,141 @@ namespace CHECK_FALSE(traits::is_function); CHECK_TRUE(traits::is_member_function); + CHECK_FALSE(traits::is_functor); CHECK_TRUE(traits::is_const); - CHECK_EQUAL(0, traits::argument_count); + CHECK_FALSE(traits::is_volatile); + CHECK_FALSE(traits::is_noexcept); + CHECK_EQUAL(0, traits::arity); + } + + //************************************************************************* + TEST(test_member_function_void_noexcept) + { + using traits = etl::function_traits; + + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same, traits::argument_types>::value)); + + CHECK_FALSE(traits::is_function); + CHECK_TRUE(traits::is_member_function); + CHECK_FALSE(traits::is_functor); + CHECK_FALSE(traits::is_const); + CHECK_FALSE(traits::is_volatile); +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + CHECK_TRUE(traits::is_noexcept); +#else + CHECK_FALSE(traits::is_noexcept); +#endif + CHECK_EQUAL(0, traits::arity); + } + + //************************************************************************* + TEST(test_member_function_void_const_noexcept) + { + using traits = etl::function_traits; + + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same, traits::argument_types>::value)); + + CHECK_FALSE(traits::is_function); + CHECK_TRUE(traits::is_member_function); + CHECK_FALSE(traits::is_functor); + CHECK_TRUE(traits::is_const); + CHECK_FALSE(traits::is_volatile); +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + CHECK_TRUE(traits::is_noexcept); +#else + CHECK_FALSE(traits::is_noexcept); +#endif + CHECK_EQUAL(0, traits::arity); + } + + //************************************************************************* + TEST(test_member_function_void_volatile) + { + using traits = etl::function_traits; + + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same, traits::argument_types>::value)); + + CHECK_FALSE(traits::is_function); + CHECK_TRUE(traits::is_member_function); + CHECK_FALSE(traits::is_functor); + CHECK_FALSE(traits::is_const); + CHECK_TRUE(traits::is_volatile); + CHECK_FALSE(traits::is_noexcept); + CHECK_EQUAL(0, traits::arity); + } + + //************************************************************************* + TEST(test_member_function_void_const_volatile) + { + using traits = etl::function_traits; + + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same, traits::argument_types>::value)); + + CHECK_FALSE(traits::is_function); + CHECK_TRUE(traits::is_member_function); + CHECK_FALSE(traits::is_functor); + CHECK_TRUE(traits::is_const); + CHECK_TRUE(traits::is_volatile); + CHECK_FALSE(traits::is_noexcept); + CHECK_EQUAL(0, traits::arity); + } + + //************************************************************************* + TEST(test_member_function_void_volatile_noexcept) + { + using traits = etl::function_traits; + + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same, traits::argument_types>::value)); + + CHECK_FALSE(traits::is_function); + CHECK_TRUE(traits::is_member_function); + CHECK_FALSE(traits::is_functor); + CHECK_FALSE(traits::is_const); + CHECK_TRUE(traits::is_volatile); +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + CHECK_TRUE(traits::is_noexcept); +#else + CHECK_FALSE(traits::is_noexcept); +#endif + CHECK_EQUAL(0, traits::arity); + } + + //************************************************************************* + TEST(test_member_function_void_const_volatile_noexcept) + { + using traits = etl::function_traits; + + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same, traits::argument_types>::value)); + + CHECK_FALSE(traits::is_function); + CHECK_TRUE(traits::is_member_function); + CHECK_FALSE(traits::is_functor); + CHECK_TRUE(traits::is_const); + CHECK_TRUE(traits::is_volatile); +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + CHECK_TRUE(traits::is_noexcept); +#else + CHECK_FALSE(traits::is_noexcept); +#endif + CHECK_EQUAL(0, traits::arity); } //************************************************************************* @@ -172,8 +374,11 @@ namespace CHECK_FALSE(traits::is_function); CHECK_TRUE(traits::is_member_function); + CHECK_FALSE(traits::is_functor); CHECK_FALSE(traits::is_const); - CHECK_EQUAL(2, traits::argument_count); + CHECK_FALSE(traits::is_volatile); + CHECK_FALSE(traits::is_noexcept); + CHECK_EQUAL(2, traits::arity); } //************************************************************************* @@ -188,8 +393,11 @@ namespace CHECK_FALSE(traits::is_function); CHECK_TRUE(traits::is_member_function); + CHECK_FALSE(traits::is_functor); CHECK_TRUE(traits::is_const); - CHECK_EQUAL(2, traits::argument_count); + CHECK_FALSE(traits::is_volatile); + CHECK_FALSE(traits::is_noexcept); + CHECK_EQUAL(2, traits::arity); } //************************************************************************* @@ -204,8 +412,123 @@ namespace CHECK_TRUE(traits::is_function); CHECK_FALSE(traits::is_member_function); + CHECK_FALSE(traits::is_functor); CHECK_FALSE(traits::is_const); - CHECK_EQUAL(1, traits::argument_count); + CHECK_FALSE(traits::is_volatile); + CHECK_FALSE(traits::is_noexcept); + CHECK_EQUAL(1, traits::arity); + } + + //************************************************************************* + TEST(test_lambda) + { + auto lambda = [](int a, const std::string& s) -> long { return static_cast(a + s.size()); }; + + using traits = etl::function_traits; + + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same, traits::argument_types>::value)); + + CHECK_FALSE(traits::is_function); + CHECK_TRUE(traits::is_member_function); + CHECK_TRUE(traits::is_functor); + CHECK_TRUE(traits::is_const); + CHECK_FALSE(traits::is_volatile); + CHECK_FALSE(traits::is_noexcept); + CHECK_EQUAL(2, traits::arity); + } + + //************************************************************************* + TEST(test_functor) + { + struct functor + { + long operator()(int a, const std::string& s) + { + return static_cast(a + s.size()); + }; + }; + + using traits = etl::function_traits; + + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same, traits::argument_types>::value)); + + CHECK_FALSE(traits::is_function); + CHECK_TRUE(traits::is_member_function); + CHECK_TRUE(traits::is_functor); + CHECK_FALSE(traits::is_const); + CHECK_FALSE(traits::is_volatile); + CHECK_FALSE(traits::is_noexcept); + CHECK_EQUAL(2, traits::arity); + } + + //************************************************************************* + // Forwarding of top-level cv/ref on the whole type to the unqualified type + TEST(test_function_traits_forward_cvref_free_ptr) + { + using ptr_t = decltype(&free_void); + using const_ptr_t = typename std::add_const::type; // void(* const)() + using ref_ptr_t = ptr_t&; // void(*&)() + + using traits_c = etl::function_traits; + using traits_r = etl::function_traits; + + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE(traits_c::is_function); + CHECK_TRUE(traits_r::is_function); + CHECK_FALSE(traits_c::is_member_function); + CHECK_FALSE(traits_r::is_member_function); + } + + //************************************************************************* + TEST(test_function_traits_forward_cvref_member_ptr) + { + using mptr_t = decltype(&Object::member_int); + using const_mptr_t = typename std::add_const::type; // int (Object::* const)(int,int) + using ref_mptr_t = mptr_t&; // int (Object::*&)(int,int) + + using traits_c = etl::function_traits; + using traits_r = etl::function_traits; + + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_FALSE(traits_c::is_function); + CHECK_FALSE(traits_r::is_function); + CHECK_TRUE(traits_c::is_member_function); + CHECK_TRUE(traits_r::is_member_function); + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + } + + //************************************************************************* + // Ensure function_traits resolves for Functor and const Functor + TEST(test_function_traits_functor_and_const_functor) + { + using traits_f = etl::function_traits; + using traits_cf = etl::function_traits; + + // Both should be recognized as functor types + CHECK_TRUE(traits_f::is_functor); + CHECK_TRUE(traits_cf::is_functor); + + // The function_type should be int(int) + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + + // const Functor should be marked const + CHECK_FALSE(traits_f::is_const); + CHECK_TRUE(traits_cf::is_const); + + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + CHECK_EQUAL(1, traits_f::arity); + CHECK_EQUAL(1, traits_cf::arity); } }; } diff --git a/test/test_type_traits.cpp b/test/test_type_traits.cpp index f6c8a73f..76d8b8cc 100644 --- a/test/test_type_traits.cpp +++ b/test/test_type_traits.cpp @@ -140,6 +140,67 @@ namespace struct other_specialized { }; + + struct MF + { + int f(int) { return 0; } + int fc(int) const { return 0; } + int fv(int) volatile { return 0; } + int fcv(int) const volatile { return 0; } + +#if ETL_USING_CPP11 + int fl(int) & { return 0; } + int flc(int) const & { return 0; } + int flv(int) volatile & { return 0; } + int flcv(int) const volatile & { return 0; } + + int fr(int) && { return 0; } + int frc(int) const && { return 0; } + int frv(int) volatile && { return 0; } + int frcv(int) const volatile && { return 0; } +#endif + +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + int fn(int) noexcept { return 0; } + int fnc(int) const noexcept { return 0; } + int fnv(int) volatile noexcept { return 0; } + int fncv(int) const volatile noexcept { return 0; } + + int fnl(int) & noexcept { return 0; } + int fnlc(int) const & noexcept { return 0; } + int fnlv(int) volatile & noexcept { return 0; } + int fnlcv(int) const volatile & noexcept { return 0; } + + int fnr(int) && noexcept { return 0; } + int fnrc(int) const && noexcept { return 0; } + int fnrv(int) volatile && noexcept { return 0; } + int fnrcv(int) const volatile && noexcept { return 0; } +#endif + + int fvar(int, ...) { return 0; } + int fvarc(int, ...) const { return 0; } + }; + + struct MO + { + int data; + }; + + static int f(int) { return 0; } + static int fvar(...) { return 0; } + static int fvar2(int, ...) { return 0; } + + template + static T ft(TArgs...) { return T(); } + +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + static int fn(int) noexcept { return 0; } + static int fnvar(...) noexcept { return 0; } + static int fnvar2(int, ...) noexcept { return 0; } + + template + static T fnt(TArgs...) noexcept { return T(); } +#endif } // Definitions for when the STL and compiler built-ins are not available. @@ -1490,4 +1551,118 @@ namespace CHECK_FALSE(c1); } #endif + + //************************************************************************* + // Basic cv for member function pointers + TEST(test_is_member_function_pointer) + { + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); +#endif + + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + } + + //************************************************************************* + // Negative tests for member function pointer trait + TEST(test_is_member_function_pointer_negative) + { + (void)f(0); + + // Free function pointer + CHECK_FALSE((etl::is_member_function_pointer::value)); + + // Member object pointer + CHECK_FALSE((etl::is_member_function_pointer::value)); + + // Plain function type (not pointer) + CHECK_FALSE((etl::is_member_function_pointer::value)); + + // Non-function type + CHECK_FALSE((etl::is_member_function_pointer::value)); + } + + //************************************************************************* + // Member object pointer trait + TEST(test_is_member_object_pointer) + { + CHECK_TRUE((etl::is_member_object_pointer::value)); + + // Not a member object pointer + CHECK_FALSE((etl::is_member_object_pointer::value)); + CHECK_FALSE((etl::is_member_object_pointer::value)); + } + + //************************************************************************* + // Member pointer (either member object or member function pointer) + TEST(test_is_member_pointer_any) + { + CHECK_TRUE((etl::is_member_pointer::value)); + CHECK_TRUE((etl::is_member_pointer::value)); + + // Not member pointers + CHECK_FALSE((etl::is_member_pointer::value)); + CHECK_FALSE((etl::is_member_pointer::value)); + } + + //************************************************************************* + // Function type detection + TEST(test_is_function) + { + (void)f(0); + (void)fvar(); + (void)fvar2(0); + (void)ft(0, 0.0); + + CHECK_TRUE((etl::is_function::value)); + CHECK_TRUE((etl::is_function::value)); + CHECK_TRUE((etl::is_function::value)); + CHECK_TRUE((etl::is_function)>::value)); + +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + (void)fn(0); + (void)fnvar(); + (void)fnvar2(0); + (void)fnt(0, 0.0); + + CHECK_TRUE((etl::is_function::value)); + CHECK_TRUE((etl::is_function::value)); + CHECK_TRUE((etl::is_function::value)); + CHECK_TRUE((etl::is_function)>::value)); +#endif + + CHECK_FALSE((etl::is_function::value)); + CHECK_FALSE((etl::is_function::value)); + CHECK_FALSE((etl::is_function::value)); + CHECK_FALSE((etl::is_function::value)); // pointer, not function + } } From 1039327148075cc4bfde88acea1a31fbd8ca7150 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 9 Dec 2025 08:57:23 +0000 Subject: [PATCH 023/298] Minor comment and project file change --- test/test_span_fixed_extent.cpp | 4 ++-- test/vs2022/etl.vcxproj.filters | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/test/test_span_fixed_extent.cpp b/test/test_span_fixed_extent.cpp index a70711a9..70d4350d 100644 --- a/test/test_span_fixed_extent.cpp +++ b/test/test_span_fixed_extent.cpp @@ -428,7 +428,7 @@ namespace CHECK_EQUAL(etldata.back(), view.back()); CHECK_EQUAL(etldata.back(), cview.back()); - //these should trigger static asserts + // These should trigger static asserts // auto empty_view = view.subspan<0, 0>(); // CHECK_THROW({ auto front = empty_view.front(); (void)front; }, etl::span_out_of_range); // CHECK_THROW({ auto back = empty_view.back(); (void)back; }, etl::span_out_of_range); @@ -561,7 +561,7 @@ namespace CHECK_EQUAL(first.size(), cresult.extent); CHECK_EQUAL(first.size(), cresult.size()); - //these should trigger static asserts + // These should trigger static asserts // CHECK_THROW({ auto result2 = view.first<11>(); (void)result2; }, etl::span_out_of_range); // CHECK_THROW({ auto cresult2 = cview.first<11>(); (void)cresult2; }, etl::span_out_of_range); } diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index 7c816a12..af36ac3b 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -3716,9 +3716,6 @@ Tests\Syntax Checks\Source - - Tests - Tests\Syntax Checks\Source @@ -3734,6 +3731,12 @@ Tests\Misc + + Tests\Callbacks & Delegates + + + Tests\State Machines + From 133d065bf19ca382565c90ecff736d6ad9d1b0ac Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 9 Dec 2025 08:58:07 +0000 Subject: [PATCH 024/298] Updated release notes --- support/Release notes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/support/Release notes.txt b/support/Release notes.txt index 94f74931..7be7c7ae 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -19,6 +19,7 @@ Pull Requests: #1225 Fix value_or not taking const in optional #1226 Add missing include to optional #1229 variant_legacy.h: Rename template parameters +#1231 Issue 1212 span constructor =============================================================================== 20.44.1 From 868eaa2b79b4e2471e3147917441f7737089ffcc Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 9 Dec 2025 09:11:07 +0000 Subject: [PATCH 025/298] Changed Github CI to use macos-15 --- .github/workflows/clang-c++20.yml | 8 ++++---- .github/workflows/clang-c++23.yml | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/clang-c++20.yml b/.github/workflows/clang-c++20.yml index d1e640a6..d170a982 100644 --- a/.github/workflows/clang-c++20.yml +++ b/.github/workflows/clang-c++20.yml @@ -100,7 +100,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [macos-13] + os: [macos-15] steps: - uses: actions/checkout@v4 @@ -122,7 +122,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [macos-13] + os: [macos-15] steps: - uses: actions/checkout@v4 @@ -144,7 +144,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [macos-13] + os: [macos-15] steps: - uses: actions/checkout@v4 @@ -166,7 +166,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [macos-13] + os: [macos-15] steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/clang-c++23.yml b/.github/workflows/clang-c++23.yml index 82c4a16d..b6b6cd84 100644 --- a/.github/workflows/clang-c++23.yml +++ b/.github/workflows/clang-c++23.yml @@ -99,7 +99,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [macos-13] + os: [macos-15] steps: - uses: actions/checkout@v4 @@ -121,7 +121,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [macos-13] + os: [macos-15] steps: - uses: actions/checkout@v4 @@ -143,7 +143,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [macos-13] + os: [macos-15] steps: - uses: actions/checkout@v4 @@ -165,7 +165,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [macos-13] + os: [macos-15] steps: - uses: actions/checkout@v4 From 338d0a4cf5795dd555683839ff99f6fa86ecd9e8 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 9 Dec 2025 09:34:07 +0000 Subject: [PATCH 026/298] Don't test deprecated has_denorm in C++23 and above --- test/test_limits.cpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/test_limits.cpp b/test/test_limits.cpp index c82f662c..38a75ae1 100644 --- a/test/test_limits.cpp +++ b/test/test_limits.cpp @@ -45,7 +45,9 @@ namespace CHECK_EQUAL(STD_NL::digits, ETL_NL::digits); CHECK_EQUAL(STD_NL::digits10, ETL_NL::digits10); CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); +#if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); +#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); @@ -84,7 +86,9 @@ namespace CHECK_EQUAL(STD_NL::digits, ETL_NL::digits); CHECK_EQUAL(STD_NL::digits10, ETL_NL::digits10); CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); +#if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); +#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); @@ -123,7 +127,9 @@ namespace CHECK_EQUAL(STD_NL::digits, ETL_NL::digits); CHECK_EQUAL(STD_NL::digits10, ETL_NL::digits10); CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); +#if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); +#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); @@ -162,7 +168,9 @@ namespace CHECK_EQUAL(STD_NL::digits, ETL_NL::digits); CHECK_EQUAL(STD_NL::digits10, ETL_NL::digits10); CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); +#if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); +#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); @@ -201,7 +209,9 @@ namespace CHECK_EQUAL(STD_NL::digits, ETL_NL::digits); CHECK_EQUAL(STD_NL::digits10, ETL_NL::digits10); CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); +#if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); +#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); @@ -240,7 +250,9 @@ namespace CHECK_EQUAL(STD_NL::digits, ETL_NL::digits); CHECK_EQUAL(STD_NL::digits10, ETL_NL::digits10); CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); +#if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); +#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); @@ -279,7 +291,9 @@ namespace CHECK_EQUAL(STD_NL::digits, ETL_NL::digits); CHECK_EQUAL(STD_NL::digits10, ETL_NL::digits10); CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); +#if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); +#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); @@ -318,7 +332,9 @@ namespace CHECK_EQUAL(STD_NL::digits, ETL_NL::digits); CHECK_EQUAL(STD_NL::digits10, ETL_NL::digits10); CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); +#if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); +#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); @@ -357,7 +373,9 @@ namespace CHECK_EQUAL(STD_NL::digits, ETL_NL::digits); CHECK_EQUAL(STD_NL::digits10, ETL_NL::digits10); CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); +#if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); +#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); @@ -396,7 +414,9 @@ namespace CHECK_EQUAL(STD_NL::digits, ETL_NL::digits); CHECK_EQUAL(STD_NL::digits10, ETL_NL::digits10); CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); +#if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); +#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); @@ -435,7 +455,9 @@ namespace CHECK_EQUAL(STD_NL::digits, ETL_NL::digits); CHECK_EQUAL(STD_NL::digits10, ETL_NL::digits10); CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); +#if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); +#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); @@ -474,7 +496,9 @@ namespace CHECK_EQUAL(STD_NL::digits, ETL_NL::digits); CHECK_EQUAL(STD_NL::digits10, ETL_NL::digits10); CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); +#if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); +#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); @@ -513,7 +537,9 @@ namespace CHECK_EQUAL(STD_NL::digits, ETL_NL::digits); CHECK_EQUAL(STD_NL::digits10, ETL_NL::digits10); CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); +#if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); +#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); @@ -552,7 +578,9 @@ namespace CHECK_EQUAL(STD_NL::digits, ETL_NL::digits); CHECK_EQUAL(STD_NL::digits10, ETL_NL::digits10); CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); +#if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); +#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); @@ -591,7 +619,9 @@ namespace CHECK_EQUAL(STD_NL::digits, ETL_NL::digits); CHECK_EQUAL(STD_NL::digits10, ETL_NL::digits10); CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); +#if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); +#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); From 9eb17369c470c70c977f26c9069f3d652c52a175 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 9 Dec 2025 09:34:07 +0000 Subject: [PATCH 027/298] Don't test deprecated has_denorm in C++23 and above --- test/test_limits.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/test_limits.cpp b/test/test_limits.cpp index 38a75ae1..6858c86d 100644 --- a/test/test_limits.cpp +++ b/test/test_limits.cpp @@ -49,6 +49,7 @@ namespace CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); #endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); +#endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); CHECK_EQUAL(STD_NL::has_signaling_NaN, ETL_NL::has_signaling_NaN); @@ -90,6 +91,7 @@ namespace CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); #endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); +#endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); CHECK_EQUAL(STD_NL::has_signaling_NaN, ETL_NL::has_signaling_NaN); @@ -131,6 +133,7 @@ namespace CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); #endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); +#endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); CHECK_EQUAL(STD_NL::has_signaling_NaN, ETL_NL::has_signaling_NaN); @@ -172,6 +175,7 @@ namespace CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); #endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); +#endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); CHECK_EQUAL(STD_NL::has_signaling_NaN, ETL_NL::has_signaling_NaN); @@ -213,6 +217,7 @@ namespace CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); #endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); +#endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); CHECK_EQUAL(STD_NL::has_signaling_NaN, ETL_NL::has_signaling_NaN); @@ -254,6 +259,7 @@ namespace CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); #endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); +#endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); CHECK_EQUAL(STD_NL::has_signaling_NaN, ETL_NL::has_signaling_NaN); @@ -295,6 +301,7 @@ namespace CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); #endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); +#endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); CHECK_EQUAL(STD_NL::has_signaling_NaN, ETL_NL::has_signaling_NaN); @@ -336,6 +343,7 @@ namespace CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); #endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); +#endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); CHECK_EQUAL(STD_NL::has_signaling_NaN, ETL_NL::has_signaling_NaN); @@ -377,6 +385,7 @@ namespace CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); #endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); +#endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); CHECK_EQUAL(STD_NL::has_signaling_NaN, ETL_NL::has_signaling_NaN); @@ -418,6 +427,7 @@ namespace CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); #endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); +#endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); CHECK_EQUAL(STD_NL::has_signaling_NaN, ETL_NL::has_signaling_NaN); @@ -459,6 +469,7 @@ namespace CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); #endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); +#endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); CHECK_EQUAL(STD_NL::has_signaling_NaN, ETL_NL::has_signaling_NaN); @@ -500,6 +511,7 @@ namespace CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); #endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); +#endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); CHECK_EQUAL(STD_NL::has_signaling_NaN, ETL_NL::has_signaling_NaN); @@ -541,6 +553,7 @@ namespace CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); #endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); +#endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); CHECK_EQUAL(STD_NL::has_signaling_NaN, ETL_NL::has_signaling_NaN); @@ -582,6 +595,7 @@ namespace CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); #endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); +#endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); CHECK_EQUAL(STD_NL::has_signaling_NaN, ETL_NL::has_signaling_NaN); @@ -623,6 +637,7 @@ namespace CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); #endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); +#endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); CHECK_EQUAL(STD_NL::has_quiet_NaN, ETL_NL::has_quiet_NaN); CHECK_EQUAL(STD_NL::has_signaling_NaN, ETL_NL::has_signaling_NaN); From 6ebd24578bdbe42925d649edd4a4f15b8059a76a Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 9 Dec 2025 09:34:07 +0000 Subject: [PATCH 028/298] Don't test deprecated has_denorm in C++23 and above --- test/test_limits.cpp | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/test/test_limits.cpp b/test/test_limits.cpp index 6858c86d..8c120454 100644 --- a/test/test_limits.cpp +++ b/test/test_limits.cpp @@ -47,7 +47,6 @@ namespace CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); #if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); -#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); #endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); @@ -89,7 +88,6 @@ namespace CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); #if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); -#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); #endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); @@ -131,7 +129,6 @@ namespace CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); #if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); -#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); #endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); @@ -173,7 +170,6 @@ namespace CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); #if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); -#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); #endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); @@ -215,7 +211,6 @@ namespace CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); #if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); -#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); #endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); @@ -257,7 +252,6 @@ namespace CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); #if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); -#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); #endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); @@ -299,7 +293,6 @@ namespace CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); #if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); -#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); #endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); @@ -341,7 +334,6 @@ namespace CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); #if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); -#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); #endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); @@ -383,7 +375,6 @@ namespace CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); #if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); -#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); #endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); @@ -425,7 +416,6 @@ namespace CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); #if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); -#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); #endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); @@ -467,7 +457,6 @@ namespace CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); #if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); -#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); #endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); @@ -509,7 +498,6 @@ namespace CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); #if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); -#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); #endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); @@ -551,7 +539,6 @@ namespace CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); #if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); -#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); #endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); @@ -593,7 +580,6 @@ namespace CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); #if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); -#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); #endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); @@ -635,7 +621,6 @@ namespace CHECK_EQUAL(STD_NL::epsilon(), ETL_NL::epsilon()); #if ETL_NOT_USING_CPP23 CHECK_EQUAL(int(STD_NL::has_denorm), int(ETL_NL::has_denorm)); -#endif CHECK_EQUAL(STD_NL::has_denorm_loss, ETL_NL::has_denorm_loss); #endif CHECK_EQUAL(STD_NL::has_infinity, ETL_NL::has_infinity); From 0744ee698901a117be618142a9a8e1fe00a1319c Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 10 Dec 2025 08:22:45 +0000 Subject: [PATCH 029/298] Added type_traits to test_memory --- test/test_memory.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test_memory.cpp b/test/test_memory.cpp index 1b88c8a5..8fc7e628 100644 --- a/test/test_memory.cpp +++ b/test/test_memory.cpp @@ -43,6 +43,7 @@ SOFTWARE. #include #include #include +#include namespace { From 558c04b0a0d6714a319e99f50d89048e5686c9d2 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 10 Dec 2025 18:35:45 +0000 Subject: [PATCH 030/298] Added for C++23 clang --- test/test_murmur3.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test_murmur3.cpp b/test/test_murmur3.cpp index 5a6da403..24a91dd3 100644 --- a/test/test_murmur3.cpp +++ b/test/test_murmur3.cpp @@ -33,6 +33,7 @@ SOFTWARE. #include #include #include +#include #include #include From 8f3db74be87990c8cb420b3898c97380e99b19bf Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Sat, 13 Dec 2025 08:46:14 +0100 Subject: [PATCH 031/298] Various cleanup (#1238) * Fix typo for remainder in rounded_integral_division.h * Use etl::make_unsigned instead of std::make_unsigned * Fix divide_round_half_down and divide_round_half_odd --- include/etl/rounded_integral_division.h | 39 ++++++++++++++++--------- test/test_rounded_integral_division.cpp | 4 +-- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/include/etl/rounded_integral_division.h b/include/etl/rounded_integral_division.h index 417b3143..ea277db3 100644 --- a/include/etl/rounded_integral_division.h +++ b/include/etl/rounded_integral_division.h @@ -414,7 +414,7 @@ namespace etl const T quotient = numerator / denominator; // Work with magnitudes in unsigned form (avoids abs() overflow) - typedef typename std::make_unsigned::type utype; + typedef typename etl::make_unsigned::type utype; utype abs_remainder = remainder < 0 ? utype(0) - utype(remainder) : utype(remainder); utype abs_denominator = denominator < 0 ? utype(0) - utype(denominator) : utype(denominator); @@ -519,16 +519,18 @@ namespace etl T>::type divide_round_half_down(T numerator, T denominator) ETL_NOEXCEPT { - const T quotient = numerator / denominator; - const T remainder = numerator % denominator; - const T abs_denominator = etl::absolute(denominator); - const T abs_remainderainder = etl::absolute(remainder); + const T quotient = numerator / denominator; + const T remainder = numerator % denominator; + + typedef typename etl::make_unsigned::type utype; + const utype abs_denominator = etl::absolute_unsigned(denominator); + const utype abs_remainder = etl::absolute_unsigned(remainder); // Direction: +1 if result should be more positive, -1 if more negative - const T direction = ((numerator >= 0) == (denominator >= 0)) ? 1 : -1; + const T direction = private_rounded_integral_division::are_same_sign(numerator, denominator) ? 1 : -1; // Only round away from zero if remainder is strictly greater than half the divisor - return abs_remainderainder > (abs_denominator / 2) ? quotient + direction : quotient; + return abs_remainder > (abs_denominator / 2U) ? quotient + direction : quotient; } //*************************************************************************** @@ -730,17 +732,26 @@ namespace etl T>::type divide_round_half_odd(T numerator, T denominator) ETL_NOEXCEPT { - const T quotient = numerator / denominator; - const T remainder = numerator % denominator; - const T abs_denominator = etl::absolute(denominator); - const T abs_remainderainder = etl::absolute(remainder); - const T direction = ((numerator >= 0) == (denominator >= 0)) ? 1 : -1; + const T quotient = numerator / denominator; + const T remainder = numerator % denominator; - if ((abs_remainderainder * 2) < abs_denominator) + typedef typename etl::make_unsigned::type utype; + const utype abs_denominator = etl::absolute_unsigned(denominator); + const utype abs_remainder = etl::absolute_unsigned(remainder); + const utype half = abs_denominator / 2U; + const T direction = private_rounded_integral_division::are_same_sign(numerator, denominator) ? 1 : -1; + + // Odd divisor => no exact-half case; 'half' is floor(abs_denominator/2). + if ((abs_denominator & 1U) != 0U) + { + return (abs_remainder > half) ? quotient + direction : quotient; + } + + if (abs_remainder < half) { return quotient; } - else if ((abs_remainderainder * 2) > abs_denominator) + else if (abs_remainder > half) { return quotient + direction; } diff --git a/test/test_rounded_integral_division.cpp b/test/test_rounded_integral_division.cpp index dc91390b..67cc28b9 100644 --- a/test/test_rounded_integral_division.cpp +++ b/test/test_rounded_integral_division.cpp @@ -624,7 +624,7 @@ namespace CHECK_EQUAL(std::numeric_limits::max(), etl::divide_round_half_down(std::numeric_limits::max(), int32_t(1))); CHECK_EQUAL(int32_t(0), etl::divide_round_half_down(int32_t(1), std::numeric_limits::max())); CHECK_EQUAL(std::numeric_limits::min(), etl::divide_round_half_down(std::numeric_limits::min(), int32_t(1))); - CHECK_EQUAL(int32_t(-1), etl::divide_round_half_down(int32_t(1), std::numeric_limits::min())); + CHECK_EQUAL(int32_t(0), etl::divide_round_half_down(int32_t(1), std::numeric_limits::min())); } //************************************************************************* @@ -840,7 +840,7 @@ namespace CHECK_EQUAL(std::numeric_limits::max(), etl::divide_round_half_odd(std::numeric_limits::max(), int32_t(1))); CHECK_EQUAL(int32_t(0), etl::divide_round_half_odd(int32_t(1), std::numeric_limits::max())); CHECK_EQUAL(std::numeric_limits::min(), etl::divide_round_half_odd(std::numeric_limits::min(), int32_t(1))); - CHECK_EQUAL(int32_t(-1), etl::divide_round_half_odd(int32_t(1), std::numeric_limits::min())); + CHECK_EQUAL(int32_t(0), etl::divide_round_half_odd(int32_t(1), std::numeric_limits::min())); } //************************************************************************* From d884719098fb2ce1c284771a3a5c0ba2469c41d2 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 16 Dec 2025 09:15:26 +0000 Subject: [PATCH 032/298] Fixed all 'extra semicolon' warnings --- include/etl/atomic/atomic_gcc_sync.h | 8 +- include/etl/basic_string.h | 2 +- include/etl/bit.h | 2 +- include/etl/buffer_descriptors.h | 2 +- include/etl/byte.h | 2 +- include/etl/flat_map.h | 4 +- include/etl/intrusive_forward_list.h | 2 +- include/etl/intrusive_list.h | 4 +- include/etl/list.h | 2 +- include/etl/multimap.h | 4 +- include/etl/multiset.h | 4 +- include/etl/private/bitset_new.h | 4 +- include/etl/private/variant_legacy.h | 56 +- .../etl/private/variant_select_do_operator.h | 60 +- .../etl/private/variant_select_do_visitor.h | 60 +- include/etl/queue_lockable.h | 6 +- include/etl/queue_spsc_locked.h | 2 +- include/etl/reference_counted_object.h | 2 +- include/etl/rescale.h | 2 +- include/etl/set.h | 4 +- include/etl/to_arithmetic.h | 6 +- test/CMakeLists.txt | 6 + test/etl_profile.h | 2 +- test/murmurhash3.cpp | 6 +- test/syntax_check/CMakeLists.txt | 14 + test/test_algorithm.cpp | 2 +- test/test_alignment.cpp | 2 +- test/test_array.cpp | 2 +- test/test_array_view.cpp | 2 +- test/test_array_wrapper.cpp | 2 +- test/test_atomic.cpp | 6 +- test/test_base64_RFC2152_decoder.cpp | 2 +- test/test_base64_RFC2152_encoder.cpp | 2 +- test/test_base64_RFC3501_decoder.cpp | 2 +- test/test_base64_RFC3501_encoder.cpp | 2 +- ...64_RFC4648_URL_decoder_with_no_padding.cpp | 2 +- ...ase64_RFC4648_URL_decoder_with_padding.cpp | 2 +- ...64_RFC4648_URL_encoder_with_no_padding.cpp | 2 +- ...ase64_RFC4648_URL_encoder_with_padding.cpp | 2 +- ...base64_RFC4648_decoder_with_no_padding.cpp | 2 +- ...st_base64_RFC4648_decoder_with_padding.cpp | 2 +- ...base64_RFC4648_encoder_with_no_padding.cpp | 2 +- ...st_base64_RFC4648_encoder_with_padding.cpp | 2 +- test/test_binary.cpp | 2 +- test/test_bip_buffer_spsc_atomic.cpp | 2 +- test/test_bit.cpp | 2 +- test/test_bit_stream.cpp | 2 +- test/test_bit_stream_reader_big_endian.cpp | 2 +- test/test_bit_stream_reader_little_endian.cpp | 2 +- test/test_bit_stream_writer_big_endian.cpp | 2 +- test/test_bit_stream_writer_little_endian.cpp | 2 +- test/test_bitset_legacy.cpp | 2 +- test/test_bitset_new_comparisons.cpp | 2 +- test/test_bitset_new_default_element_type.cpp | 2 +- ...itset_new_explicit_single_element_type.cpp | 2 +- ...st_bitset_new_ext_default_element_type.cpp | 2 +- ...t_new_ext_explicit_single_element_type.cpp | 2 +- test/test_bloom_filter.cpp | 2 +- test/test_bresenham_line.cpp | 2 +- test/test_bsd_checksum.cpp | 2 +- test/test_buffer_descriptors.cpp | 2 +- test/test_byte_stream.cpp | 2 +- test/test_callback_service.cpp | 2 +- test/test_callback_timer.cpp | 2 +- test/test_callback_timer_atomic.cpp | 2 +- test/test_callback_timer_deferred_locked.cpp | 2 +- test/test_callback_timer_interrupt.cpp | 2 +- test/test_callback_timer_locked.cpp | 2 +- test/test_char_traits.cpp | 2 +- test/test_checksum.cpp | 2 +- test/test_chrono_clocks.cpp | 2 +- test/test_chrono_day.cpp | 2 +- test/test_chrono_duration.cpp | 2 +- test/test_chrono_hh_mm_ss.cpp | 2 +- test/test_chrono_literals.cpp | 2 +- test/test_chrono_month.cpp | 2 +- test/test_chrono_month_day.cpp | 3 +- test/test_chrono_month_day_last.cpp | 2 +- test/test_chrono_month_weekday.cpp | 2 +- test/test_chrono_month_weekday_last.cpp | 2 +- test/test_chrono_operators.cpp | 2 +- test/test_chrono_time_point.cpp | 2 +- test/test_chrono_weekday.cpp | 2 +- test/test_chrono_weekday_indexed.cpp | 2 +- test/test_chrono_weekday_last.cpp | 2 +- test/test_chrono_year.cpp | 2 +- test/test_chrono_year_month.cpp | 2 +- test/test_chrono_year_month_day.cpp | 2 +- test/test_chrono_year_month_day_last.cpp | 2 +- test/test_chrono_year_month_weekday.cpp | 2 +- test/test_chrono_year_month_weekday_last.cpp | 2 +- test/test_circular_buffer.cpp | 7 +- test/test_circular_buffer_external_buffer.cpp | 2 +- test/test_circular_iterator.cpp | 2 +- test/test_closure.cpp | 2 +- test/test_closure_constexpr.cpp | 2 +- test/test_compare.cpp | 2 +- test/test_const_map.cpp | 6 +- test/test_const_map_constexpr.cpp | 6 +- test/test_const_map_ext.cpp | 6 +- test/test_const_map_ext_constexpr.cpp | 6 +- test/test_const_multimap.cpp | 6 +- test/test_const_multimap_constexpr.cpp | 6 +- test/test_const_multimap_ext.cpp | 6 +- test/test_const_multimap_ext_constexpr.cpp | 6 +- test/test_const_multiset.cpp | 6 +- test/test_const_multiset_constexpr.cpp | 6 +- test/test_const_multiset_ext.cpp | 6 +- test/test_const_multiset_ext_constexpr.cpp | 6 +- test/test_const_set.cpp | 4 +- test/test_const_set_constexpr.cpp | 10 +- test/test_const_set_ext.cpp | 6 +- test/test_const_set_ext_constexpr.cpp | 6 +- test/test_constant.cpp | 2 +- test/test_container.cpp | 2 +- test/test_correlation.cpp | 2 +- test/test_covariance.cpp | 2 +- test/test_crc1.cpp | 2 +- test/test_crc16.cpp | 2 +- test/test_crc16_a.cpp | 2 +- test/test_crc16_arc.cpp | 2 +- test/test_crc16_aug_ccitt.cpp | 2 +- test/test_crc16_buypass.cpp | 2 +- test/test_crc16_ccitt.cpp | 2 +- test/test_crc16_cdma2000.cpp | 2 +- test/test_crc16_dds110.cpp | 2 +- test/test_crc16_dectr.cpp | 2 +- test/test_crc16_dectx.cpp | 2 +- test/test_crc16_dnp.cpp | 2 +- test/test_crc16_en13757.cpp | 2 +- test/test_crc16_genibus.cpp | 2 +- test/test_crc16_kermit.cpp | 2 +- test/test_crc16_m17.cpp | 2 +- test/test_crc16_maxim.cpp | 2 +- test/test_crc16_mcrf4xx.cpp | 2 +- test/test_crc16_modbus.cpp | 2 +- test/test_crc16_opensafety_a.cpp | 2 +- test/test_crc16_opensafety_b.cpp | 2 +- test/test_crc16_profibus.cpp | 2 +- test/test_crc16_riello.cpp | 2 +- test/test_crc16_t10dif.cpp | 2 +- test/test_crc16_teledisk.cpp | 2 +- test/test_crc16_tms37157.cpp | 2 +- test/test_crc16_usb.cpp | 2 +- test/test_crc16_x25.cpp | 2 +- test/test_crc16_xmodem.cpp | 2 +- test/test_crc32.cpp | 2 +- test/test_crc32_bzip2.cpp | 2 +- test/test_crc32_c.cpp | 2 +- test/test_crc32_d.cpp | 2 +- test/test_crc32_jamcrc.cpp | 2 +- test/test_crc32_mpeg2.cpp | 2 +- test/test_crc32_posix.cpp | 2 +- test/test_crc32_q.cpp | 2 +- test/test_crc32_xfer.cpp | 2 +- test/test_crc64_ecma.cpp | 2 +- test/test_crc64_iso.cpp | 2 +- test/test_crc8_ccitt.cpp | 2 +- test/test_crc8_cdma2000.cpp | 2 +- test/test_crc8_darc.cpp | 2 +- test/test_crc8_dvbs2.cpp | 2 +- test/test_crc8_ebu.cpp | 2 +- test/test_crc8_icode.cpp | 2 +- test/test_crc8_itu.cpp | 2 +- test/test_crc8_j1850.cpp | 2 +- test/test_crc8_j1850_zero.cpp | 2 +- test/test_crc8_maxim.cpp | 2 +- test/test_crc8_nrsc5.cpp | 2 +- test/test_crc8_opensafety.cpp | 2 +- test/test_crc8_rohc.cpp | 2 +- test/test_crc8_wcdma.cpp | 2 +- test/test_cyclic_value.cpp | 2 +- test/test_debounce.cpp | 2 +- test/test_delegate.cpp | 6 +- test/test_delegate_cpp03.cpp | 4 +- test/test_delegate_observable.cpp | 2 +- test/test_delegate_service.cpp | 2 +- test/test_delegate_service_compile_time.cpp | 2 +- test/test_delegate_service_cpp03.cpp | 2 +- test/test_deque.cpp | 2 +- test/test_endian.cpp | 2 +- test/test_enum_type.cpp | 2 +- test/test_error_handler.cpp | 2 +- test/test_etl_assert.cpp | 2 +- test/test_etl_traits.cpp | 2 +- test/test_exception.cpp | 2 +- test/test_expected.cpp | 2 +- test/test_fixed_iterator.cpp | 2 +- test/test_flags.cpp | 2 +- test/test_flat_map.cpp | 2 +- test/test_flat_multimap.cpp | 2 +- test/test_flat_multiset.cpp | 2 +- test/test_flat_set.cpp | 2 +- test/test_fnv_1.cpp | 2 +- test/test_format_spec.cpp | 2 +- test/test_forward_list.cpp | 2 +- test/test_forward_list_shared_pool.cpp | 2 +- test/test_fsm.cpp | 2 +- test/test_function.cpp | 2 +- test/test_function_traits.cpp | 4 +- test/test_functional.cpp | 2 +- test/test_gamma.cpp | 2 +- test/test_hash.cpp | 2 +- test/test_hfsm.cpp | 2 +- ...t_hfsm_recurse_to_inner_state_on_start.cpp | 2 +- test/test_histogram.cpp | 2 +- test/test_indirect_vector.cpp | 2 +- test/test_indirect_vector_external_buffer.cpp | 2 +- test/test_instance_count.cpp | 2 +- test/test_integral_limits.cpp | 2 +- test/test_intrusive_forward_list.cpp | 2 +- test/test_intrusive_links.cpp | 2 +- test/test_intrusive_list.cpp | 2 +- test/test_intrusive_queue.cpp | 2 +- test/test_intrusive_stack.cpp | 2 +- test/test_invert.cpp | 2 +- test/test_io_port.cpp | 2 +- test/test_iterator.cpp | 2 +- test/test_jenkins.cpp | 2 +- test/test_largest.cpp | 2 +- test/test_limiter.cpp | 2 +- test/test_limits.cpp | 2 +- test/test_list.cpp | 2 +- test/test_list_shared_pool.cpp | 2 +- test/test_macros.cpp | 2 +- test/test_make_string.cpp | 8 +- test/test_map.cpp | 2 +- test/test_math.cpp | 2 +- test/test_math_functions.cpp | 2 +- test/test_mean.cpp | 2 +- test/test_mem_cast.cpp | 2 +- test/test_mem_cast_ptr.cpp | 2 +- test/test_memory.cpp | 4 +- test/test_message.cpp | 2 +- test/test_message_broker.cpp | 2 +- test/test_message_bus.cpp | 2 +- test/test_message_packet.cpp | 2 +- test/test_message_router.cpp | 2 +- test/test_message_router_registry.cpp | 2 +- test/test_message_timer.cpp | 2 +- test/test_message_timer_atomic.cpp | 2 +- test/test_message_timer_interrupt.cpp | 2 +- test/test_message_timer_locked.cpp | 2 +- test/test_multi_array.cpp | 2 +- test/test_multi_range.cpp | 2 +- test/test_multi_span.cpp | 2 +- test/test_multi_vector.cpp | 2 +- test/test_multimap.cpp | 2 +- test/test_multiset.cpp | 2 +- test/test_murmur3.cpp | 2 +- test/test_not_null_pointer.cpp | 2 +- test/test_not_null_pointer_constexpr.cpp | 2 +- test/test_numeric.cpp | 2 +- test/test_optional.cpp | 2 +- test/test_overload.cpp | 2 +- test/test_parameter_pack.cpp | 2 +- test/test_parameter_type.cpp | 2 +- test/test_parity_checksum.cpp | 2 +- test/test_pearson.cpp | 2 +- test/test_pool.cpp | 794 +++++----- test/test_priority_queue.cpp | 2 +- test/test_pseudo_moving_average.cpp | 2 +- test/test_quantize.cpp | 2 +- test/test_queue.cpp | 2 +- test/test_queue_lockable.cpp | 2 +- test/test_queue_lockable_small.cpp | 2 +- test/test_queue_memory_model_small.cpp | 2 +- test/test_queue_mpmc_mutex.cpp | 8 +- test/test_queue_mpmc_mutex_small.cpp | 8 +- test/test_queue_spsc_atomic.cpp | 2 +- test/test_queue_spsc_atomic_small.cpp | 2 +- test/test_queue_spsc_isr.cpp | 2 +- test/test_queue_spsc_isr_small.cpp | 2 +- test/test_queue_spsc_locked.cpp | 2 +- test/test_queue_spsc_locked_small.cpp | 2 +- test/test_random.cpp | 3 +- test/test_ratio.cpp | 3 +- test/test_reference_flat_map.cpp | 2 +- test/test_reference_flat_multimap.cpp | 2 +- test/test_reference_flat_multiset.cpp | 2 +- test/test_reference_flat_set.cpp | 2 +- test/test_rescale.cpp | 2 +- test/test_result.cpp | 2 +- test/test_rms.cpp | 2 +- test/test_rounded_integral_division.cpp | 2 +- test/test_scaled_rounding.cpp | 2 +- test/test_set.cpp | 2 +- test/test_smallest.cpp | 2 +- test/test_span_dynamic_extent.cpp | 2 +- test/test_span_fixed_extent.cpp | 2 +- test/test_stack.cpp | 2 +- test/test_standard_deviation.cpp | 2 +- test/test_state_chart.cpp | 2 +- test/test_state_chart_compile_time.cpp | 2 +- ...chart_compile_time_with_data_parameter.cpp | 2 +- test/test_state_chart_with_data_parameter.cpp | 2 +- ...state_chart_with_rvalue_data_parameter.cpp | 2 +- test/test_string_char.cpp | 2 +- test/test_string_char_external_buffer.cpp | 2 +- test/test_string_stream.cpp | 2 +- test/test_string_stream_u16.cpp | 2 +- test/test_string_stream_u32.cpp | 2 +- test/test_string_stream_u8.cpp | 2 +- test/test_string_stream_wchar_t.cpp | 2 +- test/test_string_u16.cpp | 2 +- test/test_string_u16_external_buffer.cpp | 2 +- test/test_string_u32.cpp | 2 +- test/test_string_u32_external_buffer.cpp | 2 +- test/test_string_u8.cpp | 2 +- test/test_string_u8_external_buffer.cpp | 2 +- test/test_string_utilities.cpp | 2 +- test/test_string_utilities_std.cpp | 2 +- test/test_string_utilities_std_u16.cpp | 2 +- test/test_string_utilities_std_u32.cpp | 2 +- test/test_string_utilities_std_u8.cpp | 2 +- test/test_string_utilities_std_wchar_t.cpp | 2 +- test/test_string_utilities_u16.cpp | 2 +- test/test_string_utilities_u32.cpp | 2 +- test/test_string_utilities_u8.cpp | 2 +- test/test_string_utilities_wchar_t.cpp | 2 +- test/test_string_view.cpp | 2 +- test/test_string_wchar_t.cpp | 2 +- test/test_string_wchar_t_external_buffer.cpp | 2 +- test/test_task_scheduler.cpp | 2 +- test/test_threshold.cpp | 2 +- test/test_to_string.cpp | 2 +- test/test_to_u16string.cpp | 2 +- test/test_to_u32string.cpp | 2 +- test/test_to_u8string.cpp | 2 +- test/test_to_wstring.cpp | 2 +- test/test_type_def.cpp | 2 +- test/test_type_list.cpp | 2 +- test/test_type_lookup.cpp | 2 +- test/test_type_select.cpp | 2 +- test/test_type_traits.cpp | 1304 ++++++++--------- test/test_unaligned_type.cpp | 2 +- test/test_unaligned_type_ext.cpp | 2 +- test/test_uncopyable.cpp | 2 +- test/test_unordered_map.cpp | 2 +- test/test_unordered_multimap.cpp | 2 +- test/test_unordered_multiset.cpp | 2 +- test/test_unordered_set.cpp | 2 +- test/test_user_type.cpp | 14 +- test/test_utility.cpp | 56 +- test/test_variance.cpp | 2 +- test/test_variant_legacy.cpp | 2 +- test/test_variant_pool.cpp | 2 +- test/test_variant_pool_external_buffer.cpp | 2 +- test/test_variant_variadic.cpp | 2 +- test/test_vector.cpp | 2 +- test/test_vector_external_buffer.cpp | 2 +- test/test_vector_non_trivial.cpp | 2 +- test/test_vector_pointer.cpp | 2 +- test/test_vector_pointer_external_buffer.cpp | 2 +- test/test_xor_checksum.cpp | 2 +- test/test_xor_rotate_checksum.cpp | 2 +- test/vs2022/etl.vcxproj.filters | 6 +- 357 files changed, 1609 insertions(+), 1591 deletions(-) diff --git a/include/etl/atomic/atomic_gcc_sync.h b/include/etl/atomic/atomic_gcc_sync.h index 67c7c8bf..de7b8d5a 100644 --- a/include/etl/atomic/atomic_gcc_sync.h +++ b/include/etl/atomic/atomic_gcc_sync.h @@ -75,8 +75,8 @@ namespace etl { #if defined(ETL_USE_ATOMIC_BUILTINS) -#define ETL_BUILTIN_LOCK while (__atomic_test_and_set(&flag, etl::memory_order_seq_cst)) {} -#define ETL_BUILTIN_UNLOCK __atomic_clear(&flag, etl::memory_order_seq_cst); +#define ETL_BUILTIN_LOCK do { while (__atomic_test_and_set(&flag, etl::memory_order_seq_cst)) {} } while (0) +#define ETL_BUILTIN_UNLOCK do { __atomic_clear(&flag, etl::memory_order_seq_cst); } while (0) //*************************************************************************** // Atomic type for pre C++11 GCC compilers that support the builtin '__atomic' functions. @@ -1021,8 +1021,8 @@ namespace etl #if defined(ETL_USE_SYNC_BUILTINS) -#define ETL_BUILTIN_LOCK while (__sync_lock_test_and_set(&flag, 1U)) {} -#define ETL_BUILTIN_UNLOCK __sync_lock_release(&flag); +#define ETL_BUILTIN_LOCK do { while (__sync_lock_test_and_set(&flag, 1U)) {} } while(0) +#define ETL_BUILTIN_UNLOCK do { __sync_lock_release(&flag); } while(0) //*************************************************************************** // Atomic type for pre C++11 GCC compilers that support the builtin '__sync' functions. diff --git a/include/etl/basic_string.h b/include/etl/basic_string.h index 9a39b078..d98adf1b 100644 --- a/include/etl/basic_string.h +++ b/include/etl/basic_string.h @@ -1015,7 +1015,7 @@ namespace etl ETL_ASSERT_FAIL(ETL_ERROR(string_truncation)); #endif #endif - return to_iterator(position);; + return to_iterator(position); } // Fills the string to the end? diff --git a/include/etl/bit.h b/include/etl/bit.h index eb7d5817..d8b6c2e6 100644 --- a/include/etl/bit.h +++ b/include/etl/bit.h @@ -138,7 +138,7 @@ namespace etl typename etl::enable_if::value, int>::type countr_one(T value) ETL_NOEXCEPT { - return etl::count_trailing_ones(value);; + return etl::count_trailing_ones(value); } diff --git a/include/etl/buffer_descriptors.h b/include/etl/buffer_descriptors.h index b34e223b..02ff32a9 100644 --- a/include/etl/buffer_descriptors.h +++ b/include/etl/buffer_descriptors.h @@ -147,7 +147,7 @@ namespace etl //********************************* void allocate() { - pdesc_item->in_use = true;; + pdesc_item->in_use = true; } /// The pointer to the buffer descriptor. diff --git a/include/etl/byte.h b/include/etl/byte.h index 51528288..ae10af77 100644 --- a/include/etl/byte.h +++ b/include/etl/byte.h @@ -76,7 +76,7 @@ namespace etl typename etl::enable_if::value, etl::byte&>::type operator <<=(etl::byte& b, TInteger shift) ETL_NOEXCEPT { - return b = b << shift;; + return b = b << shift; } //************************************************************************* diff --git a/include/etl/flat_map.h b/include/etl/flat_map.h index c57856a8..0bb1d552 100644 --- a/include/etl/flat_map.h +++ b/include/etl/flat_map.h @@ -606,7 +606,7 @@ namespace etl i_element->~value_type(); storage.release(etl::addressof(*i_element)); refmap_t::erase(i_element); - ETL_DECREMENT_DEBUG_COUNT;; + ETL_DECREMENT_DEBUG_COUNT; return 1; } } @@ -627,7 +627,7 @@ namespace etl i_element->~value_type(); storage.release(etl::addressof(*i_element)); refmap_t::erase(i_element); - ETL_DECREMENT_DEBUG_COUNT;; + ETL_DECREMENT_DEBUG_COUNT; return 1; } } diff --git a/include/etl/intrusive_forward_list.h b/include/etl/intrusive_forward_list.h index 262c8052..210dd542 100644 --- a/include/etl/intrusive_forward_list.h +++ b/include/etl/intrusive_forward_list.h @@ -1165,7 +1165,7 @@ namespace etl link_type* before = &this->start; link_type* before_next = get_next(before); - link_type* terminal = &this->terminator;; + link_type* terminal = &this->terminator; while ((before->etl_next != terminal) && (other_begin != other_terminal)) { diff --git a/include/etl/intrusive_list.h b/include/etl/intrusive_list.h index 36f3966d..7a6d057b 100644 --- a/include/etl/intrusive_list.h +++ b/include/etl/intrusive_list.h @@ -259,7 +259,7 @@ namespace etl //************************************************************************* bool contains_node(const link_type& search_link) const { - return is_link_in_list(&search_link);; + return is_link_in_list(&search_link); } //************************************************************************* @@ -268,7 +268,7 @@ namespace etl //************************************************************************* bool contains_node(const link_type* search_link) const { - return is_link_in_list(search_link);; + return is_link_in_list(search_link); } protected: diff --git a/include/etl/list.h b/include/etl/list.h index ea070c0e..63ab9fc3 100644 --- a/include/etl/list.h +++ b/include/etl/list.h @@ -1839,7 +1839,7 @@ namespace etl { ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool)); p_node_pool->release_all(); - ETL_RESET_DEBUG_COUNT;; + ETL_RESET_DEBUG_COUNT; } else { diff --git a/include/etl/multimap.h b/include/etl/multimap.h index 59f0d001..f585e45d 100644 --- a/include/etl/multimap.h +++ b/include/etl/multimap.h @@ -1490,7 +1490,7 @@ namespace etl key_compare key_comp() const { return kcompare; - }; + } //************************************************************************* /// How to compare two value elements. @@ -1498,7 +1498,7 @@ namespace etl value_compare value_comp() const { return vcompare; - }; + } //************************************************************************* /// Check if the map contains the key. diff --git a/include/etl/multiset.h b/include/etl/multiset.h index a44fe751..de020d28 100644 --- a/include/etl/multiset.h +++ b/include/etl/multiset.h @@ -1478,7 +1478,7 @@ namespace etl key_compare key_comp() const { return compare; - }; + } //************************************************************************* /// How to compare two value elements. @@ -1486,7 +1486,7 @@ namespace etl value_compare value_comp() const { return compare; - }; + } //************************************************************************* /// Check if the set contains the key. diff --git a/include/etl/private/bitset_new.h b/include/etl/private/bitset_new.h index e7673f4b..6d67a390 100644 --- a/include/etl/private/bitset_new.h +++ b/include/etl/private/bitset_new.h @@ -1231,7 +1231,7 @@ namespace etl void reset_position(pointer pbuffer, size_t position) ETL_NOEXCEPT { - const size_t index = position >> etl::log2::value;; + const size_t index = position >> etl::log2::value; const element_type bit = element_type(1) << (position & (Bits_Per_Element - 1)); pbuffer[index] &= ~bit; @@ -1454,7 +1454,7 @@ namespace etl void flip_position(pointer pbuffer, size_t position) ETL_NOEXCEPT { - const size_t index = position >> etl::log2::value;; + const size_t index = position >> etl::log2::value; const element_type bit = element_type(1) << (position & (Bits_Per_Element - 1)); pbuffer[index] ^= bit; diff --git a/include/etl/private/variant_legacy.h b/include/etl/private/variant_legacy.h index a53e3602..e6c01156 100644 --- a/include/etl/private/variant_legacy.h +++ b/include/etl/private/variant_legacy.h @@ -285,7 +285,7 @@ namespace etl private: - void read(no_type8&) {}; + void read(no_type8&) {} }; //************************************************************************* @@ -311,8 +311,8 @@ namespace etl private: - void read(no_type7&) {}; - void read(no_type8&) {}; + void read(no_type7&) {} + void read(no_type8&) {} }; //************************************************************************* @@ -337,9 +337,9 @@ namespace etl private: - void read(no_type6&) {}; - void read(no_type7&) {}; - void read(no_type8&) {}; + void read(no_type6&) {} + void read(no_type7&) {} + void read(no_type8&) {} }; //************************************************************************* @@ -363,10 +363,10 @@ namespace etl private: - void read(no_type5&) {}; - void read(no_type6&) {}; - void read(no_type7&) {}; - void read(no_type8&) {}; + void read(no_type5&) {} + void read(no_type6&) {} + void read(no_type7&) {} + void read(no_type8&) {} }; //************************************************************************* @@ -389,11 +389,11 @@ namespace etl private: - void read(no_type4&) {}; - void read(no_type5&) {}; - void read(no_type6&) {}; - void read(no_type7&) {}; - void read(no_type8&) {}; + void read(no_type4&) {} + void read(no_type5&) {} + void read(no_type6&) {} + void read(no_type7&) {} + void read(no_type8&) {} }; //************************************************************************* @@ -415,12 +415,12 @@ namespace etl private: - void read(no_type3&) {}; - void read(no_type4&) {}; - void read(no_type5&) {}; - void read(no_type6&) {}; - void read(no_type7&) {}; - void read(no_type8&) {}; + void read(no_type3&) {} + void read(no_type4&) {} + void read(no_type5&) {} + void read(no_type6&) {} + void read(no_type7&) {} + void read(no_type8&) {} }; //************************************************************************* @@ -441,13 +441,13 @@ namespace etl private: - void read(no_type2&) {}; - void read(no_type3&) {}; - void read(no_type4&) {}; - void read(no_type5&) {}; - void read(no_type6&) {}; - void read(no_type7&) {}; - void read(no_type8&) {}; + void read(no_type2&) {} + void read(no_type3&) {} + void read(no_type4&) {} + void read(no_type5&) {} + void read(no_type6&) {} + void read(no_type7&) {} + void read(no_type8&) {} }; //*************************************************************************** diff --git a/include/etl/private/variant_select_do_operator.h b/include/etl/private/variant_select_do_operator.h index c4b125d0..d16f1fe3 100644 --- a/include/etl/private/variant_select_do_operator.h +++ b/include/etl/private/variant_select_do_operator.h @@ -84,7 +84,7 @@ namespace private_variant case 2: { visitor(etl::get<2>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -102,7 +102,7 @@ namespace private_variant case 3: { visitor(etl::get<3>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -121,7 +121,7 @@ namespace private_variant case 4: { visitor(etl::get<4>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -141,7 +141,7 @@ namespace private_variant case 5: { visitor(etl::get<5>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -162,7 +162,7 @@ namespace private_variant case 6: { visitor(etl::get<6>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -184,7 +184,7 @@ namespace private_variant case 7: { visitor(etl::get<7>(the_variant)); break; } default: break; } - }; + } }; #if !defined(ETL_VARIANT_CPP11_MAX_8_TYPES) //*************************************************************************** @@ -207,7 +207,7 @@ namespace private_variant case 8: { visitor(etl::get<8>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -231,7 +231,7 @@ namespace private_variant case 9: { visitor(etl::get<9>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -256,7 +256,7 @@ namespace private_variant case 10: { visitor(etl::get<10>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -282,7 +282,7 @@ namespace private_variant case 11: { visitor(etl::get<11>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -309,7 +309,7 @@ namespace private_variant case 12: { visitor(etl::get<12>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -337,7 +337,7 @@ namespace private_variant case 13: { visitor(etl::get<13>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -366,7 +366,7 @@ namespace private_variant case 14: { visitor(etl::get<14>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -396,7 +396,7 @@ namespace private_variant case 15: { visitor(etl::get<15>(the_variant)); break; } default: break; } - }; + } }; #if !defined(ETL_VARIANT_CPP11_MAX_16_TYPES) //*************************************************************************** @@ -427,7 +427,7 @@ namespace private_variant case 16: { visitor(etl::get<16>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -459,7 +459,7 @@ namespace private_variant case 17: { visitor(etl::get<17>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -492,7 +492,7 @@ namespace private_variant case 18: { visitor(etl::get<18>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -526,7 +526,7 @@ namespace private_variant case 19: { visitor(etl::get<19>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -561,7 +561,7 @@ namespace private_variant case 20: { visitor(etl::get<20>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -597,7 +597,7 @@ namespace private_variant case 21: { visitor(etl::get<21>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -634,7 +634,7 @@ namespace private_variant case 22: { visitor(etl::get<22>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -672,7 +672,7 @@ namespace private_variant case 23: { visitor(etl::get<23>(the_variant)); break; } default: break; } - }; + } }; #if !defined(ETL_VARIANT_CPP11_MAX_24_TYPES) //*************************************************************************** @@ -711,7 +711,7 @@ namespace private_variant case 24: { visitor(etl::get<24>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -751,7 +751,7 @@ namespace private_variant case 25: { visitor(etl::get<25>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -792,7 +792,7 @@ namespace private_variant case 26: { visitor(etl::get<26>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -834,7 +834,7 @@ namespace private_variant case 27: { visitor(etl::get<27>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -877,7 +877,7 @@ namespace private_variant case 28: { visitor(etl::get<28>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -921,7 +921,7 @@ namespace private_variant case 29: { visitor(etl::get<29>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -966,7 +966,7 @@ namespace private_variant case 30: { visitor(etl::get<30>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -1012,7 +1012,7 @@ namespace private_variant case 31: { visitor(etl::get<31>(the_variant)); break; } default: break; } - }; + } }; #endif #endif diff --git a/include/etl/private/variant_select_do_visitor.h b/include/etl/private/variant_select_do_visitor.h index b6e5bc50..e1a5bbbd 100644 --- a/include/etl/private/variant_select_do_visitor.h +++ b/include/etl/private/variant_select_do_visitor.h @@ -84,7 +84,7 @@ namespace private_variant case 2: { visitor.visit(etl::get<2>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -102,7 +102,7 @@ namespace private_variant case 3: { visitor.visit(etl::get<3>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -121,7 +121,7 @@ namespace private_variant case 4: { visitor.visit(etl::get<4>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -141,7 +141,7 @@ namespace private_variant case 5: { visitor.visit(etl::get<5>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -162,7 +162,7 @@ namespace private_variant case 6: { visitor.visit(etl::get<6>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -184,7 +184,7 @@ namespace private_variant case 7: { visitor.visit(etl::get<7>(the_variant)); break; } default: break; } - }; + } }; #if !defined(ETL_VARIANT_CPP11_MAX_8_TYPES) //*************************************************************************** @@ -207,7 +207,7 @@ namespace private_variant case 8: { visitor.visit(etl::get<8>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -231,7 +231,7 @@ namespace private_variant case 9: { visitor.visit(etl::get<9>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -256,7 +256,7 @@ namespace private_variant case 10: { visitor.visit(etl::get<10>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -282,7 +282,7 @@ namespace private_variant case 11: { visitor.visit(etl::get<11>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -309,7 +309,7 @@ namespace private_variant case 12: { visitor.visit(etl::get<12>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -337,7 +337,7 @@ namespace private_variant case 13: { visitor.visit(etl::get<13>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -366,7 +366,7 @@ namespace private_variant case 14: { visitor.visit(etl::get<14>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -396,7 +396,7 @@ namespace private_variant case 15: { visitor.visit(etl::get<15>(the_variant)); break; } default: break; } - }; + } }; #if !defined(ETL_VARIANT_CPP11_MAX_16_TYPES) //*************************************************************************** @@ -427,7 +427,7 @@ namespace private_variant case 16: { visitor.visit(etl::get<16>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -459,7 +459,7 @@ namespace private_variant case 17: { visitor.visit(etl::get<17>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -492,7 +492,7 @@ namespace private_variant case 18: { visitor.visit(etl::get<18>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -526,7 +526,7 @@ namespace private_variant case 19: { visitor.visit(etl::get<19>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -561,7 +561,7 @@ namespace private_variant case 20: { visitor.visit(etl::get<20>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -597,7 +597,7 @@ namespace private_variant case 21: { visitor.visit(etl::get<21>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -634,7 +634,7 @@ namespace private_variant case 22: { visitor.visit(etl::get<22>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -672,7 +672,7 @@ namespace private_variant case 23: { visitor.visit(etl::get<23>(the_variant)); break; } default: break; } - }; + } }; #if !defined(ETL_VARIANT_CPP11_MAX_24_TYPES) //*************************************************************************** @@ -711,7 +711,7 @@ namespace private_variant case 24: { visitor.visit(etl::get<24>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -751,7 +751,7 @@ namespace private_variant case 25: { visitor.visit(etl::get<25>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -792,7 +792,7 @@ namespace private_variant case 26: { visitor.visit(etl::get<26>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -834,7 +834,7 @@ namespace private_variant case 27: { visitor.visit(etl::get<27>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -877,7 +877,7 @@ namespace private_variant case 28: { visitor.visit(etl::get<28>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -921,7 +921,7 @@ namespace private_variant case 29: { visitor.visit(etl::get<29>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -966,7 +966,7 @@ namespace private_variant case 30: { visitor.visit(etl::get<30>(the_variant)); break; } default: break; } - }; + } }; //*************************************************************************** @@ -1012,7 +1012,7 @@ namespace private_variant case 31: { visitor.visit(etl::get<31>(the_variant)); break; } default: break; } - }; + } }; #endif #endif diff --git a/include/etl/queue_lockable.h b/include/etl/queue_lockable.h index 75507a7a..7d467bf5 100644 --- a/include/etl/queue_lockable.h +++ b/include/etl/queue_lockable.h @@ -227,7 +227,7 @@ namespace etl //************************************************************************* bool full_implementation() const { - return (current_size == Max_Size);; + return (current_size == Max_Size); } //************************************************************************* @@ -781,7 +781,7 @@ namespace etl //************************************************************************* reference front_implementation() { - return p_buffer[this->read_index];; + return p_buffer[this->read_index]; } //************************************************************************* @@ -789,7 +789,7 @@ namespace etl //************************************************************************* const_reference front_implementation() const { - return p_buffer[this->read_index];; + return p_buffer[this->read_index]; } // Disable copy construction and assignment. diff --git a/include/etl/queue_spsc_locked.h b/include/etl/queue_spsc_locked.h index aa76cf09..ee53c5c6 100644 --- a/include/etl/queue_spsc_locked.h +++ b/include/etl/queue_spsc_locked.h @@ -406,7 +406,7 @@ namespace etl //************************************************************************* bool pop_from_unlocked(reference value) { - return pop_implementation(value);; + return pop_implementation(value); } //************************************************************************* diff --git a/include/etl/reference_counted_object.h b/include/etl/reference_counted_object.h index 198da27a..56b1278d 100644 --- a/include/etl/reference_counted_object.h +++ b/include/etl/reference_counted_object.h @@ -73,7 +73,7 @@ namespace etl { public: - virtual ~ireference_counter() {}; + virtual ~ireference_counter() {} virtual void set_reference_count(int32_t value) = 0; virtual void increment_reference_count() = 0; ETL_NODISCARD virtual int32_t decrement_reference_count() = 0; diff --git a/include/etl/rescale.h b/include/etl/rescale.h index 924542a5..394ed7c7 100644 --- a/include/etl/rescale.h +++ b/include/etl/rescale.h @@ -68,7 +68,7 @@ namespace etl //***************************************************************** TOutput operator ()(TInput value) const { - return TOutput(((value - input_min_value) * multiplier)) + output_min_value;; + return TOutput(((value - input_min_value) * multiplier)) + output_min_value; } private: diff --git a/include/etl/set.h b/include/etl/set.h index fa7d077a..dd4f208d 100644 --- a/include/etl/set.h +++ b/include/etl/set.h @@ -1355,7 +1355,7 @@ namespace etl key_compare key_comp() const { return compare; - }; + } //************************************************************************* /// How to compare two value elements. @@ -1363,7 +1363,7 @@ namespace etl value_compare value_comp() const { return compare; - }; + } //************************************************************************* /// Check if the set contains the key. diff --git a/include/etl/to_arithmetic.h b/include/etl/to_arithmetic.h index ffc8b9d5..a3fce142 100644 --- a/include/etl/to_arithmetic.h +++ b/include/etl/to_arithmetic.h @@ -844,7 +844,7 @@ namespace etl typename etl::enable_if::value, etl::to_arithmetic_result >::type to_arithmetic(const etl::ibasic_string& str, const etl::radix::value_type radix) { - return etl::to_arithmetic(etl::basic_string_view(str), radix);; + return etl::to_arithmetic(etl::basic_string_view(str), radix); } //*************************************************************************** @@ -856,7 +856,7 @@ namespace etl typename etl::enable_if::value, etl::to_arithmetic_result >::type to_arithmetic(const etl::ibasic_string& str) { - return etl::to_arithmetic(etl::basic_string_view(str), etl::radix::decimal);; + return etl::to_arithmetic(etl::basic_string_view(str), etl::radix::decimal); } //*************************************************************************** @@ -868,7 +868,7 @@ namespace etl typename etl::enable_if::value, etl::to_arithmetic_result >::type to_arithmetic(const etl::ibasic_string& str, const typename etl::private_basic_format_spec::base_spec& spec) { - return etl::to_arithmetic(etl::basic_string_view(str), spec);; + return etl::to_arithmetic(etl::basic_string_view(str), spec); } //*************************************************************************** diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 624f38d2..2afa0473 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -460,12 +460,14 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") PRIVATE -fno-omit-frame-pointer -fno-common +# -pedantic-errors -Wall -Wextra -Werror -Wfloat-equal -Wshadow -Wnull-dereference + -Wextra-semi -g ) endif () @@ -475,12 +477,16 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") PRIVATE -fno-omit-frame-pointer -fno-common +# -pedantic-errors -Wall -Wextra -Werror -Wfloat-equal -Wshadow -Wnull-dereference + -Wextra-semi + -Wextra-semi-stmt + -Wc++11-extra-semi -g ) endif () diff --git a/test/etl_profile.h b/test/etl_profile.h index a7c680ff..d29a1093 100644 --- a/test/etl_profile.h +++ b/test/etl_profile.h @@ -42,7 +42,7 @@ SOFTWARE. #define ETL_IDEQUE_REPAIR_ENABLE #define ETL_ICIRCULAR_BUFFER_REPAIR_ENABLE #define ETL_IN_UNIT_TEST -#define ETL_DEBUG_COUNT +//#define ETL_DEBUG_COUNT #define ETL_ARRAY_VIEW_IS_MUTABLE #define ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK diff --git a/test/murmurhash3.cpp b/test/murmurhash3.cpp index dc1f0c13..d404a5cc 100644 --- a/test/murmurhash3.cpp +++ b/test/murmurhash3.cpp @@ -158,7 +158,7 @@ void MurmurHash3_x86_32(const void * key, int len, uint32_t seed, void * out) case 2: k1 ^= tail[1] << 8U; case 1: k1 ^= tail[0]; k1 *= c1; k1 = ROTL32(k1, 15); k1 *= c2; h1 ^= k1; - }; + } //---------- // finalization @@ -251,7 +251,7 @@ void MurmurHash3_x86_128(const void * key, const int len, case 2: k1 ^= tail[1] << 8U; case 1: k1 ^= tail[0] << 0U; k1 *= c1; k1 = ROTL32(k1, 15); k1 *= c2; h1 ^= k1; - }; + } //---------- // finalization @@ -337,7 +337,7 @@ void MurmurHash3_x64_128(const void * key, const int len, case 2: k1 ^= ((uint64_t)tail[1]) << 8U; case 1: k1 ^= ((uint64_t)tail[0]) << 0U; k1 *= c1; k1 = ROTL64(k1, 31); k1 *= c2; h1 ^= k1; - }; + } //---------- // finalization diff --git a/test/syntax_check/CMakeLists.txt b/test/syntax_check/CMakeLists.txt index 31629a73..e6316fc7 100644 --- a/test/syntax_check/CMakeLists.txt +++ b/test/syntax_check/CMakeLists.txt @@ -35,10 +35,24 @@ set_target_properties(tests PROPERTIES CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS ON ) +if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") target_compile_options(tests PRIVATE -fsyntax-only + -pedantic-errors + -Wextra-semi ) +endif () +if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") +target_compile_options(tests + PRIVATE + -fsyntax-only + -pedantic-errors + -Wextra-semi + -Wextra-semi-stmt + -Wc++11-extra-semi + ) +endif () if (ETL_CXX_STANDARD MATCHES "98") message(STATUS "Compiling for C++98") diff --git a/test/test_algorithm.cpp b/test/test_algorithm.cpp index b7573bb0..f79ff95a 100644 --- a/test/test_algorithm.cpp +++ b/test/test_algorithm.cpp @@ -2504,5 +2504,5 @@ namespace CHECK_EQUAL(0, result5); CHECK_EQUAL(10, result6); } - }; + } } diff --git a/test/test_alignment.cpp b/test/test_alignment.cpp index 24ff4c28..ff461d25 100644 --- a/test/test_alignment.cpp +++ b/test/test_alignment.cpp @@ -284,5 +284,5 @@ namespace c.destroy(); CHECK_FALSE(c.has_value()); } - }; + } } diff --git a/test/test_array.cpp b/test/test_array.cpp index 857719f2..9edd0719 100644 --- a/test/test_array.cpp +++ b/test/test_array.cpp @@ -920,5 +920,5 @@ namespace #endif } #endif - }; + } } diff --git a/test/test_array_view.cpp b/test/test_array_view.cpp index 0202dcd1..0bb69eda 100644 --- a/test/test_array_view.cpp +++ b/test/test_array_view.cpp @@ -767,5 +767,5 @@ namespace bool isEqual = std::equal(filldata.begin(), filldata.end(), view.begin()); CHECK(isEqual); } - }; + } } diff --git a/test/test_array_wrapper.cpp b/test/test_array_wrapper.cpp index b93ff35d..cfcb4131 100644 --- a/test/test_array_wrapper.cpp +++ b/test/test_array_wrapper.cpp @@ -567,7 +567,7 @@ namespace CHECK_EQUAL(compare_hash, hash); } - }; + } } #if defined(ETL_COMPILER_CLANG) diff --git a/test/test_atomic.cpp b/test/test_atomic.cpp index 281b7650..a7442975 100644 --- a/test/test_atomic.cpp +++ b/test/test_atomic.cpp @@ -464,8 +464,8 @@ namespace //************************************************************************* TEST(test_atomic_operator_fetch_and) { - std::atomic compare(0xFFFFFFFFUL); - etl::atomic test(0xFFFFFFFFUL); + std::atomic compare(int(0xFFFFFFFFUL)); + etl::atomic test(int(0xFFFFFFFFUL)); CHECK_EQUAL(compare.fetch_and(0x55AA55AAUL), test.fetch_and(0x55AA55AAUL)); } @@ -766,5 +766,5 @@ namespace CHECK_EQUAL(0, atomic_value.load()); } #endif - }; + } } diff --git a/test/test_base64_RFC2152_decoder.cpp b/test/test_base64_RFC2152_decoder.cpp index 64cc11ca..66642b83 100644 --- a/test/test_base64_RFC2152_decoder.cpp +++ b/test/test_base64_RFC2152_decoder.cpp @@ -774,6 +774,6 @@ namespace CHECK_TRUE(b64.error()); #endif } - }; + } } diff --git a/test/test_base64_RFC2152_encoder.cpp b/test/test_base64_RFC2152_encoder.cpp index f463da39..947f0b57 100644 --- a/test/test_base64_RFC2152_encoder.cpp +++ b/test/test_base64_RFC2152_encoder.cpp @@ -744,6 +744,6 @@ namespace CHECK_TRUE(b64.overflow()); #endif } - }; + } } diff --git a/test/test_base64_RFC3501_decoder.cpp b/test/test_base64_RFC3501_decoder.cpp index 2e3c2faf..1c5e14e6 100644 --- a/test/test_base64_RFC3501_decoder.cpp +++ b/test/test_base64_RFC3501_decoder.cpp @@ -771,6 +771,6 @@ namespace CHECK_TRUE(b64.error()); #endif } - }; + } } diff --git a/test/test_base64_RFC3501_encoder.cpp b/test/test_base64_RFC3501_encoder.cpp index 0acc36a3..4c6f23ba 100644 --- a/test/test_base64_RFC3501_encoder.cpp +++ b/test/test_base64_RFC3501_encoder.cpp @@ -740,6 +740,6 @@ namespace CHECK_THROW((b64.encode(input_data.data(), 10)), etl::base64_overflow); CHECK_TRUE(b64.overflow()); } - }; + } } diff --git a/test/test_base64_RFC4648_URL_decoder_with_no_padding.cpp b/test/test_base64_RFC4648_URL_decoder_with_no_padding.cpp index c1c9280d..216cde1b 100644 --- a/test/test_base64_RFC4648_URL_decoder_with_no_padding.cpp +++ b/test/test_base64_RFC4648_URL_decoder_with_no_padding.cpp @@ -786,6 +786,6 @@ namespace CHECK_TRUE(b64.error()); #endif } - }; + } } diff --git a/test/test_base64_RFC4648_URL_decoder_with_padding.cpp b/test/test_base64_RFC4648_URL_decoder_with_padding.cpp index ab75c182..990b6613 100644 --- a/test/test_base64_RFC4648_URL_decoder_with_padding.cpp +++ b/test/test_base64_RFC4648_URL_decoder_with_padding.cpp @@ -786,5 +786,5 @@ namespace CHECK_TRUE(b64.error()); #endif } - }; + } } diff --git a/test/test_base64_RFC4648_URL_encoder_with_no_padding.cpp b/test/test_base64_RFC4648_URL_encoder_with_no_padding.cpp index 56835228..798d2695 100644 --- a/test/test_base64_RFC4648_URL_encoder_with_no_padding.cpp +++ b/test/test_base64_RFC4648_URL_encoder_with_no_padding.cpp @@ -738,6 +738,6 @@ namespace CHECK_THROW((b64.encode(input_data.data(), 10)), etl::base64_overflow); CHECK_TRUE(b64.overflow()); } - }; + } } diff --git a/test/test_base64_RFC4648_URL_encoder_with_padding.cpp b/test/test_base64_RFC4648_URL_encoder_with_padding.cpp index 9c9f2e21..dc5fe71f 100644 --- a/test/test_base64_RFC4648_URL_encoder_with_padding.cpp +++ b/test/test_base64_RFC4648_URL_encoder_with_padding.cpp @@ -738,6 +738,6 @@ namespace CHECK_THROW((b64.encode(input_data.data(), 10)), etl::base64_overflow); CHECK_TRUE(b64.overflow()); } - }; + } } diff --git a/test/test_base64_RFC4648_decoder_with_no_padding.cpp b/test/test_base64_RFC4648_decoder_with_no_padding.cpp index 8fbde338..dddfd0eb 100644 --- a/test/test_base64_RFC4648_decoder_with_no_padding.cpp +++ b/test/test_base64_RFC4648_decoder_with_no_padding.cpp @@ -786,6 +786,6 @@ namespace CHECK_TRUE(b64.error()); #endif } - }; + } } diff --git a/test/test_base64_RFC4648_decoder_with_padding.cpp b/test/test_base64_RFC4648_decoder_with_padding.cpp index fef5112a..0b05fb9d 100644 --- a/test/test_base64_RFC4648_decoder_with_padding.cpp +++ b/test/test_base64_RFC4648_decoder_with_padding.cpp @@ -786,6 +786,6 @@ namespace CHECK_TRUE(b64.error()); #endif } - }; + } } diff --git a/test/test_base64_RFC4648_encoder_with_no_padding.cpp b/test/test_base64_RFC4648_encoder_with_no_padding.cpp index eefe003f..d09f3ac0 100644 --- a/test/test_base64_RFC4648_encoder_with_no_padding.cpp +++ b/test/test_base64_RFC4648_encoder_with_no_padding.cpp @@ -738,6 +738,6 @@ namespace CHECK_THROW((b64.encode(input_data.data(), 10)), etl::base64_overflow); CHECK_TRUE(b64.overflow()); } - }; + } } diff --git a/test/test_base64_RFC4648_encoder_with_padding.cpp b/test/test_base64_RFC4648_encoder_with_padding.cpp index 50b48b3b..74e9ae62 100644 --- a/test/test_base64_RFC4648_encoder_with_padding.cpp +++ b/test/test_base64_RFC4648_encoder_with_padding.cpp @@ -738,6 +738,6 @@ namespace CHECK_THROW((b64.encode(input_data.data(), 10)), etl::base64_overflow); CHECK_TRUE(b64.overflow()); } - }; + } } diff --git a/test/test_binary.cpp b/test/test_binary.cpp index 32d6343e..f8d54ada 100644 --- a/test/test_binary.cpp +++ b/test/test_binary.cpp @@ -3052,7 +3052,7 @@ namespace CHECK_ARRAY_EQUAL(expected.data(), output.data(), expected.size()); } - }; + } } #include "etl/private/diagnostic_pop.h" diff --git a/test/test_bip_buffer_spsc_atomic.cpp b/test/test_bip_buffer_spsc_atomic.cpp index c850ec92..9711685d 100644 --- a/test/test_bip_buffer_spsc_atomic.cpp +++ b/test/test_bip_buffer_spsc_atomic.cpp @@ -392,7 +392,7 @@ namespace } } #endif - }; + } } #endif // ETL_HAS_ATOMIC diff --git a/test/test_bit.cpp b/test/test_bit.cpp index 176345c8..0443de68 100644 --- a/test/test_bit.cpp +++ b/test/test_bit.cpp @@ -1563,7 +1563,7 @@ namespace CHECK_EQUAL(test_bit_width(uint64_t(0xAU)), sizeof(temp)); } #endif - }; + } } #include "etl/private/diagnostic_pop.h" diff --git a/test/test_bit_stream.cpp b/test/test_bit_stream.cpp index 666e5911..6d232995 100644 --- a/test/test_bit_stream.cpp +++ b/test/test_bit_stream.cpp @@ -1072,7 +1072,7 @@ namespace CHECK(bit_stream.get(rd)); CHECK_CLOSE(f, rd, 0.1f); } - }; + } } #include "etl/private/diagnostic_pop.h" diff --git a/test/test_bit_stream_reader_big_endian.cpp b/test/test_bit_stream_reader_big_endian.cpp index 9c099085..f7aadf2e 100644 --- a/test/test_bit_stream_reader_big_endian.cpp +++ b/test/test_bit_stream_reader_big_endian.cpp @@ -1504,7 +1504,7 @@ namespace CHECK_EQUAL(object2.i, result2.i); CHECK_EQUAL(object2.c, result2.c); } - }; + } } #include "etl/private/diagnostic_pop.h" diff --git a/test/test_bit_stream_reader_little_endian.cpp b/test/test_bit_stream_reader_little_endian.cpp index fcf91b22..c2e86d05 100644 --- a/test/test_bit_stream_reader_little_endian.cpp +++ b/test/test_bit_stream_reader_little_endian.cpp @@ -1192,7 +1192,7 @@ namespace CHECK_EQUAL(object2.i, result2.i); CHECK_EQUAL(object2.c, result2.c); } - }; + } } #include "etl/private/diagnostic_pop.h" diff --git a/test/test_bit_stream_writer_big_endian.cpp b/test/test_bit_stream_writer_big_endian.cpp index 429d1754..ddcf25b2 100644 --- a/test/test_bit_stream_writer_big_endian.cpp +++ b/test/test_bit_stream_writer_big_endian.cpp @@ -814,7 +814,7 @@ namespace CHECK_EQUAL(bit_stream.empty(), false); CHECK_EQUAL(bit_stream.full(), true); } - }; + } } #include "etl/private/diagnostic_pop.h" diff --git a/test/test_bit_stream_writer_little_endian.cpp b/test/test_bit_stream_writer_little_endian.cpp index 56e47287..7094bfe6 100644 --- a/test/test_bit_stream_writer_little_endian.cpp +++ b/test/test_bit_stream_writer_little_endian.cpp @@ -902,7 +902,7 @@ namespace CHECK_EQUAL(bit_stream.empty(), false); CHECK_EQUAL(bit_stream.full(), true); } - }; + } } #include "etl/private/diagnostic_pop.h" diff --git a/test/test_bitset_legacy.cpp b/test/test_bitset_legacy.cpp index 7723b172..45fae83f 100644 --- a/test/test_bitset_legacy.cpp +++ b/test/test_bitset_legacy.cpp @@ -1532,5 +1532,5 @@ namespace etl::bitset<0> shiftbits = bits << 1; // No exception. } - }; + } } diff --git a/test/test_bitset_new_comparisons.cpp b/test/test_bitset_new_comparisons.cpp index 4436982f..b88684d6 100644 --- a/test/test_bitset_new_comparisons.cpp +++ b/test/test_bitset_new_comparisons.cpp @@ -235,5 +235,5 @@ namespace CHECK(data2 != data3); // bitset (M) != bitset_ext (S) CHECK(data3 != data2); // bitset_ext (S) != bitset (M) } - }; + } } diff --git a/test/test_bitset_new_default_element_type.cpp b/test/test_bitset_new_default_element_type.cpp index 30619fcf..6730948c 100644 --- a/test/test_bitset_new_default_element_type.cpp +++ b/test/test_bitset_new_default_element_type.cpp @@ -2709,5 +2709,5 @@ namespace CHECK_EQUAL(32, ETL_OR_STD17::size(b)); } - }; + } } diff --git a/test/test_bitset_new_explicit_single_element_type.cpp b/test/test_bitset_new_explicit_single_element_type.cpp index f06d4d42..c4cce00e 100644 --- a/test/test_bitset_new_explicit_single_element_type.cpp +++ b/test/test_bitset_new_explicit_single_element_type.cpp @@ -2823,5 +2823,5 @@ namespace CHECK_EQUAL(32, ETL_OR_STD17::size(b)); } - }; + } } diff --git a/test/test_bitset_new_ext_default_element_type.cpp b/test/test_bitset_new_ext_default_element_type.cpp index 3cc9fc25..75b81eb0 100644 --- a/test/test_bitset_new_ext_default_element_type.cpp +++ b/test/test_bitset_new_ext_default_element_type.cpp @@ -2459,5 +2459,5 @@ namespace CHECK_EQUAL(32, ETL_OR_STD17::size(b)); } - }; + } } diff --git a/test/test_bitset_new_ext_explicit_single_element_type.cpp b/test/test_bitset_new_ext_explicit_single_element_type.cpp index 75c18a5f..6542cbf2 100644 --- a/test/test_bitset_new_ext_explicit_single_element_type.cpp +++ b/test/test_bitset_new_ext_explicit_single_element_type.cpp @@ -2627,5 +2627,5 @@ namespace CHECK_EQUAL(32, ETL_OR_STD17::size(b)); } - }; + } } diff --git a/test/test_bloom_filter.cpp b/test/test_bloom_filter.cpp index 12768336..804e5fa6 100644 --- a/test/test_bloom_filter.cpp +++ b/test/test_bloom_filter.cpp @@ -260,6 +260,6 @@ namespace CHECK(!any_exist); } - }; + } } diff --git a/test/test_bresenham_line.cpp b/test/test_bresenham_line.cpp index e350e894..a0ccd53b 100644 --- a/test/test_bresenham_line.cpp +++ b/test/test_bresenham_line.cpp @@ -436,5 +436,5 @@ namespace CHECK(bl1 != bl4); CHECK(!(bl1 == bl4)); } - }; + } } diff --git a/test/test_bsd_checksum.cpp b/test/test_bsd_checksum.cpp index 2dff6c74..8c37ca35 100644 --- a/test/test_bsd_checksum.cpp +++ b/test/test_bsd_checksum.cpp @@ -173,6 +173,6 @@ namespace CHECK_EQUAL(hash1, hash2); CHECK_EQUAL(hash1, hash3); } - }; + } } diff --git a/test/test_buffer_descriptors.cpp b/test/test_buffer_descriptors.cpp index e66729f2..030f718a 100644 --- a/test/test_buffer_descriptors.cpp +++ b/test/test_buffer_descriptors.cpp @@ -403,5 +403,5 @@ namespace t2.join(); } #endif - }; + } } diff --git a/test/test_byte_stream.cpp b/test/test_byte_stream.cpp index 4d63068d..f6c461af 100644 --- a/test/test_byte_stream.cpp +++ b/test/test_byte_stream.cpp @@ -1348,7 +1348,7 @@ namespace CHECK_FALSE(result.has_value()); CHECK_TRUE(r.empty()); } - }; + } } #include "etl/private/diagnostic_pop.h" diff --git a/test/test_callback_service.cpp b/test/test_callback_service.cpp index c2f89db2..420ec1c0 100644 --- a/test/test_callback_service.cpp +++ b/test/test_callback_service.cpp @@ -329,5 +329,5 @@ namespace CHECK(!member2_called); CHECK(unhandled_called); } - }; + } } diff --git a/test/test_callback_timer.cpp b/test/test_callback_timer.cpp index 62b2a059..471e25d4 100644 --- a/test/test_callback_timer.cpp +++ b/test/test_callback_timer.cpp @@ -945,5 +945,5 @@ namespace //CHECK_ARRAY_EQUAL(compare2.data(), free_tick_list1.data(), min(compare2.size(), free_tick_list1.size())); } #endif - }; + } } diff --git a/test/test_callback_timer_atomic.cpp b/test/test_callback_timer_atomic.cpp index 01b09e89..34f4ce81 100644 --- a/test/test_callback_timer_atomic.cpp +++ b/test/test_callback_timer_atomic.cpp @@ -951,7 +951,7 @@ namespace //CHECK_ARRAY_EQUAL(compare2.data(), free_tick_list1.data(), min(compare2.size(), free_tick_list1.size())); } #endif - }; + } } #endif diff --git a/test/test_callback_timer_deferred_locked.cpp b/test/test_callback_timer_deferred_locked.cpp index 46aaafe5..3fb551fe 100644 --- a/test/test_callback_timer_deferred_locked.cpp +++ b/test/test_callback_timer_deferred_locked.cpp @@ -1264,5 +1264,5 @@ namespace CHECK_EQUAL(0U, threadLock.lock_count); } #endif - }; + } } diff --git a/test/test_callback_timer_interrupt.cpp b/test/test_callback_timer_interrupt.cpp index ae373c6e..41ed325c 100644 --- a/test/test_callback_timer_interrupt.cpp +++ b/test/test_callback_timer_interrupt.cpp @@ -996,5 +996,5 @@ namespace // Check the CHECK_EQUAL(0U, ScopedGuard::guard_count); } - }; + } } diff --git a/test/test_callback_timer_locked.cpp b/test/test_callback_timer_locked.cpp index ddeda3a4..76240d0c 100644 --- a/test/test_callback_timer_locked.cpp +++ b/test/test_callback_timer_locked.cpp @@ -1146,5 +1146,5 @@ namespace CHECK_EQUAL(0U, threadLock.lock_count); } #endif - }; + } } diff --git a/test/test_char_traits.cpp b/test/test_char_traits.cpp index 75b6dad3..5b43ed94 100644 --- a/test/test_char_traits.cpp +++ b/test/test_char_traits.cpp @@ -750,7 +750,7 @@ namespace CHECK(int_type(char_traits::eof()) != char_traits::not_eof(char_traits::eof())); CHECK(int_type(char_traits::eof() + 1) == char_traits::not_eof(char_traits::eof() + 1)); } - }; + } } #include "etl/private/diagnostic_pop.h" diff --git a/test/test_checksum.cpp b/test/test_checksum.cpp index 207e927a..99819254 100644 --- a/test/test_checksum.cpp +++ b/test/test_checksum.cpp @@ -181,6 +181,6 @@ namespace uint32_t hash3 = etl::checksum(data3.rbegin(), data3.rend()); CHECK_EQUAL(int(hash1), int(hash3)); } - }; + } } diff --git a/test/test_chrono_clocks.cpp b/test/test_chrono_clocks.cpp index 31ceadc7..78deb309 100644 --- a/test/test_chrono_clocks.cpp +++ b/test/test_chrono_clocks.cpp @@ -171,5 +171,5 @@ namespace CHECK_EQUAL(sys_clock_count, scaled_steady_lock_count); } - }; + } } diff --git a/test/test_chrono_day.cpp b/test/test_chrono_day.cpp index d7066c61..af9dec6c 100644 --- a/test/test_chrono_day.cpp +++ b/test/test_chrono_day.cpp @@ -323,5 +323,5 @@ namespace CHECK_EQUAL(256U, hashes.size()); } #endif - }; + } } diff --git a/test/test_chrono_duration.cpp b/test/test_chrono_duration.cpp index 8da3d36d..935d2c71 100644 --- a/test/test_chrono_duration.cpp +++ b/test/test_chrono_duration.cpp @@ -1138,5 +1138,5 @@ namespace #endif } #endif - }; + } } diff --git a/test/test_chrono_hh_mm_ss.cpp b/test/test_chrono_hh_mm_ss.cpp index 887bb42f..b051a988 100644 --- a/test/test_chrono_hh_mm_ss.cpp +++ b/test/test_chrono_hh_mm_ss.cpp @@ -285,5 +285,5 @@ namespace CHECK_EQUAL(0, time.fractional_width); CHECK_TRUE((std::is_same::precision>::value)); } - }; + } } diff --git a/test/test_chrono_literals.cpp b/test/test_chrono_literals.cpp index 00fde480..d9d30e9a 100644 --- a/test/test_chrono_literals.cpp +++ b/test/test_chrono_literals.cpp @@ -84,5 +84,5 @@ namespace CHECK_TRUE(etl::chrono::microseconds(1000) == 1000_microseconds); CHECK_TRUE(etl::chrono::nanoseconds(10000) == 10000_nanoseconds); } - }; + } } diff --git a/test/test_chrono_month.cpp b/test/test_chrono_month.cpp index 47c633fd..765d018f 100644 --- a/test/test_chrono_month.cpp +++ b/test/test_chrono_month.cpp @@ -352,5 +352,5 @@ namespace CHECK_EQUAL(11U, static_cast(Chrono::November)); CHECK_EQUAL(12U, static_cast(Chrono::December)); } - }; + } } diff --git a/test/test_chrono_month_day.cpp b/test/test_chrono_month_day.cpp index edd32e0e..c79eceea 100644 --- a/test/test_chrono_month_day.cpp +++ b/test/test_chrono_month_day.cpp @@ -210,6 +210,5 @@ namespace CHECK_EQUAL(Chrono::December, md_max.month()); CHECK_EQUAL(Chrono::day{31}, md_max.day()); } - - }; + } } diff --git a/test/test_chrono_month_day_last.cpp b/test/test_chrono_month_day_last.cpp index ec9b6ae4..4685215e 100644 --- a/test/test_chrono_month_day_last.cpp +++ b/test/test_chrono_month_day_last.cpp @@ -126,5 +126,5 @@ namespace (void)std::unique(hashes.begin(), hashes.end()); } #endif - }; + } } diff --git a/test/test_chrono_month_weekday.cpp b/test/test_chrono_month_weekday.cpp index 29b532ab..5853bca7 100644 --- a/test/test_chrono_month_weekday.cpp +++ b/test/test_chrono_month_weekday.cpp @@ -120,5 +120,5 @@ namespace CHECK_EQUAL(256U, hashes.size()); } #endif - }; + } } diff --git a/test/test_chrono_month_weekday_last.cpp b/test/test_chrono_month_weekday_last.cpp index a79fe0e1..87d448c5 100644 --- a/test/test_chrono_month_weekday_last.cpp +++ b/test/test_chrono_month_weekday_last.cpp @@ -121,5 +121,5 @@ namespace CHECK_EQUAL(256U, hashes.size()); } #endif - }; + } } diff --git a/test/test_chrono_operators.cpp b/test/test_chrono_operators.cpp index 74a69f90..ecccba63 100644 --- a/test/test_chrono_operators.cpp +++ b/test/test_chrono_operators.cpp @@ -281,5 +281,5 @@ namespace CHECK_EQUAL(etl::chrono::May, ymdl5.month()); CHECK_EQUAL(etl::chrono::weekday_last(etl::chrono::Friday).weekday().c_encoding(), ymdl5.weekday().c_encoding()); } - }; + } } \ No newline at end of file diff --git a/test/test_chrono_time_point.cpp b/test/test_chrono_time_point.cpp index abf1cefc..9eb13ddb 100644 --- a/test/test_chrono_time_point.cpp +++ b/test/test_chrono_time_point.cpp @@ -358,5 +358,5 @@ namespace CHECK_EQUAL(expected, actual); } - }; + } } diff --git a/test/test_chrono_weekday.cpp b/test/test_chrono_weekday.cpp index 6f4cc5ee..7aa52251 100644 --- a/test/test_chrono_weekday.cpp +++ b/test/test_chrono_weekday.cpp @@ -383,5 +383,5 @@ namespace CHECK_EQUAL(256U, hashes.size()); } #endif - }; + } } diff --git a/test/test_chrono_weekday_indexed.cpp b/test/test_chrono_weekday_indexed.cpp index abaa6aad..92b9221b 100644 --- a/test/test_chrono_weekday_indexed.cpp +++ b/test/test_chrono_weekday_indexed.cpp @@ -159,5 +159,5 @@ namespace (void)std::unique(hashes.begin(), hashes.end()); } #endif - }; + } } diff --git a/test/test_chrono_weekday_last.cpp b/test/test_chrono_weekday_last.cpp index 4db7e658..9b949160 100644 --- a/test/test_chrono_weekday_last.cpp +++ b/test/test_chrono_weekday_last.cpp @@ -131,5 +131,5 @@ namespace (void)std::unique(hashes.begin(), hashes.end()); } #endif - }; + } } diff --git a/test/test_chrono_year.cpp b/test/test_chrono_year.cpp index a86d5a4c..e7ec7904 100644 --- a/test/test_chrono_year.cpp +++ b/test/test_chrono_year.cpp @@ -313,5 +313,5 @@ namespace CHECK_EQUAL(65535U, hashes.size()); } #endif - }; + } } diff --git a/test/test_chrono_year_month.cpp b/test/test_chrono_year_month.cpp index a0e8ab7f..e016e8c4 100644 --- a/test/test_chrono_year_month.cpp +++ b/test/test_chrono_year_month.cpp @@ -144,5 +144,5 @@ namespace CHECK_TRUE(ym1 != ym2); // Different year CHECK_TRUE(ym1 != ym3); // Different month } - }; + } } diff --git a/test/test_chrono_year_month_day.cpp b/test/test_chrono_year_month_day.cpp index c7e9cabd..a5710e73 100644 --- a/test/test_chrono_year_month_day.cpp +++ b/test/test_chrono_year_month_day.cpp @@ -225,5 +225,5 @@ namespace CHECK_TRUE(ym1 != ym3); // Different month CHECK_TRUE(ym1 != ym4); // Different day } - }; + } } diff --git a/test/test_chrono_year_month_day_last.cpp b/test/test_chrono_year_month_day_last.cpp index 4e9145b0..e2ada34c 100644 --- a/test/test_chrono_year_month_day_last.cpp +++ b/test/test_chrono_year_month_day_last.cpp @@ -195,5 +195,5 @@ namespace CHECK_EQUAL(11016, sd.time_since_epoch().count()); } - }; + } } diff --git a/test/test_chrono_year_month_weekday.cpp b/test/test_chrono_year_month_weekday.cpp index 9e3f38bc..fdb9c4d2 100644 --- a/test/test_chrono_year_month_weekday.cpp +++ b/test/test_chrono_year_month_weekday.cpp @@ -150,5 +150,5 @@ namespace CHECK_TRUE(ym1 != ym3); // Different month CHECK_TRUE(ym1 != ym4); // Different day } - }; + } } diff --git a/test/test_chrono_year_month_weekday_last.cpp b/test/test_chrono_year_month_weekday_last.cpp index 1084398b..409c2d93 100644 --- a/test/test_chrono_year_month_weekday_last.cpp +++ b/test/test_chrono_year_month_weekday_last.cpp @@ -103,5 +103,5 @@ namespace CHECK_TRUE(ym1 != ym3); // Different month CHECK_TRUE(ym1 != ym4); // Different day } - }; + } } diff --git a/test/test_circular_buffer.cpp b/test/test_circular_buffer.cpp index d4e6314c..b7cc15d0 100644 --- a/test/test_circular_buffer.cpp +++ b/test/test_circular_buffer.cpp @@ -997,7 +997,7 @@ namespace using CB = etl::circular_buffer; std::vector input = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - CB data(input.begin(), input.end());; + CB data(input.begin(), input.end()); char buffer[sizeof(CB)]; @@ -1034,7 +1034,7 @@ namespace using ICB = etl::icircular_buffer; std::vector input = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - CB data(input.begin(), input.end());; + CB data(input.begin(), input.end()); char buffer[sizeof(CB)]; @@ -1063,6 +1063,5 @@ namespace CHECK(!is_equal); } - - }; + } } diff --git a/test/test_circular_buffer_external_buffer.cpp b/test/test_circular_buffer_external_buffer.cpp index 40d1933f..a86da8c0 100644 --- a/test/test_circular_buffer_external_buffer.cpp +++ b/test/test_circular_buffer_external_buffer.cpp @@ -1096,5 +1096,5 @@ namespace CHECK(data1 != data2); } - }; + } } diff --git a/test/test_circular_iterator.cpp b/test/test_circular_iterator.cpp index 191b4ad5..167af271 100644 --- a/test/test_circular_iterator.cpp +++ b/test/test_circular_iterator.cpp @@ -699,5 +699,5 @@ namespace CHECK(ci1 != ci3); CHECK(ci3 != ci1); } - }; + } } diff --git a/test/test_closure.cpp b/test/test_closure.cpp index 2a9f41a0..dc48fea3 100644 --- a/test/test_closure.cpp +++ b/test/test_closure.cpp @@ -187,5 +187,5 @@ namespace //c.bind(1, 2, 3); // Argument count mismatch //c.bind(1, std::string()); // Argument is not convertible } - }; + } } diff --git a/test/test_closure_constexpr.cpp b/test/test_closure_constexpr.cpp index 4467a882..fb8b2e2d 100644 --- a/test/test_closure_constexpr.cpp +++ b/test/test_closure_constexpr.cpp @@ -158,7 +158,7 @@ namespace static constexpr int result = c5(); CHECK_EQUAL(23, result); } - }; + } } #endif diff --git a/test/test_compare.cpp b/test/test_compare.cpp index f0de4b26..e9cefbe3 100644 --- a/test/test_compare.cpp +++ b/test/test_compare.cpp @@ -191,5 +191,5 @@ namespace CHECK_EQUAL(CompareInt::Greater, cmp_test_greater); CHECK_EQUAL(CompareInt::Equal, cmp_test_equal); } - }; + } } diff --git a/test/test_const_map.cpp b/test/test_const_map.cpp index 65efe5b4..2774cd9d 100644 --- a/test/test_const_map.cpp +++ b/test/test_const_map.cpp @@ -1152,7 +1152,7 @@ namespace static const bool compareAB1 = compare(value_type{ Key{ 'A' }, 0 }, value_type{ Key{ 'B' }, 0 }); static const bool compareAB2 = compare(value_type{ Key{ 'A' }, 0 }, Key{ 'B' }); - static const bool compareAB3 = compare(Key{ 'A' }, value_type{ Key{ 'B' }, 0 });; + static const bool compareAB3 = compare(Key{ 'A' }, value_type{ Key{ 'B' }, 0 }); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -1197,7 +1197,7 @@ namespace static const bool compareAB1 = compare(value_type{ 'A', 0 }, value_type{ 'B', 0 }); static const bool compareAB2 = compare(value_type{ 'A', 0 }, 'B'); - static const bool compareAB3 = compare('A', value_type{ 'B', 0 });; + static const bool compareAB3 = compare('A', value_type{ 'B', 0 }); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -1574,5 +1574,5 @@ namespace CHECK_TRUE(greater_than_equal11); #endif } - }; + } } diff --git a/test/test_const_map_constexpr.cpp b/test/test_const_map_constexpr.cpp index eca2b48e..b52ed59f 100644 --- a/test/test_const_map_constexpr.cpp +++ b/test/test_const_map_constexpr.cpp @@ -1154,7 +1154,7 @@ namespace static constexpr bool compareAB1 = compare(value_type{ Key{ 'A' }, 0 }, value_type{ Key{ 'B' }, 0 }); static constexpr bool compareAB2 = compare(value_type{ Key{ 'A' }, 0 }, Key{ 'B' }); - static constexpr bool compareAB3 = compare(Key{ 'A' }, value_type{ Key{ 'B' }, 0 });; + static constexpr bool compareAB3 = compare(Key{ 'A' }, value_type{ Key{ 'B' }, 0 }); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -1199,7 +1199,7 @@ namespace static constexpr bool compareAB1 = compare(value_type{ 'A', 0 }, value_type{ 'B', 0 }); static constexpr bool compareAB2 = compare(value_type{ 'A', 0 }, 'B'); - static constexpr bool compareAB3 = compare('A', value_type{ 'B', 0 });; + static constexpr bool compareAB3 = compare('A', value_type{ 'B', 0 }); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -1576,7 +1576,7 @@ namespace CHECK_TRUE(greater_than_equal11); #endif } - }; + } } #endif diff --git a/test/test_const_map_ext.cpp b/test/test_const_map_ext.cpp index fc3ed33e..5867ccaa 100644 --- a/test/test_const_map_ext.cpp +++ b/test/test_const_map_ext.cpp @@ -1236,7 +1236,7 @@ namespace static const bool compareAB1 = compare(value_type{ Key{ 'A' }, 0 }, value_type{ Key{ 'B' }, 0 }); static const bool compareAB2 = compare(value_type{ Key{ 'A' }, 0 }, Key{ 'B' }); - static const bool compareAB3 = compare(Key{ 'A' }, value_type{ Key{ 'B' }, 0 });; + static const bool compareAB3 = compare(Key{ 'A' }, value_type{ Key{ 'B' }, 0 }); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -1281,7 +1281,7 @@ namespace static const bool compareAB1 = compare(value_type{ 'A', 0 }, value_type{ 'B', 0 }); static const bool compareAB2 = compare(value_type{ 'A', 0 }, 'B'); - static const bool compareAB3 = compare('A', value_type{ 'B', 0 });; + static const bool compareAB3 = compare('A', value_type{ 'B', 0 }); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -1709,5 +1709,5 @@ namespace CHECK_TRUE(greater_than_equal11); #endif } - }; + } } diff --git a/test/test_const_map_ext_constexpr.cpp b/test/test_const_map_ext_constexpr.cpp index c1735fff..db0ad13f 100644 --- a/test/test_const_map_ext_constexpr.cpp +++ b/test/test_const_map_ext_constexpr.cpp @@ -1238,7 +1238,7 @@ namespace static constexpr bool compareAB1 = compare(value_type{ Key{ 'A' }, 0 }, value_type{ Key{ 'B' }, 0 }); static constexpr bool compareAB2 = compare(value_type{ Key{ 'A' }, 0 }, Key{ 'B' }); - static constexpr bool compareAB3 = compare(Key{ 'A' }, value_type{ Key{ 'B' }, 0 });; + static constexpr bool compareAB3 = compare(Key{ 'A' }, value_type{ Key{ 'B' }, 0 }); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -1283,7 +1283,7 @@ namespace static constexpr bool compareAB1 = compare(value_type{ 'A', 0 }, value_type{ 'B', 0 }); static constexpr bool compareAB2 = compare(value_type{ 'A', 0 }, 'B'); - static constexpr bool compareAB3 = compare('A', value_type{ 'B', 0 });; + static constexpr bool compareAB3 = compare('A', value_type{ 'B', 0 }); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -1711,7 +1711,7 @@ namespace CHECK_TRUE(greater_than_equal11); #endif } - }; + } } #endif diff --git a/test/test_const_multimap.cpp b/test/test_const_multimap.cpp index 46457b41..bb45eee2 100644 --- a/test/test_const_multimap.cpp +++ b/test/test_const_multimap.cpp @@ -900,7 +900,7 @@ namespace static const bool compareAB1 = compare(value_type{ Key{ 'A' }, 0 }, value_type{ Key{ 'B' }, 0 }); static const bool compareAB2 = compare(value_type{ Key{ 'A' }, 0 }, Key{ 'B' }); - static const bool compareAB3 = compare(Key{ 'A' }, value_type{ Key{ 'B' }, 0 });; + static const bool compareAB3 = compare(Key{ 'A' }, value_type{ Key{ 'B' }, 0 }); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -945,7 +945,7 @@ namespace static const bool compareAB1 = compare(value_type{ 'A', 0 }, value_type{ 'B', 0 }); static const bool compareAB2 = compare(value_type{ 'A', 0 }, 'B'); - static const bool compareAB3 = compare('A', value_type{ 'B', 0 });; + static const bool compareAB3 = compare('A', value_type{ 'B', 0 }); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -1321,5 +1321,5 @@ namespace CHECK_TRUE(greater_than_equal11); #endif } - }; + } } diff --git a/test/test_const_multimap_constexpr.cpp b/test/test_const_multimap_constexpr.cpp index a881c491..6c87ba94 100644 --- a/test/test_const_multimap_constexpr.cpp +++ b/test/test_const_multimap_constexpr.cpp @@ -833,7 +833,7 @@ namespace static constexpr bool compareAB1 = compare(value_type{ Key{ 'A' }, 0 }, value_type{ Key{ 'B' }, 0 }); static constexpr bool compareAB2 = compare(value_type{ Key{ 'A' }, 0 }, Key{ 'B' }); - static constexpr bool compareAB3 = compare(Key{ 'A' }, value_type{ Key{ 'B' }, 0 });; + static constexpr bool compareAB3 = compare(Key{ 'A' }, value_type{ Key{ 'B' }, 0 }); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -878,7 +878,7 @@ namespace static constexpr bool compareAB1 = compare(value_type{ 'A', 0 }, value_type{ 'B', 0 }); static constexpr bool compareAB2 = compare(value_type{ 'A', 0 }, 'B'); - static constexpr bool compareAB3 = compare('A', value_type{ 'B', 0 });; + static constexpr bool compareAB3 = compare('A', value_type{ 'B', 0 }); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -1254,7 +1254,7 @@ namespace CHECK_TRUE(greater_than_equal11); #endif } - }; + } } #endif diff --git a/test/test_const_multimap_ext.cpp b/test/test_const_multimap_ext.cpp index b68ad450..32bc629a 100644 --- a/test/test_const_multimap_ext.cpp +++ b/test/test_const_multimap_ext.cpp @@ -1042,7 +1042,7 @@ namespace static const bool compareAB1 = compare(value_type{ Key{ 'A' }, 0 }, value_type{ Key{ 'B' }, 0 }); static const bool compareAB2 = compare(value_type{ Key{ 'A' }, 0 }, Key{ 'B' }); - static const bool compareAB3 = compare(Key{ 'A' }, value_type{ Key{ 'B' }, 0 });; + static const bool compareAB3 = compare(Key{ 'A' }, value_type{ Key{ 'B' }, 0 }); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -1087,7 +1087,7 @@ namespace static const bool compareAB1 = compare(value_type{ 'A', 0 }, value_type{ 'B', 0 }); static const bool compareAB2 = compare(value_type{ 'A', 0 }, 'B'); - static const bool compareAB3 = compare('A', value_type{ 'B', 0 });; + static const bool compareAB3 = compare('A', value_type{ 'B', 0 }); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -1516,5 +1516,5 @@ namespace CHECK_TRUE(greater_than_equal11); #endif } - }; + } } diff --git a/test/test_const_multimap_ext_constexpr.cpp b/test/test_const_multimap_ext_constexpr.cpp index 9425e42b..a373ce65 100644 --- a/test/test_const_multimap_ext_constexpr.cpp +++ b/test/test_const_multimap_ext_constexpr.cpp @@ -1035,7 +1035,7 @@ namespace static constexpr bool compareAB1 = compare(value_type{ Key{ 'A' }, 0 }, value_type{ Key{ 'B' }, 0 }); static constexpr bool compareAB2 = compare(value_type{ Key{ 'A' }, 0 }, Key{ 'B' }); - static constexpr bool compareAB3 = compare(Key{ 'A' }, value_type{ Key{ 'B' }, 0 });; + static constexpr bool compareAB3 = compare(Key{ 'A' }, value_type{ Key{ 'B' }, 0 }); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -1080,7 +1080,7 @@ namespace static constexpr bool compareAB1 = compare(value_type{ 'A', 0 }, value_type{ 'B', 0 }); static constexpr bool compareAB2 = compare(value_type{ 'A', 0 }, 'B'); - static constexpr bool compareAB3 = compare('A', value_type{ 'B', 0 });; + static constexpr bool compareAB3 = compare('A', value_type{ 'B', 0 }); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -1509,7 +1509,7 @@ namespace CHECK_TRUE(greater_than_equal11); #endif } - }; + } } #endif diff --git a/test/test_const_multiset.cpp b/test/test_const_multiset.cpp index b5102738..f7fc71a3 100644 --- a/test/test_const_multiset.cpp +++ b/test/test_const_multiset.cpp @@ -903,7 +903,7 @@ namespace static const bool compareAB1 = compare(Key('A'), Key('B')); static const bool compareAB2 = compare(Key('A'), Key{ 'B' }); - static const bool compareAB3 = compare(Key{ 'A' }, Key('B'));; + static const bool compareAB3 = compare(Key{ 'A' }, Key('B')); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -948,7 +948,7 @@ namespace static const bool compareAB1 = compare(Key('A'), Key('B')); static const bool compareAB2 = compare(Key('A'), 'B'); - static const bool compareAB3 = compare('A', Key('B'));; + static const bool compareAB3 = compare('A', Key('B')); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -1324,5 +1324,5 @@ namespace CHECK_TRUE(greater_than_equal11); #endif } - }; + } } diff --git a/test/test_const_multiset_constexpr.cpp b/test/test_const_multiset_constexpr.cpp index 95dc2db7..ae4c41f5 100644 --- a/test/test_const_multiset_constexpr.cpp +++ b/test/test_const_multiset_constexpr.cpp @@ -905,7 +905,7 @@ namespace static constexpr bool compareAB1 = compare(Key('A'), Key('B')); static constexpr bool compareAB2 = compare(Key('A'), Key{ 'B' }); - static constexpr bool compareAB3 = compare(Key{ 'A' }, Key('B'));; + static constexpr bool compareAB3 = compare(Key{ 'A' }, Key('B')); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -950,7 +950,7 @@ namespace static constexpr bool compareAB1 = compare(Key('A'), Key('B')); static constexpr bool compareAB2 = compare(Key('A'), 'B'); - static constexpr bool compareAB3 = compare('A', Key('B'));; + static constexpr bool compareAB3 = compare('A', Key('B')); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -1326,7 +1326,7 @@ namespace CHECK_TRUE(greater_than_equal11); #endif } - }; + } } #endif diff --git a/test/test_const_multiset_ext.cpp b/test/test_const_multiset_ext.cpp index 6574eff2..76a2592e 100644 --- a/test/test_const_multiset_ext.cpp +++ b/test/test_const_multiset_ext.cpp @@ -948,7 +948,7 @@ namespace static const bool compareAB1 = compare(Key('A'), Key('B')); static const bool compareAB2 = compare(Key('A'), Key{ 'B' }); - static const bool compareAB3 = compare(Key{ 'A' }, Key('B'));; + static const bool compareAB3 = compare(Key{ 'A' }, Key('B')); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -993,7 +993,7 @@ namespace static const bool compareAB1 = compare(Key('A'), Key('B')); static const bool compareAB2 = compare(Key('A'), 'B'); - static const bool compareAB3 = compare('A', Key('B'));; + static const bool compareAB3 = compare('A', Key('B')); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -1421,5 +1421,5 @@ namespace CHECK_TRUE(greater_than_equal11); #endif } - }; + } } diff --git a/test/test_const_multiset_ext_constexpr.cpp b/test/test_const_multiset_ext_constexpr.cpp index 2cff9b54..42043e31 100644 --- a/test/test_const_multiset_ext_constexpr.cpp +++ b/test/test_const_multiset_ext_constexpr.cpp @@ -950,7 +950,7 @@ namespace static constexpr bool compareAB1 = compare(Key('A'), Key('B')); static constexpr bool compareAB2 = compare(Key('A'), Key{ 'B' }); - static constexpr bool compareAB3 = compare(Key{ 'A' }, Key('B'));; + static constexpr bool compareAB3 = compare(Key{ 'A' }, Key('B')); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -995,7 +995,7 @@ namespace static constexpr bool compareAB1 = compare(Key('A'), Key('B')); static constexpr bool compareAB2 = compare(Key('A'), 'B'); - static constexpr bool compareAB3 = compare('A', Key('B'));; + static constexpr bool compareAB3 = compare('A', Key('B')); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -1423,7 +1423,7 @@ namespace CHECK_TRUE(greater_than_equal11); #endif } - }; + } } #endif diff --git a/test/test_const_set.cpp b/test/test_const_set.cpp index 06ed6b44..15ad54dd 100644 --- a/test/test_const_set.cpp +++ b/test/test_const_set.cpp @@ -1012,7 +1012,7 @@ namespace static const bool compareAB1 = compare( Key{ 'A' }, Key{ 'B' }); static const bool compareAB2 = compare( Key{ 'A' }, Key{ 'B' }); - static const bool compareAB3 = compare( Key{ 'A' }, Key{ 'B' });; + static const bool compareAB3 = compare( Key{ 'A' }, Key{ 'B' }); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -1433,5 +1433,5 @@ namespace CHECK_TRUE(greater_than_equal11); #endif } - }; + } } diff --git a/test/test_const_set_constexpr.cpp b/test/test_const_set_constexpr.cpp index c126bddf..8f4286e0 100644 --- a/test/test_const_set_constexpr.cpp +++ b/test/test_const_set_constexpr.cpp @@ -33,10 +33,10 @@ SOFTWARE. #include #include -#if ETL_USING_CPP14 - #include "etl/const_set.h" +#if ETL_USING_CPP14 + namespace { static constexpr size_t Max_Size = 10UL; @@ -85,11 +85,13 @@ namespace return (lhs.k == rhs.k); } +#if ETL_NOT_USING_CPP20 // Equality operator for Key != Key constexpr bool operator !=(const Key& lhs, const Key& rhs) noexcept { return !(lhs.k == rhs.k); } +#endif #define TEST_GREATER_THAN #ifdef TEST_GREATER_THAN @@ -1012,7 +1014,7 @@ namespace static constexpr bool compareAB1 = compare( Key{ 'A' }, Key{ 'B' }); static constexpr bool compareAB2 = compare( Key{ 'A' }, Key{ 'B' }); - static constexpr bool compareAB3 = compare( Key{ 'A' }, Key{ 'B' });; + static constexpr bool compareAB3 = compare( Key{ 'A' }, Key{ 'B' }); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -1433,7 +1435,7 @@ namespace CHECK_TRUE(greater_than_equal11); #endif } - }; + } } #endif diff --git a/test/test_const_set_ext.cpp b/test/test_const_set_ext.cpp index d9d194c0..c0176968 100644 --- a/test/test_const_set_ext.cpp +++ b/test/test_const_set_ext.cpp @@ -1095,7 +1095,7 @@ namespace static const bool compareAB1 = compare( Key{ 'A' }, Key{ 'B' }); static const bool compareAB2 = compare( Key{ 'A' }, Key{ 'B' }); - static const bool compareAB3 = compare(Key{ 'A' }, Key{ 'B' });; + static const bool compareAB3 = compare(Key{ 'A' }, Key{ 'B' }); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -1140,7 +1140,7 @@ namespace static const bool compareAB1 = compare( 'A', 'B'); static const bool compareAB2 = compare( 'A', 'B'); - static const bool compareAB3 = compare('A', 'B');; + static const bool compareAB3 = compare('A', 'B'); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -1568,5 +1568,5 @@ namespace CHECK_TRUE(greater_than_equal11); #endif } - }; + } } diff --git a/test/test_const_set_ext_constexpr.cpp b/test/test_const_set_ext_constexpr.cpp index ab5bd491..23161cb8 100644 --- a/test/test_const_set_ext_constexpr.cpp +++ b/test/test_const_set_ext_constexpr.cpp @@ -1097,7 +1097,7 @@ namespace static constexpr bool compareAB1 = compare( Key{ 'A' }, Key{ 'B' }); static constexpr bool compareAB2 = compare( Key{ 'A' }, Key{ 'B' }); - static constexpr bool compareAB3 = compare(Key{ 'A' }, Key{ 'B' });; + static constexpr bool compareAB3 = compare(Key{ 'A' }, Key{ 'B' }); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -1142,7 +1142,7 @@ namespace static constexpr bool compareAB1 = compare( 'A', 'B'); static constexpr bool compareAB2 = compare( 'A', 'B'); - static constexpr bool compareAB3 = compare('A', 'B');; + static constexpr bool compareAB3 = compare('A', 'B'); #ifdef TEST_GREATER_THAN CHECK_FALSE(compareAA1); @@ -1570,7 +1570,7 @@ namespace CHECK_TRUE(greater_than_equal11); #endif } - }; + } } #endif diff --git a/test/test_constant.cpp b/test/test_constant.cpp index e6bdd0c7..06130431 100644 --- a/test/test_constant.cpp +++ b/test/test_constant.cpp @@ -61,5 +61,5 @@ namespace CHECK_EQUAL((int64_t)etl::integral_limits::max, C3::value); CHECK((etl::is_same::value)); } - }; + } } diff --git a/test/test_container.cpp b/test/test_container.cpp index e2fbb811..ece1afba 100644 --- a/test/test_container.cpp +++ b/test/test_container.cpp @@ -145,7 +145,7 @@ namespace size_t compiletime_size = sizeof(etl::array_size(data)); CHECK_EQUAL(SIZE, compiletime_size); } - }; + } } #endif diff --git a/test/test_correlation.cpp b/test/test_correlation.cpp index 2bd689f1..8f86334a 100644 --- a/test/test_correlation.cpp +++ b/test/test_correlation.cpp @@ -280,5 +280,5 @@ namespace covariance_result = correlation3.get_covariance(); CHECK_CLOSE(9.17, covariance_result, 0.1); } - }; + } } diff --git a/test/test_covariance.cpp b/test/test_covariance.cpp index 705f1e12..fa86a393 100644 --- a/test/test_covariance.cpp +++ b/test/test_covariance.cpp @@ -238,5 +238,5 @@ namespace covariance_result = covariance3.get_covariance(); CHECK_CLOSE(9.17, covariance_result, 0.1); } - }; + } } diff --git a/test/test_crc1.cpp b/test/test_crc1.cpp index 4bbabefa..fb843c1a 100644 --- a/test/test_crc1.cpp +++ b/test/test_crc1.cpp @@ -146,6 +146,6 @@ namespace CHECK_EQUAL(etl::crc1::odd_parity, etl::crc1(data_odd.begin(), data_odd.end())); CHECK_EQUAL(etl::crc1::even_parity, etl::crc1(data_even.begin(), data_even.end())); } - }; + } } diff --git a/test/test_crc16.cpp b/test/test_crc16.cpp index de947c94..6bc37840 100644 --- a/test/test_crc16.cpp +++ b/test/test_crc16.cpp @@ -305,6 +305,6 @@ namespace uint16_t crc3 = etl::crc16_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc16_a.cpp b/test/test_crc16_a.cpp index 2dd49ee5..ebad7bf5 100644 --- a/test/test_crc16_a.cpp +++ b/test/test_crc16_a.cpp @@ -316,6 +316,6 @@ namespace uint16_t crc3 = etl::crc16_a_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc16_arc.cpp b/test/test_crc16_arc.cpp index 8e7376bf..2762fe79 100644 --- a/test/test_crc16_arc.cpp +++ b/test/test_crc16_arc.cpp @@ -316,6 +316,6 @@ namespace uint16_t crc3 = etl::crc16_arc_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc16_aug_ccitt.cpp b/test/test_crc16_aug_ccitt.cpp index 54ce1d2b..9b33bb03 100644 --- a/test/test_crc16_aug_ccitt.cpp +++ b/test/test_crc16_aug_ccitt.cpp @@ -316,6 +316,6 @@ namespace uint16_t crc3 = etl::crc16_aug_ccitt_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc16_buypass.cpp b/test/test_crc16_buypass.cpp index 14b2b45d..87ffd57a 100644 --- a/test/test_crc16_buypass.cpp +++ b/test/test_crc16_buypass.cpp @@ -316,6 +316,6 @@ namespace uint16_t crc3 = etl::crc16_buypass_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc16_ccitt.cpp b/test/test_crc16_ccitt.cpp index 3492252e..2fe6fb61 100644 --- a/test/test_crc16_ccitt.cpp +++ b/test/test_crc16_ccitt.cpp @@ -316,6 +316,6 @@ namespace uint16_t crc3 = etl::crc16_ccitt_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc16_cdma2000.cpp b/test/test_crc16_cdma2000.cpp index b80b1891..40e420ee 100644 --- a/test/test_crc16_cdma2000.cpp +++ b/test/test_crc16_cdma2000.cpp @@ -316,6 +316,6 @@ namespace uint16_t crc3 = etl::crc16_cdma2000_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc16_dds110.cpp b/test/test_crc16_dds110.cpp index 20e1869f..34dcfa84 100644 --- a/test/test_crc16_dds110.cpp +++ b/test/test_crc16_dds110.cpp @@ -316,6 +316,6 @@ namespace uint16_t crc3 = etl::crc16_dds110_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc16_dectr.cpp b/test/test_crc16_dectr.cpp index e713b725..5274b37a 100644 --- a/test/test_crc16_dectr.cpp +++ b/test/test_crc16_dectr.cpp @@ -316,6 +316,6 @@ namespace uint16_t crc3 = etl::crc16_dect_r_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc16_dectx.cpp b/test/test_crc16_dectx.cpp index f3e77a15..4ce202be 100644 --- a/test/test_crc16_dectx.cpp +++ b/test/test_crc16_dectx.cpp @@ -316,6 +316,6 @@ namespace uint16_t crc3 = etl::crc16_dect_x_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc16_dnp.cpp b/test/test_crc16_dnp.cpp index 5402dd9d..2bf15b10 100644 --- a/test/test_crc16_dnp.cpp +++ b/test/test_crc16_dnp.cpp @@ -316,6 +316,6 @@ namespace uint16_t crc3 = etl::crc16_dnp_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc16_en13757.cpp b/test/test_crc16_en13757.cpp index a70b3425..067fb58c 100644 --- a/test/test_crc16_en13757.cpp +++ b/test/test_crc16_en13757.cpp @@ -316,6 +316,6 @@ namespace uint16_t crc3 = etl::crc16_en13757_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc16_genibus.cpp b/test/test_crc16_genibus.cpp index 1ab9bbf1..46191e00 100644 --- a/test/test_crc16_genibus.cpp +++ b/test/test_crc16_genibus.cpp @@ -316,6 +316,6 @@ namespace uint16_t crc3 = etl::crc16_genibus_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc16_kermit.cpp b/test/test_crc16_kermit.cpp index 32fc673e..a759056d 100644 --- a/test/test_crc16_kermit.cpp +++ b/test/test_crc16_kermit.cpp @@ -316,6 +316,6 @@ namespace uint16_t crc3 = etl::crc16_kermit_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc16_m17.cpp b/test/test_crc16_m17.cpp index 5a6fda2d..b1ee95c2 100644 --- a/test/test_crc16_m17.cpp +++ b/test/test_crc16_m17.cpp @@ -316,6 +316,6 @@ namespace uint16_t crc3 = etl::crc16_m17_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc16_maxim.cpp b/test/test_crc16_maxim.cpp index 38b3058b..eab8ff09 100644 --- a/test/test_crc16_maxim.cpp +++ b/test/test_crc16_maxim.cpp @@ -316,6 +316,6 @@ namespace uint16_t crc3 = etl::crc16_maxim_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc16_mcrf4xx.cpp b/test/test_crc16_mcrf4xx.cpp index b7509aae..7bd2cce4 100644 --- a/test/test_crc16_mcrf4xx.cpp +++ b/test/test_crc16_mcrf4xx.cpp @@ -316,6 +316,6 @@ namespace uint16_t crc3 = etl::crc16_mcrf4xx_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc16_modbus.cpp b/test/test_crc16_modbus.cpp index e747a9ea..819c395b 100644 --- a/test/test_crc16_modbus.cpp +++ b/test/test_crc16_modbus.cpp @@ -316,6 +316,6 @@ namespace uint16_t crc3 = etl::crc16_modbus_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc16_opensafety_a.cpp b/test/test_crc16_opensafety_a.cpp index dbf2804b..48981168 100644 --- a/test/test_crc16_opensafety_a.cpp +++ b/test/test_crc16_opensafety_a.cpp @@ -316,6 +316,6 @@ namespace uint16_t crc3 = etl::crc16_opensafety_a_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc16_opensafety_b.cpp b/test/test_crc16_opensafety_b.cpp index 523d41bf..de9e059c 100644 --- a/test/test_crc16_opensafety_b.cpp +++ b/test/test_crc16_opensafety_b.cpp @@ -316,6 +316,6 @@ namespace uint16_t crc3 = etl::crc16_opensafety_b_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc16_profibus.cpp b/test/test_crc16_profibus.cpp index a7e3f301..1d57eeb7 100644 --- a/test/test_crc16_profibus.cpp +++ b/test/test_crc16_profibus.cpp @@ -316,6 +316,6 @@ namespace uint16_t crc3 = etl::crc16_profibus_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc16_riello.cpp b/test/test_crc16_riello.cpp index 319b0a84..2965e152 100644 --- a/test/test_crc16_riello.cpp +++ b/test/test_crc16_riello.cpp @@ -316,6 +316,6 @@ namespace uint16_t crc3 = etl::crc16_riello_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc16_t10dif.cpp b/test/test_crc16_t10dif.cpp index 570b9935..312289db 100644 --- a/test/test_crc16_t10dif.cpp +++ b/test/test_crc16_t10dif.cpp @@ -316,6 +316,6 @@ namespace uint16_t crc3 = etl::crc16_t10dif_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc16_teledisk.cpp b/test/test_crc16_teledisk.cpp index 69135f08..f50fa2ff 100644 --- a/test/test_crc16_teledisk.cpp +++ b/test/test_crc16_teledisk.cpp @@ -316,6 +316,6 @@ namespace uint16_t crc3 = etl::crc16_teledisk_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc16_tms37157.cpp b/test/test_crc16_tms37157.cpp index 12733b0f..fbb474c9 100644 --- a/test/test_crc16_tms37157.cpp +++ b/test/test_crc16_tms37157.cpp @@ -316,6 +316,6 @@ namespace uint16_t crc3 = etl::crc16_tms37157_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc16_usb.cpp b/test/test_crc16_usb.cpp index e3249443..ac06985f 100644 --- a/test/test_crc16_usb.cpp +++ b/test/test_crc16_usb.cpp @@ -316,6 +316,6 @@ namespace uint16_t crc3 = etl::crc16_usb_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc16_x25.cpp b/test/test_crc16_x25.cpp index 42799814..2b434f32 100644 --- a/test/test_crc16_x25.cpp +++ b/test/test_crc16_x25.cpp @@ -316,6 +316,6 @@ namespace uint16_t crc3 = etl::crc16_x25_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc16_xmodem.cpp b/test/test_crc16_xmodem.cpp index 4630f438..5b0c0bf3 100644 --- a/test/test_crc16_xmodem.cpp +++ b/test/test_crc16_xmodem.cpp @@ -316,6 +316,6 @@ namespace uint16_t crc3 = etl::crc16_xmodem_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc32.cpp b/test/test_crc32.cpp index e8ce34e0..89ecf035 100644 --- a/test/test_crc32.cpp +++ b/test/test_crc32.cpp @@ -305,6 +305,6 @@ namespace uint32_t crc3 = etl::crc32_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc32_bzip2.cpp b/test/test_crc32_bzip2.cpp index 262f471e..bbffb555 100644 --- a/test/test_crc32_bzip2.cpp +++ b/test/test_crc32_bzip2.cpp @@ -316,6 +316,6 @@ namespace uint32_t crc3 = etl::crc32_bzip2_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc32_c.cpp b/test/test_crc32_c.cpp index 65e4de2d..40802124 100644 --- a/test/test_crc32_c.cpp +++ b/test/test_crc32_c.cpp @@ -316,6 +316,6 @@ namespace uint32_t crc3 = etl::crc32_c_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc32_d.cpp b/test/test_crc32_d.cpp index 8b68d0c6..484478ac 100644 --- a/test/test_crc32_d.cpp +++ b/test/test_crc32_d.cpp @@ -316,6 +316,6 @@ namespace uint32_t crc3 = etl::crc32_d_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc32_jamcrc.cpp b/test/test_crc32_jamcrc.cpp index 29f2285f..316f4c85 100644 --- a/test/test_crc32_jamcrc.cpp +++ b/test/test_crc32_jamcrc.cpp @@ -316,6 +316,6 @@ namespace uint32_t crc3 = etl::crc32_jamcrc_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc32_mpeg2.cpp b/test/test_crc32_mpeg2.cpp index 3826e065..b0e700c7 100644 --- a/test/test_crc32_mpeg2.cpp +++ b/test/test_crc32_mpeg2.cpp @@ -316,6 +316,6 @@ namespace uint32_t crc3 = etl::crc32_mpeg2_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc32_posix.cpp b/test/test_crc32_posix.cpp index fd3101e0..54fab698 100644 --- a/test/test_crc32_posix.cpp +++ b/test/test_crc32_posix.cpp @@ -316,6 +316,6 @@ namespace uint32_t crc3 = etl::crc32_posix_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc32_q.cpp b/test/test_crc32_q.cpp index 92e20e07..bc1ed5ee 100644 --- a/test/test_crc32_q.cpp +++ b/test/test_crc32_q.cpp @@ -316,6 +316,6 @@ namespace uint32_t crc3 = etl::crc32_q_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc32_xfer.cpp b/test/test_crc32_xfer.cpp index 95510fb0..301e9f11 100644 --- a/test/test_crc32_xfer.cpp +++ b/test/test_crc32_xfer.cpp @@ -316,6 +316,6 @@ namespace uint32_t crc3 = etl::crc32_xfer_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc64_ecma.cpp b/test/test_crc64_ecma.cpp index dea9430b..b73111d2 100644 --- a/test/test_crc64_ecma.cpp +++ b/test/test_crc64_ecma.cpp @@ -316,6 +316,6 @@ namespace uint64_t crc3 = etl::crc64_ecma_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc64_iso.cpp b/test/test_crc64_iso.cpp index dc87ebdd..869db18d 100644 --- a/test/test_crc64_iso.cpp +++ b/test/test_crc64_iso.cpp @@ -316,6 +316,6 @@ namespace uint64_t crc3 = etl::crc64_iso_t4(data3.rbegin(), data3.rend()); CHECK_EQUAL(crc1, crc3); } - }; + } } diff --git a/test/test_crc8_ccitt.cpp b/test/test_crc8_ccitt.cpp index d71ee2ff..fda367a7 100644 --- a/test/test_crc8_ccitt.cpp +++ b/test/test_crc8_ccitt.cpp @@ -316,6 +316,6 @@ namespace uint8_t crc3 = etl::crc8_ccitt(data3.rbegin(), data3.rend()); CHECK_EQUAL(int(crc1), int(crc3)); } - }; + } } diff --git a/test/test_crc8_cdma2000.cpp b/test/test_crc8_cdma2000.cpp index 71a5b24d..67b7b4f5 100644 --- a/test/test_crc8_cdma2000.cpp +++ b/test/test_crc8_cdma2000.cpp @@ -316,6 +316,6 @@ namespace uint8_t crc3 = etl::crc8_cdma2000(data3.rbegin(), data3.rend()); CHECK_EQUAL(int(crc1), int(crc3)); } - }; + } } diff --git a/test/test_crc8_darc.cpp b/test/test_crc8_darc.cpp index adfef170..944f7f88 100644 --- a/test/test_crc8_darc.cpp +++ b/test/test_crc8_darc.cpp @@ -316,6 +316,6 @@ namespace uint8_t crc3 = etl::crc8_darc(data3.rbegin(), data3.rend()); CHECK_EQUAL(int(crc1), int(crc3)); } - }; + } } diff --git a/test/test_crc8_dvbs2.cpp b/test/test_crc8_dvbs2.cpp index ea13c3e9..19a14e4b 100644 --- a/test/test_crc8_dvbs2.cpp +++ b/test/test_crc8_dvbs2.cpp @@ -316,6 +316,6 @@ namespace uint8_t crc3 = etl::crc8_dvbs2(data3.rbegin(), data3.rend()); CHECK_EQUAL(int(crc1), int(crc3)); } - }; + } } diff --git a/test/test_crc8_ebu.cpp b/test/test_crc8_ebu.cpp index 065498dd..80f71074 100644 --- a/test/test_crc8_ebu.cpp +++ b/test/test_crc8_ebu.cpp @@ -316,6 +316,6 @@ namespace uint8_t crc3 = etl::crc8_ebu(data3.rbegin(), data3.rend()); CHECK_EQUAL(int(crc1), int(crc3)); } - }; + } } diff --git a/test/test_crc8_icode.cpp b/test/test_crc8_icode.cpp index 33403afd..de3a43cf 100644 --- a/test/test_crc8_icode.cpp +++ b/test/test_crc8_icode.cpp @@ -316,6 +316,6 @@ namespace uint8_t crc3 = etl::crc8_icode(data3.rbegin(), data3.rend()); CHECK_EQUAL(int(crc1), int(crc3)); } - }; + } } diff --git a/test/test_crc8_itu.cpp b/test/test_crc8_itu.cpp index 02924153..d6d4f678 100644 --- a/test/test_crc8_itu.cpp +++ b/test/test_crc8_itu.cpp @@ -316,6 +316,6 @@ namespace uint8_t crc3 = etl::crc8_itu(data3.rbegin(), data3.rend()); CHECK_EQUAL(int(crc1), int(crc3)); } - }; + } } diff --git a/test/test_crc8_j1850.cpp b/test/test_crc8_j1850.cpp index e0a6b325..5567ef11 100644 --- a/test/test_crc8_j1850.cpp +++ b/test/test_crc8_j1850.cpp @@ -316,6 +316,6 @@ namespace uint8_t crc3 = etl::crc8_j1850(data3.rbegin(), data3.rend()); CHECK_EQUAL(int(crc1), int(crc3)); } - }; + } } diff --git a/test/test_crc8_j1850_zero.cpp b/test/test_crc8_j1850_zero.cpp index 0e37afbb..2abde07e 100644 --- a/test/test_crc8_j1850_zero.cpp +++ b/test/test_crc8_j1850_zero.cpp @@ -316,6 +316,6 @@ namespace uint8_t crc3 = etl::crc8_j1850_zero(data3.rbegin(), data3.rend()); CHECK_EQUAL(int(crc1), int(crc3)); } - }; + } } diff --git a/test/test_crc8_maxim.cpp b/test/test_crc8_maxim.cpp index e06f5497..b65fcc6c 100644 --- a/test/test_crc8_maxim.cpp +++ b/test/test_crc8_maxim.cpp @@ -316,6 +316,6 @@ namespace uint8_t crc3 = etl::crc8_maxim(data3.rbegin(), data3.rend()); CHECK_EQUAL(int(crc1), int(crc3)); } - }; + } } diff --git a/test/test_crc8_nrsc5.cpp b/test/test_crc8_nrsc5.cpp index db109988..45835e7a 100644 --- a/test/test_crc8_nrsc5.cpp +++ b/test/test_crc8_nrsc5.cpp @@ -291,6 +291,6 @@ namespace uint8_t crc3 = etl::crc8_nrsc5(data3.rbegin(), data3.rend()); CHECK_EQUAL(int(crc1), int(crc3)); } - }; + } } diff --git a/test/test_crc8_opensafety.cpp b/test/test_crc8_opensafety.cpp index 913ce7ba..608852fd 100644 --- a/test/test_crc8_opensafety.cpp +++ b/test/test_crc8_opensafety.cpp @@ -316,6 +316,6 @@ namespace uint8_t crc3 = etl::crc8_opensafety(data3.rbegin(), data3.rend()); CHECK_EQUAL(int(crc1), int(crc3)); } - }; + } } diff --git a/test/test_crc8_rohc.cpp b/test/test_crc8_rohc.cpp index 84f49726..d2da2cde 100644 --- a/test/test_crc8_rohc.cpp +++ b/test/test_crc8_rohc.cpp @@ -316,6 +316,6 @@ namespace uint8_t crc3 = etl::crc8_rohc(data3.rbegin(), data3.rend()); CHECK_EQUAL(int(crc1), int(crc3)); } - }; + } } diff --git a/test/test_crc8_wcdma.cpp b/test/test_crc8_wcdma.cpp index 2c591e3c..33b44686 100644 --- a/test/test_crc8_wcdma.cpp +++ b/test/test_crc8_wcdma.cpp @@ -316,6 +316,6 @@ namespace uint8_t crc3 = etl::crc8_wcdma(data3.rbegin(), data3.rend()); CHECK_EQUAL(int(crc1), int(crc3)); } - }; + } } diff --git a/test/test_cyclic_value.cpp b/test/test_cyclic_value.cpp index f1f9e193..109a2b38 100644 --- a/test/test_cyclic_value.cpp +++ b/test/test_cyclic_value.cpp @@ -492,5 +492,5 @@ namespace CHECK(data1 == compare2); CHECK(data2 == compare1); } - }; + } } diff --git a/test/test_debounce.cpp b/test/test_debounce.cpp index a56b07ca..868739b1 100644 --- a/test/test_debounce.cpp +++ b/test/test_debounce.cpp @@ -875,5 +875,5 @@ namespace CHECK(key_state.add(false)); CHECK(!key_state.is_set()); } - }; + } } diff --git a/test/test_delegate.cpp b/test/test_delegate.cpp index 165c0250..57c52e86 100644 --- a/test/test_delegate.cpp +++ b/test/test_delegate.cpp @@ -112,7 +112,7 @@ namespace //***************************************************************************** void free_int(int i, int j) { - function_called = FunctionCalled::Free_Int_Called;; + function_called = FunctionCalled::Free_Int_Called; parameter_correct = (i == VALUE1) && (j == VALUE2); } @@ -1822,7 +1822,7 @@ namespace Object object; auto d1 = etl::delegate::create(object); - auto d2 = etl::delegate::create(object);; + auto d2 = etl::delegate::create(object); CHECK(d1 != d2); } @@ -2019,7 +2019,7 @@ namespace (void)d; } #endif - }; + } } #endif diff --git a/test/test_delegate_cpp03.cpp b/test/test_delegate_cpp03.cpp index 3a220de3..6aeb43cc 100644 --- a/test/test_delegate_cpp03.cpp +++ b/test/test_delegate_cpp03.cpp @@ -773,7 +773,7 @@ namespace Object object; auto d1 = etl_cpp03::delegate::create(object); - auto d2 = etl_cpp03::delegate::create(object);; + auto d2 = etl_cpp03::delegate::create(object); CHECK(d1 != d2); } @@ -920,5 +920,5 @@ namespace CHECK(*itr != d2); CHECK(*itr == d3); } - }; + } } diff --git a/test/test_delegate_observable.cpp b/test/test_delegate_observable.cpp index 914d97f6..a056b1b6 100644 --- a/test/test_delegate_observable.cpp +++ b/test/test_delegate_observable.cpp @@ -274,7 +274,7 @@ namespace CHECK_EQUAL(3, global_value); CHECK_EQUAL(4, member_value); } - }; + } } #endif diff --git a/test/test_delegate_service.cpp b/test/test_delegate_service.cpp index a9aa858e..d6745a3c 100644 --- a/test/test_delegate_service.cpp +++ b/test/test_delegate_service.cpp @@ -331,7 +331,7 @@ namespace CHECK(!member2_called); CHECK(unhandled_called); } - }; + } } #endif diff --git a/test/test_delegate_service_compile_time.cpp b/test/test_delegate_service_compile_time.cpp index c97db964..7c688eda 100644 --- a/test/test_delegate_service_compile_time.cpp +++ b/test/test_delegate_service_compile_time.cpp @@ -159,7 +159,7 @@ namespace CHECK(!member_called); CHECK(unhandled_called); } - }; + } } #endif diff --git a/test/test_delegate_service_cpp03.cpp b/test/test_delegate_service_cpp03.cpp index cd2caae8..da372392 100644 --- a/test/test_delegate_service_cpp03.cpp +++ b/test/test_delegate_service_cpp03.cpp @@ -331,7 +331,7 @@ namespace CHECK(!member2_called); CHECK(unhandled_called); } - }; + } } #endif diff --git a/test/test_deque.cpp b/test/test_deque.cpp index dcd9558b..a1b0fa15 100644 --- a/test/test_deque.cpp +++ b/test/test_deque.cpp @@ -2263,7 +2263,7 @@ namespace CHECK(std::equal(blank_data.begin(), blank_data.end(), data.begin())); } - }; + } } #include "etl/private/diagnostic_pop.h" diff --git a/test/test_endian.cpp b/test/test_endian.cpp index a0c7720f..8d7529ee 100644 --- a/test/test_endian.cpp +++ b/test/test_endian.cpp @@ -61,5 +61,5 @@ namespace #error Endianness unknown: Test not possible #endif } - }; + } } diff --git a/test/test_enum_type.cpp b/test/test_enum_type.cpp index f51f4ead..42b39c3a 100644 --- a/test/test_enum_type.cpp +++ b/test/test_enum_type.cpp @@ -150,5 +150,5 @@ namespace CHECK_EQUAL(expected, actual.get_enum()); } - }; + } } diff --git a/test/test_error_handler.cpp b/test/test_error_handler.cpp index a8fba63e..c060f238 100644 --- a/test/test_error_handler.cpp +++ b/test/test_error_handler.cpp @@ -188,5 +188,5 @@ namespace CHECK(error_received); } - }; + } } diff --git a/test/test_etl_assert.cpp b/test/test_etl_assert.cpp index 2df84d31..e927a0b2 100644 --- a/test/test_etl_assert.cpp +++ b/test/test_etl_assert.cpp @@ -67,5 +67,5 @@ namespace CHECK_THROW(ETL_ASSERT(false, ETL_ERROR_GENERIC("Generic Assert Exception")), etl::exception); CHECK_NO_THROW(ETL_ASSERT(true, ETL_ERROR_GENERIC("Generic Assert Exception"))); } - }; + } } diff --git a/test/test_etl_traits.cpp b/test/test_etl_traits.cpp index fa1c700d..f61b2831 100644 --- a/test/test_etl_traits.cpp +++ b/test/test_etl_traits.cpp @@ -110,5 +110,5 @@ namespace CHECK_ARRAY_EQUAL(ETL_VERSION, etl::traits::version_u16string, etl::strlen(ETL_VERSION_U16)); CHECK_ARRAY_EQUAL(ETL_VERSION, etl::traits::version_u32string, etl::strlen(ETL_VERSION_U32)); } - }; + } } diff --git a/test/test_exception.cpp b/test/test_exception.cpp index fde141cc..0a57804f 100644 --- a/test/test_exception.cpp +++ b/test/test_exception.cpp @@ -61,5 +61,5 @@ namespace CHECK_EQUAL(123, c.line_number()); } } - }; + } } diff --git a/test/test_expected.cpp b/test/test_expected.cpp index d7df3577..e71a218a 100644 --- a/test/test_expected.cpp +++ b/test/test_expected.cpp @@ -792,5 +792,5 @@ namespace CHECK_TRUE(test_unexp_1_swap == test_unexp_2); CHECK_TRUE(test_unexp_2_swap == test_unexp_1); } - }; + } } diff --git a/test/test_fixed_iterator.cpp b/test/test_fixed_iterator.cpp index e440ed18..b35f9221 100644 --- a/test/test_fixed_iterator.cpp +++ b/test/test_fixed_iterator.cpp @@ -228,5 +228,5 @@ namespace CHECK(fi1 == fi2); CHECK(fi1 != fi3); } - }; + } } diff --git a/test/test_flags.cpp b/test/test_flags.cpp index acb33e7b..231c96ac 100644 --- a/test/test_flags.cpp +++ b/test/test_flags.cpp @@ -610,5 +610,5 @@ namespace CHECK_EQUAL(int(FNONE), int(flags3 ^= F01234567)); CHECK_EQUAL(int(F0246), int(flags4 ^= FNONE)); } - }; + } } diff --git a/test/test_flat_map.cpp b/test/test_flat_map.cpp index 272ebe10..d60d2e6d 100644 --- a/test/test_flat_map.cpp +++ b/test/test_flat_map.cpp @@ -1555,5 +1555,5 @@ namespace CHECK(data.contains(Key(1))); CHECK(!data.contains(Key(99))); } - }; + } } diff --git a/test/test_flat_multimap.cpp b/test/test_flat_multimap.cpp index 50999b56..b3358d18 100644 --- a/test/test_flat_multimap.cpp +++ b/test/test_flat_multimap.cpp @@ -1364,5 +1364,5 @@ namespace CHECK(data.contains(Key(1))); CHECK(!data.contains(Key(99))); } - }; + } } diff --git a/test/test_flat_multiset.cpp b/test/test_flat_multiset.cpp index 057a0ab3..52147a66 100644 --- a/test/test_flat_multiset.cpp +++ b/test/test_flat_multiset.cpp @@ -1356,5 +1356,5 @@ namespace CHECK(data.contains(Key(N5))); CHECK(!data.contains(Key(NX))); } - }; + } } diff --git a/test/test_flat_set.cpp b/test/test_flat_set.cpp index 5c380b02..c2016ad1 100644 --- a/test/test_flat_set.cpp +++ b/test/test_flat_set.cpp @@ -1316,5 +1316,5 @@ namespace CHECK(data.contains(Key(N5))); CHECK(!data.contains(Key(NX))); } - }; + } } diff --git a/test/test_fnv_1.cpp b/test/test_fnv_1.cpp index a3f866e3..ad8091b6 100644 --- a/test/test_fnv_1.cpp +++ b/test/test_fnv_1.cpp @@ -351,6 +351,6 @@ namespace uint64_t hash3 = etl::fnv_1a_64(data3.rbegin(), data3.rend()); CHECK_EQUAL(int(hash1), int(hash3)); } - }; + } } diff --git a/test/test_format_spec.cpp b/test/test_format_spec.cpp index eadf3ab0..57eb0841 100644 --- a/test/test_format_spec.cpp +++ b/test/test_format_spec.cpp @@ -118,6 +118,6 @@ namespace CHECK_EQUAL(true, upper_case); } #endif - }; + } } diff --git a/test/test_forward_list.cpp b/test/test_forward_list.cpp index 494b69c7..d7b44bf7 100644 --- a/test/test_forward_list.cpp +++ b/test/test_forward_list.cpp @@ -1419,5 +1419,5 @@ namespace CHECK_EQUAL(ItemNDC("F"), *itr++); } #endif - }; + } } diff --git a/test/test_forward_list_shared_pool.cpp b/test/test_forward_list_shared_pool.cpp index 6500805a..39d7a201 100644 --- a/test/test_forward_list_shared_pool.cpp +++ b/test/test_forward_list_shared_pool.cpp @@ -1926,5 +1926,5 @@ namespace CHECK(data1 < data3); CHECK(data3 > data1); } - }; + } } diff --git a/test/test_fsm.cpp b/test/test_fsm.cpp index 54745f3b..c6a34e8e 100644 --- a/test/test_fsm.cpp +++ b/test/test_fsm.cpp @@ -780,5 +780,5 @@ namespace CHECK_EQUAL(StateId::Locked, int(motorControl.get_state_id())); CHECK_EQUAL(StateId::Locked, int(motorControl.get_state().get_state_id())); } - }; + } } diff --git a/test/test_function.cpp b/test/test_function.cpp index c64f81ca..5b19ce36 100644 --- a/test/test_function.cpp +++ b/test/test_function.cpp @@ -506,5 +506,5 @@ namespace CHECK(function_called); } - }; + } } diff --git a/test/test_function_traits.cpp b/test/test_function_traits.cpp index 56024198..bd6448f0 100644 --- a/test/test_function_traits.cpp +++ b/test/test_function_traits.cpp @@ -448,7 +448,7 @@ namespace long operator()(int a, const std::string& s) { return static_cast(a + s.size()); - }; + } }; using traits = etl::function_traits; @@ -530,5 +530,5 @@ namespace CHECK_EQUAL(1, traits_f::arity); CHECK_EQUAL(1, traits_cf::arity); } - }; + } } diff --git a/test/test_functional.cpp b/test/test_functional.cpp index 9970cf25..1204d330 100644 --- a/test/test_functional.cpp +++ b/test/test_functional.cpp @@ -379,5 +379,5 @@ namespace result = f3(mft, "Arg1", " : Arg2"); CHECK_EQUAL("Function3_Const: Arg1 : Arg2", result); } - }; + } } diff --git a/test/test_gamma.cpp b/test/test_gamma.cpp index 579bf58d..2d2568a6 100644 --- a/test/test_gamma.cpp +++ b/test/test_gamma.cpp @@ -95,5 +95,5 @@ namespace bool isEqual = std::equal(output2.begin(), output2.end(), result2b.begin(), Compare()); CHECK(isEqual); } - }; + } } diff --git a/test/test_hash.cpp b/test/test_hash.cpp index 53567505..4c2c8acf 100644 --- a/test/test_hash.cpp +++ b/test/test_hash.cpp @@ -317,6 +317,6 @@ namespace CHECK_TRUE(std::is_copy_assignable::value); CHECK_TRUE(std::is_move_assignable::value); } - }; + } } diff --git a/test/test_hfsm.cpp b/test/test_hfsm.cpp index 30e422e7..b473d016 100644 --- a/test/test_hfsm.cpp +++ b/test/test_hfsm.cpp @@ -1087,5 +1087,5 @@ namespace } - }; + } } diff --git a/test/test_hfsm_recurse_to_inner_state_on_start.cpp b/test/test_hfsm_recurse_to_inner_state_on_start.cpp index 7e172ac2..1c8c7c74 100644 --- a/test/test_hfsm_recurse_to_inner_state_on_start.cpp +++ b/test/test_hfsm_recurse_to_inner_state_on_start.cpp @@ -256,5 +256,5 @@ namespace CHECK_EQUAL(StateId::State1_1_1, stateMachine.get_state_id()); } - }; + } } diff --git a/test/test_histogram.cpp b/test/test_histogram.cpp index c682c723..056f67c2 100644 --- a/test/test_histogram.cpp +++ b/test/test_histogram.cpp @@ -376,5 +376,5 @@ namespace isEqual = std::equal(output2.begin(), output2.end(), histogram.begin()); CHECK(isEqual); } - }; + } } diff --git a/test/test_indirect_vector.cpp b/test/test_indirect_vector.cpp index bcc3b08d..cd639a6b 100644 --- a/test/test_indirect_vector.cpp +++ b/test/test_indirect_vector.cpp @@ -1553,5 +1553,5 @@ namespace CHECK(std::equal(blank_data.begin(), blank_data.end(), data.begin())); } - }; + } } diff --git a/test/test_indirect_vector_external_buffer.cpp b/test/test_indirect_vector_external_buffer.cpp index 7911eabd..4ce54e75 100644 --- a/test/test_indirect_vector_external_buffer.cpp +++ b/test/test_indirect_vector_external_buffer.cpp @@ -1700,5 +1700,5 @@ namespace CHECK(is_equal); } - }; + } } diff --git a/test/test_instance_count.cpp b/test/test_instance_count.cpp index 654c48eb..57229996 100644 --- a/test/test_instance_count.cpp +++ b/test/test_instance_count.cpp @@ -106,5 +106,5 @@ namespace CHECK_EQUAL(2, Test1::get_instance_count()); CHECK_EQUAL(2, Test2::get_instance_count()); } - }; + } } diff --git a/test/test_integral_limits.cpp b/test/test_integral_limits.cpp index 9fcba6d8..f5928fc6 100644 --- a/test/test_integral_limits.cpp +++ b/test/test_integral_limits.cpp @@ -101,5 +101,5 @@ namespace CHECK_EQUAL(std::numeric_limits::is_signed, (bool)etl::integral_limits::is_signed); CHECK_EQUAL(std::numeric_limits::is_signed, (bool)etl::integral_limits::is_signed); } - }; + } } diff --git a/test/test_intrusive_forward_list.cpp b/test/test_intrusive_forward_list.cpp index da4d185c..4bb3d6f3 100644 --- a/test/test_intrusive_forward_list.cpp +++ b/test/test_intrusive_forward_list.cpp @@ -1358,5 +1358,5 @@ namespace CHECK_FALSE(data0.contains(compare_node2)); } - }; + } } diff --git a/test/test_intrusive_links.cpp b/test/test_intrusive_links.cpp index 2b8d0445..c5bb92c8 100644 --- a/test/test_intrusive_links.cpp +++ b/test/test_intrusive_links.cpp @@ -1730,5 +1730,5 @@ namespace CHECK(a.etl_left == nullptr); CHECK(a.etl_right == &c); } - }; + } } diff --git a/test/test_intrusive_list.cpp b/test/test_intrusive_list.cpp index c997c610..41ea478f 100644 --- a/test/test_intrusive_list.cpp +++ b/test/test_intrusive_list.cpp @@ -1610,5 +1610,5 @@ namespace CHECK_FALSE(data0.contains(compare_node2)); } - }; + } } diff --git a/test/test_intrusive_queue.cpp b/test/test_intrusive_queue.cpp index 8b44f343..8ab16536 100644 --- a/test/test_intrusive_queue.cpp +++ b/test/test_intrusive_queue.cpp @@ -438,5 +438,5 @@ namespace queueD.pop(); CHECK_EQUAL(queueD.back(), queueDR.back()); } - }; + } } diff --git a/test/test_intrusive_stack.cpp b/test/test_intrusive_stack.cpp index 282d887a..ad55b635 100644 --- a/test/test_intrusive_stack.cpp +++ b/test/test_intrusive_stack.cpp @@ -328,5 +328,5 @@ namespace CHECK_EQUAL(stack.top(), data5); } - }; + } } diff --git a/test/test_invert.cpp b/test/test_invert.cpp index c39d023e..41f80bca 100644 --- a/test/test_invert.cpp +++ b/test/test_invert.cpp @@ -130,5 +130,5 @@ namespace bool isEqual = std::equal(output2.begin(), output2.end(), result2b.begin(), Compare()); CHECK(isEqual); } - }; + } } diff --git a/test/test_io_port.cpp b/test/test_io_port.cpp index a4e4c0a1..ed359695 100644 --- a/test/test_io_port.cpp +++ b/test/test_io_port.cpp @@ -523,5 +523,5 @@ namespace CHECK_EQUAL(iop1.read(), *itr4); CHECK_EQUAL(iop2.read(), *itr3); } - }; + } } diff --git a/test/test_iterator.cpp b/test/test_iterator.cpp index c777574d..14f0d878 100644 --- a/test/test_iterator.cpp +++ b/test/test_iterator.cpp @@ -580,5 +580,5 @@ namespace // CHECK_EQUAL(expected.size(), output.size()); // CHECK(std::equal(output.begin(), output.end(), expected.begin())); //} - }; + } } diff --git a/test/test_jenkins.cpp b/test/test_jenkins.cpp index ed00abda..86d21569 100644 --- a/test/test_jenkins.cpp +++ b/test/test_jenkins.cpp @@ -164,6 +164,6 @@ namespace CHECK_THROW(j32.add(0), etl::hash_finalized); } - }; + } } diff --git a/test/test_largest.cpp b/test/test_largest.cpp index df6aef02..d36882ec 100644 --- a/test/test_largest.cpp +++ b/test/test_largest.cpp @@ -251,5 +251,5 @@ namespace CHECK(bool(etl::is_same, uint64_t>::value)); CHECK(bool(etl::is_same, uint64_t>::value)); } - }; + } } diff --git a/test/test_limiter.cpp b/test/test_limiter.cpp index 0ad36b9d..e4f31720 100644 --- a/test/test_limiter.cpp +++ b/test/test_limiter.cpp @@ -98,5 +98,5 @@ namespace bool isEqual = std::equal(output2.begin(), output2.end(), result2a.begin(), Compare()); CHECK(isEqual); } - }; + } } diff --git a/test/test_limits.cpp b/test/test_limits.cpp index 8c120454..28fda31d 100644 --- a/test/test_limits.cpp +++ b/test/test_limits.cpp @@ -730,5 +730,5 @@ namespace CHECK_EQUAL(STD_NL::radix, ETL_NL::radix); CHECK_EQUAL(STD_NL::round_error(), ETL_NL::round_error()); } - }; + } } diff --git a/test/test_list.cpp b/test/test_list.cpp index baed08a0..003fb853 100644 --- a/test/test_list.cpp +++ b/test/test_list.cpp @@ -2233,5 +2233,5 @@ namespace CHECK_EQUAL(ItemNDC("F"), *itr++); } #endif - }; + } } diff --git a/test/test_list_shared_pool.cpp b/test/test_list_shared_pool.cpp index e87203d9..802d15dc 100644 --- a/test/test_list_shared_pool.cpp +++ b/test/test_list_shared_pool.cpp @@ -2224,5 +2224,5 @@ namespace CHECK_THROW(data0.merge(data1), etl::list_unsorted); } - }; + } } diff --git a/test/test_macros.cpp b/test/test_macros.cpp index cf8be527..c57d876b 100644 --- a/test/test_macros.cpp +++ b/test/test_macros.cpp @@ -57,5 +57,5 @@ namespace CHECK_ARRAY_EQUAL(u"ABCDEF", ETL_U16_STRING(ABCDEF), etl::strlen(u"ABCDEF")); CHECK_ARRAY_EQUAL(U"ABCDEF", ETL_U32_STRING(ABCDEF), etl::strlen(U"ABCDEF")); } - }; + } } diff --git a/test/test_make_string.cpp b/test/test_make_string.cpp index f24b95d9..06b2b540 100644 --- a/test/test_make_string.cpp +++ b/test/test_make_string.cpp @@ -144,9 +144,9 @@ namespace #if ETL_HAS_ERROR_ON_STRING_TRUNCATION CHECK_THROW(auto ctext = etl::make_string_with_capacity("Hello World"), etl::string_truncation); - CHECK_THROW(auto wtext = etl::make_string_with_capacity(L"Hello World"), etl::string_truncation);; - CHECK_THROW(auto u16text = etl::make_string_with_capacity(u"Hello World"), etl::string_truncation);; - CHECK_THROW(auto u32text = etl::make_string_with_capacity(U"Hello World"), etl::string_truncation);; + CHECK_THROW(auto wtext = etl::make_string_with_capacity(L"Hello World"), etl::string_truncation); + CHECK_THROW(auto u16text = etl::make_string_with_capacity(u"Hello World"), etl::string_truncation); + CHECK_THROW(auto u32text = etl::make_string_with_capacity(U"Hello World"), etl::string_truncation); #else size_t length = strlen("Hello World"); @@ -185,5 +185,5 @@ namespace CHECK(Equal(std::u32string(U"Hello Worl"), ctext)); #endif } - }; + } } diff --git a/test/test_map.cpp b/test/test_map.cpp index c2e4527c..b5ca6447 100644 --- a/test/test_map.cpp +++ b/test/test_map.cpp @@ -1634,5 +1634,5 @@ namespace CHECK(!data.contains(std::string("99"))); CHECK(!data.contains(Key("99"))); } - }; + } } diff --git a/test/test_math.cpp b/test/test_math.cpp index ede19aa6..880768c4 100644 --- a/test/test_math.cpp +++ b/test/test_math.cpp @@ -130,5 +130,5 @@ namespace CHECK_TRUE(etl::is_exactly_equal(i1, i1)); CHECK_FALSE(etl::is_exactly_equal(i1, i2)); } - }; + } } diff --git a/test/test_math_functions.cpp b/test/test_math_functions.cpp index 40594351..0b7c9205 100644 --- a/test/test_math_functions.cpp +++ b/test/test_math_functions.cpp @@ -587,5 +587,5 @@ namespace CHECK_EQUAL(uint16_t(0), absolute5); CHECK_EQUAL(uint16_t(65535), absolute6); } - }; + } } diff --git a/test/test_mean.cpp b/test/test_mean.cpp index 1be97dc5..af225b34 100644 --- a/test/test_mean.cpp +++ b/test/test_mean.cpp @@ -112,5 +112,5 @@ namespace mean_result = mean1.get_mean(); CHECK_CLOSE(4.5, mean_result, 0.1); } - }; + } } diff --git a/test/test_mem_cast.cpp b/test/test_mem_cast.cpp index 406231e9..8090525d 100644 --- a/test/test_mem_cast.cpp +++ b/test/test_mem_cast.cpp @@ -340,5 +340,5 @@ namespace CHECK_EQUAL(2, memCastTypes.ref().a[1]); CHECK_EQUAL(3, memCastTypes.ref().a[2]); } - }; + } } diff --git a/test/test_mem_cast_ptr.cpp b/test/test_mem_cast_ptr.cpp index 90ce4930..973a345d 100644 --- a/test/test_mem_cast_ptr.cpp +++ b/test/test_mem_cast_ptr.cpp @@ -397,5 +397,5 @@ namespace CHECK_THROW(c = memCast.ref(), etl::mem_cast_nullptr_exception); CHECK(c == 0); } - }; + } } diff --git a/test/test_memory.cpp b/test/test_memory.cpp index 8fc7e628..59e66e3a 100644 --- a/test/test_memory.cpp +++ b/test/test_memory.cpp @@ -1447,7 +1447,7 @@ namespace class Base { public: - virtual ~Base() {}; + virtual ~Base() {} virtual void function() = 0; }; @@ -1699,5 +1699,5 @@ namespace CHECK_EQUAL(&i, etl::to_address(pi)); CHECK_EQUAL(plist_item, etl::to_address(itr)); } - }; + } } diff --git a/test/test_message.cpp b/test/test_message.cpp index 1e28b1f0..d51584f0 100644 --- a/test/test_message.cpp +++ b/test/test_message.cpp @@ -129,4 +129,4 @@ SUITE(test_message) CHECK_FALSE((std::is_same::value)); CHECK_FALSE((std::is_same::value)); } -}; +} diff --git a/test/test_message_broker.cpp b/test/test_message_broker.cpp index fda9ae16..faa74539 100644 --- a/test/test_message_broker.cpp +++ b/test/test_message_broker.cpp @@ -558,5 +558,5 @@ namespace CHECK_TRUE(broker.accepts(MESSAGE5)); CHECK_TRUE(broker.accepts(MESSAGE6)); } - }; + } } diff --git a/test/test_message_bus.cpp b/test/test_message_bus.cpp index e7fde856..2dfe8964 100644 --- a/test/test_message_bus.cpp +++ b/test/test_message_bus.cpp @@ -1007,5 +1007,5 @@ namespace CHECK_TRUE(bus1.accepts(MESSAGE6)); CHECK_FALSE(bus1.accepts(MESSAGE7)); } - }; + } } diff --git a/test/test_message_packet.cpp b/test/test_message_packet.cpp index a13830c8..206d9f8c 100644 --- a/test/test_message_packet.cpp +++ b/test/test_message_packet.cpp @@ -487,5 +487,5 @@ namespace obj.Push(packet1); obj.Push(packet2); } - }; + } } diff --git a/test/test_message_router.cpp b/test/test_message_router.cpp index 43bf1174..e7d94ac1 100644 --- a/test/test_message_router.cpp +++ b/test/test_message_router.cpp @@ -733,5 +733,5 @@ namespace CHECK_FALSE(router.unknown_message_received); } - }; + } } diff --git a/test/test_message_router_registry.cpp b/test/test_message_router_registry.cpp index 8819b6a3..6dbdcb46 100644 --- a/test/test_message_router_registry.cpp +++ b/test/test_message_router_registry.cpp @@ -392,5 +392,5 @@ namespace CHECK_EQUAL(ROUTER1, (*citr).get_message_router_id()); CHECK_EQUAL(ROUTER1, citr->get_message_router_id()); } - }; + } } diff --git a/test/test_message_timer.cpp b/test/test_message_timer.cpp index 1e4eca2e..9c137805 100644 --- a/test/test_message_timer.cpp +++ b/test/test_message_timer.cpp @@ -819,5 +819,5 @@ namespace CHECK(router1.message2.size() < 65U); } #endif - }; + } } diff --git a/test/test_message_timer_atomic.cpp b/test/test_message_timer_atomic.cpp index b612cd46..87e264b3 100644 --- a/test/test_message_timer_atomic.cpp +++ b/test/test_message_timer_atomic.cpp @@ -819,5 +819,5 @@ namespace CHECK(router1.message2.size() < 65U); } #endif - }; + } } diff --git a/test/test_message_timer_interrupt.cpp b/test/test_message_timer_interrupt.cpp index 7c66edb9..a1771bf1 100644 --- a/test/test_message_timer_interrupt.cpp +++ b/test/test_message_timer_interrupt.cpp @@ -902,5 +902,5 @@ namespace // Check the CHECK_EQUAL(0U, ScopedGuard::guard_count); } - }; + } } diff --git a/test/test_message_timer_locked.cpp b/test/test_message_timer_locked.cpp index 6d7c1215..888434c0 100644 --- a/test/test_message_timer_locked.cpp +++ b/test/test_message_timer_locked.cpp @@ -958,5 +958,5 @@ namespace CHECK_EQUAL(0U, locks.lock_count); } #endif - }; + } } diff --git a/test/test_multi_array.cpp b/test/test_multi_array.cpp index 00c8670c..08085efb 100644 --- a/test/test_multi_array.cpp +++ b/test/test_multi_array.cpp @@ -488,5 +488,5 @@ namespace CHECK(data >= data); CHECK(!(lesser >= data)); } - }; + } } diff --git a/test/test_multi_range.cpp b/test/test_multi_range.cpp index a72177c5..82604d98 100644 --- a/test/test_multi_range.cpp +++ b/test/test_multi_range.cpp @@ -431,5 +431,5 @@ namespace outer.detach_all(); } - }; + } } diff --git a/test/test_multi_span.cpp b/test/test_multi_span.cpp index 19fbee95..2c150e35 100644 --- a/test/test_multi_span.cpp +++ b/test/test_multi_span.cpp @@ -761,5 +761,5 @@ namespace CHECK_EQUAL(expected[i], ms_int[i]); } } - }; + } } diff --git a/test/test_multi_vector.cpp b/test/test_multi_vector.cpp index 05efd8d4..322b84b1 100644 --- a/test/test_multi_vector.cpp +++ b/test/test_multi_vector.cpp @@ -574,5 +574,5 @@ namespace CHECK(data >= data); CHECK(!(lesser >= data)); } - }; + } } diff --git a/test/test_multimap.cpp b/test/test_multimap.cpp index a6a29e03..667cccea 100644 --- a/test/test_multimap.cpp +++ b/test/test_multimap.cpp @@ -1691,5 +1691,5 @@ namespace CHECK(!data.contains(std::string("99"))); CHECK(!data.contains(Key("99"))); } - }; + } } diff --git a/test/test_multiset.cpp b/test/test_multiset.cpp index aae2b234..47bca6e1 100644 --- a/test/test_multiset.cpp +++ b/test/test_multiset.cpp @@ -1621,5 +1621,5 @@ namespace CHECK(!data.contains(99)); CHECK(!data.contains(Key(99))); } - }; + } } diff --git a/test/test_murmur3.cpp b/test/test_murmur3.cpp index 24a91dd3..a6fd62ff 100644 --- a/test/test_murmur3.cpp +++ b/test/test_murmur3.cpp @@ -135,6 +135,6 @@ namespace MurmurHash3_x86_32((uint8_t*)&data2[0], data2.size() * sizeof(uint32_t), 0, &compare2); CHECK_EQUAL(compare2, hash2); } - }; + } } diff --git a/test/test_not_null_pointer.cpp b/test/test_not_null_pointer.cpp index d9835846..fd6eb4ed 100644 --- a/test/test_not_null_pointer.cpp +++ b/test/test_not_null_pointer.cpp @@ -160,5 +160,5 @@ namespace CHECK_FALSE(nn1 >= nn2); CHECK_TRUE(nn2 >= nn1); } - }; + } } \ No newline at end of file diff --git a/test/test_not_null_pointer_constexpr.cpp b/test/test_not_null_pointer_constexpr.cpp index 5cf53881..9ca9f524 100644 --- a/test/test_not_null_pointer_constexpr.cpp +++ b/test/test_not_null_pointer_constexpr.cpp @@ -148,7 +148,7 @@ namespace CHECK_EQUAL(s.x, x1); CHECK_EQUAL(s.get(), x2); } - }; + } } #endif diff --git a/test/test_numeric.cpp b/test/test_numeric.cpp index 8cb8b238..6d8a0802 100644 --- a/test/test_numeric.cpp +++ b/test/test_numeric.cpp @@ -204,5 +204,5 @@ namespace CHECK_CLOSE(10.0, etl::lerp(10.0, 10.0, 1), 0.001); CHECK_CLOSE(10.0, etl::lerp(10, 10, 1), 0.001); } - }; + } } diff --git a/test/test_optional.cpp b/test/test_optional.cpp index 42ab7199..99d8a312 100644 --- a/test/test_optional.cpp +++ b/test/test_optional.cpp @@ -1034,5 +1034,5 @@ namespace CHECK_EQUAL(1, (*opt3)[0]); CHECK_EQUAL(20, (*opt3)[1]); } - }; + } } diff --git a/test/test_overload.cpp b/test/test_overload.cpp index 298c8c32..ba14ac1c 100644 --- a/test/test_overload.cpp +++ b/test/test_overload.cpp @@ -162,7 +162,7 @@ namespace CHECK(result.bd == false); CHECK(result.bs == true); } - }; + } } #endif diff --git a/test/test_parameter_pack.cpp b/test/test_parameter_pack.cpp index 83aa08d6..ce5a15c2 100644 --- a/test/test_parameter_pack.cpp +++ b/test/test_parameter_pack.cpp @@ -87,5 +87,5 @@ namespace // Static assert //CHECK((std::is_same_v>)); } - }; + } } diff --git a/test/test_parameter_type.cpp b/test/test_parameter_type.cpp index 3075f3cc..5a45131f 100644 --- a/test/test_parameter_type.cpp +++ b/test/test_parameter_type.cpp @@ -86,5 +86,5 @@ namespace b = !etl::is_reference::type>::value; CHECK(b); } - }; + } } diff --git a/test/test_parity_checksum.cpp b/test/test_parity_checksum.cpp index 74ac46c3..f4050fbf 100644 --- a/test/test_parity_checksum.cpp +++ b/test/test_parity_checksum.cpp @@ -142,6 +142,6 @@ namespace CHECK_EQUAL(hash1, hash2); CHECK_EQUAL(hash1, hash3); } - }; + } } diff --git a/test/test_pearson.cpp b/test/test_pearson.cpp index 06cddab7..2327948f 100644 --- a/test/test_pearson.cpp +++ b/test/test_pearson.cpp @@ -174,6 +174,6 @@ namespace hash_t hash3 = etl::pearson(data3.rbegin(), data3.rend()); CHECK(hash1 == hash3); } - }; + } } diff --git a/test/test_pool.cpp b/test/test_pool.cpp index df9b088c..2df96149 100644 --- a/test/test_pool.cpp +++ b/test/test_pool.cpp @@ -415,9 +415,9 @@ namespace etl::generic_pool pool; - uint8_t* p1 = nullptr; - uint32_t* p2 = nullptr; - double* p3 = nullptr; + uint8_t* p1 = nullptr; + uint32_t* p2 = nullptr; + double* p3 = nullptr; Test_Data* p4 = nullptr; (void)p1; @@ -430,430 +430,430 @@ namespace CHECK_NO_THROW(p3 = pool.allocate()); CHECK_NO_THROW(p4 = pool.allocate()); } - }; - //************************************************************************* - TEST(test_create_destroy) - { - etl::pool pool0; - etl::pool pool1; - etl::pool pool2; - etl::pool pool3; - etl::pool pool4; - - D0* p0 = pool0.create(); - D1* p1 = pool1.create("1"); - D2* p2 = pool2.create("1", "2"); - D3* p3 = pool3.create("1", "2", "3"); - D4* p4 = pool4.create("1", "2", "3", "4"); - - CHECK_EQUAL(pool0.max_size() - 1, pool0.available()); - CHECK_EQUAL(1U, pool0.size()); - - CHECK_EQUAL(pool1.max_size() - 1, pool1.available()); - CHECK_EQUAL(1U, pool1.size()); - - CHECK_EQUAL(pool2.max_size() - 1, pool2.available()); - CHECK_EQUAL(1U, pool2.size()); - - CHECK_EQUAL(pool3.max_size() - 1, pool3.available()); - CHECK_EQUAL(1U, pool3.size()); - - CHECK_EQUAL(pool4.max_size() - 1, pool4.available()); - CHECK_EQUAL(1U, pool4.size()); - - CHECK_EQUAL(D0(), *p0); - CHECK_EQUAL(D1("1"), *p1); - CHECK_EQUAL(D2("1", "2"), *p2); - CHECK_EQUAL(D3("1", "2", "3"), *p3); - CHECK_EQUAL(D4("1", "2", "3", "4"), *p4); - - pool0.destroy(p0); - pool1.destroy(p1); - pool2.destroy(p2); - pool3.destroy(p3); - pool4.destroy(p4); - - CHECK_EQUAL(pool0.max_size(), pool0.available()); - CHECK_EQUAL(0U, pool0.size()); - - CHECK_EQUAL(pool1.max_size(), pool1.available()); - CHECK_EQUAL(0U, pool1.size()); - - CHECK_EQUAL(pool2.max_size(), pool2.available()); - CHECK_EQUAL(0U, pool2.size()); - - CHECK_EQUAL(pool3.max_size(), pool3.available()); - CHECK_EQUAL(0U, pool3.size()); - - CHECK_EQUAL(pool4.max_size(), pool4.available()); - CHECK_EQUAL(0U, pool4.size()); - } - - //************************************************************************* - TEST(test_allocate_release_non_class) - { - etl::pool pool; - - int* i = pool.allocate(); - pool.release(i); - } - - //************************************************************************* - TEST(test_issue_406_pool_of_c_array) - { - using elem_type = uint8_t[10]; - - etl::pool memPool{}; - - CHECK_EQUAL(3, memPool.available()); - CHECK_EQUAL(0, memPool.size()); - - elem_type* memory = memPool.allocate(); - - CHECK_EQUAL(2, memPool.available()); - CHECK_EQUAL(1, memPool.size()); - - memPool.release(memory); - - CHECK_EQUAL(3, memPool.available()); - CHECK_EQUAL(0, memPool.size()); - } - - //************************************************************************* - TEST(test_iterators) - { - etl::pool pool0; - - etl::ipool::iterator begin = pool0.begin(); - etl::ipool::iterator end = pool0.end(); - - CHECK(begin == end); - CHECK(!(begin != end)); - CHECK_EQUAL(etl::distance(begin, end), 0); - - int* a = pool0.allocate(); - *a = 1; - - begin = pool0.begin(); - end = pool0.end(); - CHECK(begin != end); - CHECK(!(begin == end)); - CHECK_EQUAL(etl::distance(begin, end), 1); - - int* b = pool0.allocate(); - *b = 2; - - begin = pool0.begin(); - end = pool0.end(); - CHECK(begin != end); - CHECK(!(begin == end)); - CHECK_EQUAL(etl::distance(begin, end), 2); - - // post increment - for (auto i = pool0.begin(); i != pool0.end(); i++) + //************************************************************************* + TEST(test_create_destroy) { - CHECK(*reinterpret_cast(*i) == 1 || *reinterpret_cast(*i) == 2); + etl::pool pool0; + etl::pool pool1; + etl::pool pool2; + etl::pool pool3; + etl::pool pool4; + + D0* p0 = pool0.create(); + D1* p1 = pool1.create("1"); + D2* p2 = pool2.create("1", "2"); + D3* p3 = pool3.create("1", "2", "3"); + D4* p4 = pool4.create("1", "2", "3", "4"); + + CHECK_EQUAL(pool0.max_size() - 1, pool0.available()); + CHECK_EQUAL(1U, pool0.size()); + + CHECK_EQUAL(pool1.max_size() - 1, pool1.available()); + CHECK_EQUAL(1U, pool1.size()); + + CHECK_EQUAL(pool2.max_size() - 1, pool2.available()); + CHECK_EQUAL(1U, pool2.size()); + + CHECK_EQUAL(pool3.max_size() - 1, pool3.available()); + CHECK_EQUAL(1U, pool3.size()); + + CHECK_EQUAL(pool4.max_size() - 1, pool4.available()); + CHECK_EQUAL(1U, pool4.size()); + + CHECK_EQUAL(D0(), *p0); + CHECK_EQUAL(D1("1"), *p1); + CHECK_EQUAL(D2("1", "2"), *p2); + CHECK_EQUAL(D3("1", "2", "3"), *p3); + CHECK_EQUAL(D4("1", "2", "3", "4"), *p4); + + pool0.destroy(p0); + pool1.destroy(p1); + pool2.destroy(p2); + pool3.destroy(p3); + pool4.destroy(p4); + + CHECK_EQUAL(pool0.max_size(), pool0.available()); + CHECK_EQUAL(0U, pool0.size()); + + CHECK_EQUAL(pool1.max_size(), pool1.available()); + CHECK_EQUAL(0U, pool1.size()); + + CHECK_EQUAL(pool2.max_size(), pool2.available()); + CHECK_EQUAL(0U, pool2.size()); + + CHECK_EQUAL(pool3.max_size(), pool3.available()); + CHECK_EQUAL(0U, pool3.size()); + + CHECK_EQUAL(pool4.max_size(), pool4.available()); + CHECK_EQUAL(0U, pool4.size()); } - // pre increment - for (auto i = pool0.begin(); i != pool0.end(); ++i) + //************************************************************************* + TEST(test_allocate_release_non_class) { - CHECK(*reinterpret_cast(*i) == 1 || *reinterpret_cast(*i) == 2); + etl::pool pool; + + int* i = pool.allocate(); + pool.release(i); } - int* c = pool0.allocate(); - *c = 3; - - begin = pool0.begin(); - end = pool0.end(); - CHECK(begin != end); - CHECK(!(begin == end)); - CHECK_EQUAL(etl::distance(begin, end), 3); - - pool0.release(b); - - begin = pool0.begin(); - end = pool0.end(); - CHECK(begin != end); - CHECK(!(begin == end)); - CHECK_EQUAL(etl::distance(begin, end), 2); - - int* d = pool0.allocate(); - *d = 4; - - begin = pool0.begin(); - end = pool0.end(); - CHECK(begin != end); - CHECK(!(begin == end)); - CHECK_EQUAL(etl::distance(begin, end), 3); - - b = pool0.allocate(); - *b = 2; - - begin = pool0.begin(); - end = pool0.end(); - CHECK(begin != end); - CHECK(!(begin == end)); - CHECK_EQUAL(etl::distance(begin, end), 4); - - // post increment - for (auto i = pool0.begin(); i != pool0.end(); i++) + //************************************************************************* + TEST(test_issue_406_pool_of_c_array) { - CHECK(*reinterpret_cast(*i) >= 1 && *reinterpret_cast(*i) <= 4); + using elem_type = uint8_t[10]; + + etl::pool memPool{}; + + CHECK_EQUAL(3, memPool.available()); + CHECK_EQUAL(0, memPool.size()); + + elem_type* memory = memPool.allocate(); + + CHECK_EQUAL(2, memPool.available()); + CHECK_EQUAL(1, memPool.size()); + + memPool.release(memory); + + CHECK_EQUAL(3, memPool.available()); + CHECK_EQUAL(0, memPool.size()); } - // pre increment - for (auto i = pool0.begin(); i != pool0.end(); ++i) + //************************************************************************* + TEST(test_iterators) { - CHECK(*reinterpret_cast(*i) >= 1 && *reinterpret_cast(*i) <= 4); - } + etl::pool pool0; - pool0.release(b); + etl::ipool::iterator begin = pool0.begin(); + etl::ipool::iterator end = pool0.end(); - begin = pool0.begin(); - end = pool0.end(); - CHECK(begin != end); - CHECK(!(begin == end)); - CHECK_EQUAL(etl::distance(begin, end), 3); + CHECK(begin == end); + CHECK(!(begin != end)); + CHECK_EQUAL(etl::distance(begin, end), 0); - pool0.release(a); + int* a = pool0.allocate(); + *a = 1; - begin = pool0.begin(); - end = pool0.end(); - CHECK(begin != end); - CHECK(!(begin == end)); - CHECK_EQUAL(etl::distance(begin, end), 2); + begin = pool0.begin(); + end = pool0.end(); + CHECK(begin != end); + CHECK(!(begin == end)); + CHECK_EQUAL(etl::distance(begin, end), 1); - pool0.release(d); + int* b = pool0.allocate(); + *b = 2; - begin = pool0.begin(); - end = pool0.end(); - CHECK(begin != end); - CHECK(!(begin == end)); - CHECK_EQUAL(etl::distance(begin, end), 1); - - auto& v = begin.get(); - v = 1; - - pool0.release(c); - - begin = pool0.begin(); - end = pool0.end(); - CHECK(begin == end); - CHECK(!(begin != end)); - CHECK_EQUAL(etl::distance(begin, end), 0); - } - - //************************************************************************* - TEST(test_const_iterators) - { - etl::pool pool0; - - etl::ipool::const_iterator begin = pool0.begin(); - etl::ipool::const_iterator end = pool0.end(); - - CHECK(begin == end); - CHECK(!(begin != end)); - CHECK_EQUAL(etl::distance(begin, end), 0); - - int* a = pool0.allocate(); - *a = 1; - - begin = pool0.cbegin(); - end = pool0.cend(); - CHECK(begin != end); - CHECK(!(begin == end)); - CHECK_EQUAL(etl::distance(begin, end), 1); - - int* b = pool0.allocate(); - *b = 2; - - begin = pool0.begin(); - end = pool0.end(); - CHECK(begin != end); - CHECK(!(begin == end)); - CHECK_EQUAL(etl::distance(begin, end), 2); - - // post increment - for (auto i = pool0.begin(); i != pool0.end(); i++) - { - CHECK(*reinterpret_cast(*i) == 1 || *reinterpret_cast(*i) == 2); - } - - // pre increment - for (auto i = pool0.begin(); i != pool0.end(); ++i) - { - CHECK(*reinterpret_cast(*i) == 1 || *reinterpret_cast(*i) == 2); - } - - int* c = pool0.allocate(); - *c = 3; - - begin = pool0.cbegin(); - end = pool0.cend(); - CHECK(begin != end); - CHECK(!(begin == end)); - CHECK_EQUAL(etl::distance(begin, end), 3); - - pool0.release(b); - - begin = pool0.begin(); - end = pool0.end(); - CHECK(begin != end); - CHECK(!(begin == end)); - CHECK_EQUAL(etl::distance(begin, end), 2); - - int* d = pool0.allocate(); - *d = 4; - - begin = pool0.cbegin(); - end = pool0.cend(); - CHECK(begin != end); - CHECK(!(begin == end)); - CHECK_EQUAL(etl::distance(begin, end), 3); - - b = pool0.allocate(); - *b = 2; - - begin = pool0.cbegin(); - end = pool0.cend(); - CHECK(begin != end); - CHECK(!(begin == end)); - CHECK_EQUAL(etl::distance(begin, end), 4); - - // post increment - for (auto i = pool0.begin(); i != pool0.end(); i++) - { - CHECK(*reinterpret_cast(*i) >= 1 && *reinterpret_cast(*i) <= 4); - } - - // pre increment - for (auto i = pool0.cbegin(); i != pool0.cend(); ++i) - { - CHECK(*reinterpret_cast(*i) >= 1 && *reinterpret_cast(*i) <= 4); - } - - pool0.release(b); - - begin = pool0.begin(); - end = pool0.end(); - CHECK(begin != end); - CHECK(!(begin == end)); - CHECK_EQUAL(etl::distance(begin, end), 3); - - pool0.release(a); - - begin = pool0.cbegin(); - end = pool0.cend(); - CHECK(begin != end); - CHECK(!(begin == end)); - CHECK_EQUAL(etl::distance(begin, end), 2); - - pool0.release(d); - - begin = pool0.begin(); - end = pool0.end(); - CHECK(begin != end); - CHECK(!(begin == end)); - CHECK_EQUAL(etl::distance(begin, end), 1); - - const auto& v = begin.get(); - CHECK(v != 0); - - pool0.release(c); - - begin = pool0.cbegin(); - end = pool0.cend(); - CHECK(begin == end); - CHECK(!(begin != end)); - CHECK_EQUAL(etl::distance(begin, end), 0); - } - - //************************************************************************* - TEST(test_releaser_functor_with_unique_ptr) - { - etl::pool pool; - auto pool_deleter = [&pool](S* ptr) { pool.release(ptr); }; - using Unique = etl::unique_ptr; - - S::instance_count = 0; - - CHECK_EQUAL(10, pool.available()); - - { - S* ps; - - ps = pool.allocate(); - ::new(ps) S(1, 2); - Unique us1(ps, pool_deleter); - CHECK_EQUAL(1, S::instance_count); - CHECK_EQUAL(1, us1->a); - CHECK_EQUAL(2, us1->b); - CHECK_EQUAL(9, pool.available()); + begin = pool0.begin(); + end = pool0.end(); + CHECK(begin != end); + CHECK(!(begin == end)); + CHECK_EQUAL(etl::distance(begin, end), 2); + // post increment + for (auto i = pool0.begin(); i != pool0.end(); i++) { - ps = pool.allocate(); - ::new(ps) S(3, 4); - Unique us2(ps, pool_deleter); - CHECK_EQUAL(2, S::instance_count); - CHECK_EQUAL(3, us2->a); - CHECK_EQUAL(4, us2->b); - CHECK_EQUAL(8, pool.available()); - us2->~S(); + CHECK(*reinterpret_cast(*i) == 1 || *reinterpret_cast(*i) == 2); } - ps = pool.allocate(); - ::new(ps) S(5, 6); - Unique us3(ps, pool_deleter); - CHECK_EQUAL(2, S::instance_count); - CHECK_EQUAL(5, us3->a); - CHECK_EQUAL(6, us3->b); - CHECK_EQUAL(8, pool.available()); - us1->~S(); - us3->~S(); + // pre increment + for (auto i = pool0.begin(); i != pool0.end(); ++i) + { + CHECK(*reinterpret_cast(*i) == 1 || *reinterpret_cast(*i) == 2); + } + + int* c = pool0.allocate(); + *c = 3; + + begin = pool0.begin(); + end = pool0.end(); + CHECK(begin != end); + CHECK(!(begin == end)); + CHECK_EQUAL(etl::distance(begin, end), 3); + + pool0.release(b); + + begin = pool0.begin(); + end = pool0.end(); + CHECK(begin != end); + CHECK(!(begin == end)); + CHECK_EQUAL(etl::distance(begin, end), 2); + + int* d = pool0.allocate(); + *d = 4; + + begin = pool0.begin(); + end = pool0.end(); + CHECK(begin != end); + CHECK(!(begin == end)); + CHECK_EQUAL(etl::distance(begin, end), 3); + + b = pool0.allocate(); + *b = 2; + + begin = pool0.begin(); + end = pool0.end(); + CHECK(begin != end); + CHECK(!(begin == end)); + CHECK_EQUAL(etl::distance(begin, end), 4); + + // post increment + for (auto i = pool0.begin(); i != pool0.end(); i++) + { + CHECK(*reinterpret_cast(*i) >= 1 && *reinterpret_cast(*i) <= 4); + } + + // pre increment + for (auto i = pool0.begin(); i != pool0.end(); ++i) + { + CHECK(*reinterpret_cast(*i) >= 1 && *reinterpret_cast(*i) <= 4); + } + + pool0.release(b); + + begin = pool0.begin(); + end = pool0.end(); + CHECK(begin != end); + CHECK(!(begin == end)); + CHECK_EQUAL(etl::distance(begin, end), 3); + + pool0.release(a); + + begin = pool0.begin(); + end = pool0.end(); + CHECK(begin != end); + CHECK(!(begin == end)); + CHECK_EQUAL(etl::distance(begin, end), 2); + + pool0.release(d); + + begin = pool0.begin(); + end = pool0.end(); + CHECK(begin != end); + CHECK(!(begin == end)); + CHECK_EQUAL(etl::distance(begin, end), 1); + + auto& v = begin.get(); + v = 1; + + pool0.release(c); + + begin = pool0.begin(); + end = pool0.end(); + CHECK(begin == end); + CHECK(!(begin != end)); + CHECK_EQUAL(etl::distance(begin, end), 0); } - CHECK_EQUAL(0, S::instance_count); - CHECK_EQUAL(10, pool.available()); - } - - //************************************************************************* - TEST(test_destroyer_functor_with_unique_ptr) - { - etl::pool pool; - auto pool_deleter = [&pool](S* ptr) { pool.destroy(ptr); }; - using Unique = etl::unique_ptr; - - S::instance_count = 0; - - CHECK_EQUAL(10, pool.available()); - + //************************************************************************* + TEST(test_const_iterators) { - Unique us1(pool.create(1, 2), pool_deleter); - CHECK_EQUAL(1, S::instance_count); - CHECK_EQUAL(1, us1->a); - CHECK_EQUAL(2, us1->b); - CHECK_EQUAL(9, pool.available()); + etl::pool pool0; + + etl::ipool::const_iterator begin = pool0.begin(); + etl::ipool::const_iterator end = pool0.end(); + + CHECK(begin == end); + CHECK(!(begin != end)); + CHECK_EQUAL(etl::distance(begin, end), 0); + + int* a = pool0.allocate(); + *a = 1; + + begin = pool0.cbegin(); + end = pool0.cend(); + CHECK(begin != end); + CHECK(!(begin == end)); + CHECK_EQUAL(etl::distance(begin, end), 1); + + int* b = pool0.allocate(); + *b = 2; + + begin = pool0.begin(); + end = pool0.end(); + CHECK(begin != end); + CHECK(!(begin == end)); + CHECK_EQUAL(etl::distance(begin, end), 2); + + // post increment + for (auto i = pool0.begin(); i != pool0.end(); i++) + { + CHECK(*reinterpret_cast(*i) == 1 || *reinterpret_cast(*i) == 2); + } + + // pre increment + for (auto i = pool0.begin(); i != pool0.end(); ++i) + { + CHECK(*reinterpret_cast(*i) == 1 || *reinterpret_cast(*i) == 2); + } + + int* c = pool0.allocate(); + *c = 3; + + begin = pool0.cbegin(); + end = pool0.cend(); + CHECK(begin != end); + CHECK(!(begin == end)); + CHECK_EQUAL(etl::distance(begin, end), 3); + + pool0.release(b); + + begin = pool0.begin(); + end = pool0.end(); + CHECK(begin != end); + CHECK(!(begin == end)); + CHECK_EQUAL(etl::distance(begin, end), 2); + + int* d = pool0.allocate(); + *d = 4; + + begin = pool0.cbegin(); + end = pool0.cend(); + CHECK(begin != end); + CHECK(!(begin == end)); + CHECK_EQUAL(etl::distance(begin, end), 3); + + b = pool0.allocate(); + *b = 2; + + begin = pool0.cbegin(); + end = pool0.cend(); + CHECK(begin != end); + CHECK(!(begin == end)); + CHECK_EQUAL(etl::distance(begin, end), 4); + + // post increment + for (auto i = pool0.begin(); i != pool0.end(); i++) + { + CHECK(*reinterpret_cast(*i) >= 1 && *reinterpret_cast(*i) <= 4); + } + + // pre increment + for (auto i = pool0.cbegin(); i != pool0.cend(); ++i) + { + CHECK(*reinterpret_cast(*i) >= 1 && *reinterpret_cast(*i) <= 4); + } + + pool0.release(b); + + begin = pool0.begin(); + end = pool0.end(); + CHECK(begin != end); + CHECK(!(begin == end)); + CHECK_EQUAL(etl::distance(begin, end), 3); + + pool0.release(a); + + begin = pool0.cbegin(); + end = pool0.cend(); + CHECK(begin != end); + CHECK(!(begin == end)); + CHECK_EQUAL(etl::distance(begin, end), 2); + + pool0.release(d); + + begin = pool0.begin(); + end = pool0.end(); + CHECK(begin != end); + CHECK(!(begin == end)); + CHECK_EQUAL(etl::distance(begin, end), 1); + + const auto& v = begin.get(); + CHECK(v != 0); + + pool0.release(c); + + begin = pool0.cbegin(); + end = pool0.cend(); + CHECK(begin == end); + CHECK(!(begin != end)); + CHECK_EQUAL(etl::distance(begin, end), 0); + } + + //************************************************************************* + TEST(test_releaser_functor_with_unique_ptr) + { + etl::pool pool; + auto pool_deleter = [&pool](S* ptr) { pool.release(ptr); }; + using Unique = etl::unique_ptr; + + S::instance_count = 0; + + CHECK_EQUAL(10, pool.available()); { - Unique us2(pool.create(3, 4), pool_deleter); + S* ps; + + ps = pool.allocate(); + ::new(ps) S(1, 2); + Unique us1(ps, pool_deleter); + CHECK_EQUAL(1, S::instance_count); + CHECK_EQUAL(1, us1->a); + CHECK_EQUAL(2, us1->b); + CHECK_EQUAL(9, pool.available()); + + { + ps = pool.allocate(); + ::new(ps) S(3, 4); + Unique us2(ps, pool_deleter); + CHECK_EQUAL(2, S::instance_count); + CHECK_EQUAL(3, us2->a); + CHECK_EQUAL(4, us2->b); + CHECK_EQUAL(8, pool.available()); + us2->~S(); + } + + ps = pool.allocate(); + ::new(ps) S(5, 6); + Unique us3(ps, pool_deleter); CHECK_EQUAL(2, S::instance_count); - CHECK_EQUAL(3, us2->a); - CHECK_EQUAL(4, us2->b); + CHECK_EQUAL(5, us3->a); + CHECK_EQUAL(6, us3->b); + CHECK_EQUAL(8, pool.available()); + us1->~S(); + us3->~S(); + } + + CHECK_EQUAL(0, S::instance_count); + CHECK_EQUAL(10, pool.available()); + } + + //************************************************************************* + TEST(test_destroyer_functor_with_unique_ptr) + { + etl::pool pool; + auto pool_deleter = [&pool](S* ptr) { pool.destroy(ptr); }; + using Unique = etl::unique_ptr; + + S::instance_count = 0; + + CHECK_EQUAL(10, pool.available()); + + { + Unique us1(pool.create(1, 2), pool_deleter); + CHECK_EQUAL(1, S::instance_count); + CHECK_EQUAL(1, us1->a); + CHECK_EQUAL(2, us1->b); + CHECK_EQUAL(9, pool.available()); + + { + Unique us2(pool.create(3, 4), pool_deleter); + CHECK_EQUAL(2, S::instance_count); + CHECK_EQUAL(3, us2->a); + CHECK_EQUAL(4, us2->b); + CHECK_EQUAL(8, pool.available()); + } + + CHECK_EQUAL(1, S::instance_count); + + Unique us3(pool.create(5, 6), pool_deleter); + CHECK_EQUAL(2, S::instance_count); + CHECK_EQUAL(5, us3->a); + CHECK_EQUAL(6, us3->b); CHECK_EQUAL(8, pool.available()); } - CHECK_EQUAL(1, S::instance_count); - - Unique us3(pool.create(5, 6), pool_deleter); - CHECK_EQUAL(2, S::instance_count); - CHECK_EQUAL(5, us3->a); - CHECK_EQUAL(6, us3->b); - CHECK_EQUAL(8, pool.available()); + CHECK_EQUAL(0, S::instance_count); + CHECK_EQUAL(10, pool.available()); } - - CHECK_EQUAL(0, S::instance_count); - CHECK_EQUAL(10, pool.available()); } } diff --git a/test/test_priority_queue.cpp b/test/test_priority_queue.cpp index c1f2d072..8d2b5067 100644 --- a/test/test_priority_queue.cpp +++ b/test/test_priority_queue.cpp @@ -650,5 +650,5 @@ namespace priority_queue2.pop(); } } - }; + } } diff --git a/test/test_pseudo_moving_average.cpp b/test/test_pseudo_moving_average.cpp index b640762b..a9b26f0e 100644 --- a/test/test_pseudo_moving_average.cpp +++ b/test/test_pseudo_moving_average.cpp @@ -344,5 +344,5 @@ namespace CHECK_CLOSE(2.82, cma.value(), 0.01); } - }; + } } diff --git a/test/test_quantize.cpp b/test/test_quantize.cpp index 1501d4c1..6c9802de 100644 --- a/test/test_quantize.cpp +++ b/test/test_quantize.cpp @@ -119,5 +119,5 @@ namespace bool isEqual = std::equal(output2.begin(), output2.end(), result2a.begin(), Compare()); CHECK(isEqual); } - }; + } } diff --git a/test/test_queue.cpp b/test/test_queue.cpp index 71d033f1..1f2a04cf 100644 --- a/test/test_queue.cpp +++ b/test/test_queue.cpp @@ -575,5 +575,5 @@ namespace CHECK_EQUAL(4, queue.front()); queue.pop(); } - }; + } } diff --git a/test/test_queue_lockable.cpp b/test/test_queue_lockable.cpp index 2bebeb09..893e5d2a 100644 --- a/test/test_queue_lockable.cpp +++ b/test/test_queue_lockable.cpp @@ -754,5 +754,5 @@ namespace } } #endif - }; + } } diff --git a/test/test_queue_lockable_small.cpp b/test/test_queue_lockable_small.cpp index c1bf69b2..bc123464 100644 --- a/test/test_queue_lockable_small.cpp +++ b/test/test_queue_lockable_small.cpp @@ -757,5 +757,5 @@ namespace } } #endif - }; + } } diff --git a/test/test_queue_memory_model_small.cpp b/test/test_queue_memory_model_small.cpp index d640cd8a..14aab550 100644 --- a/test/test_queue_memory_model_small.cpp +++ b/test/test_queue_memory_model_small.cpp @@ -550,5 +550,5 @@ namespace CHECK_EQUAL(4, queue.front()); queue.pop(); } - }; + } } diff --git a/test/test_queue_mpmc_mutex.cpp b/test/test_queue_mpmc_mutex.cpp index cdb6e6c1..96c9c4e0 100644 --- a/test/test_queue_mpmc_mutex.cpp +++ b/test/test_queue_mpmc_mutex.cpp @@ -508,10 +508,10 @@ namespace TEST(queue_threads) { push1.reserve(LENGTH / 2); - push2.reserve(LENGTH / 2);; + push2.reserve(LENGTH / 2); - pop1.reserve(LENGTH / 2);; - pop2.reserve(LENGTH / 2);; + pop1.reserve(LENGTH / 2); + pop2.reserve(LENGTH / 2); start = false; @@ -550,7 +550,7 @@ namespace } } #endif - }; + } } #endif diff --git a/test/test_queue_mpmc_mutex_small.cpp b/test/test_queue_mpmc_mutex_small.cpp index 7abf00fc..094cf7b5 100644 --- a/test/test_queue_mpmc_mutex_small.cpp +++ b/test/test_queue_mpmc_mutex_small.cpp @@ -533,10 +533,10 @@ namespace TEST(queue_threads) { push1.reserve(LENGTH / 2); - push2.reserve(LENGTH / 2);; + push2.reserve(LENGTH / 2); - pop1.reserve(LENGTH / 2);; - pop2.reserve(LENGTH / 2);; + pop1.reserve(LENGTH / 2); + pop2.reserve(LENGTH / 2); start = false; @@ -575,7 +575,7 @@ namespace } } #endif - }; + } } #endif diff --git a/test/test_queue_spsc_atomic.cpp b/test/test_queue_spsc_atomic.cpp index 232249e1..c69c2d2c 100644 --- a/test/test_queue_spsc_atomic.cpp +++ b/test/test_queue_spsc_atomic.cpp @@ -456,7 +456,7 @@ namespace } } #endif - }; + } } #endif diff --git a/test/test_queue_spsc_atomic_small.cpp b/test/test_queue_spsc_atomic_small.cpp index f1ed6fbc..3a9edde0 100644 --- a/test/test_queue_spsc_atomic_small.cpp +++ b/test/test_queue_spsc_atomic_small.cpp @@ -474,7 +474,7 @@ namespace } } #endif - }; + } } #endif diff --git a/test/test_queue_spsc_isr.cpp b/test/test_queue_spsc_isr.cpp index 2d80f4db..3e26aeaf 100644 --- a/test/test_queue_spsc_isr.cpp +++ b/test/test_queue_spsc_isr.cpp @@ -712,5 +712,5 @@ namespace } } #endif - }; + } } diff --git a/test/test_queue_spsc_isr_small.cpp b/test/test_queue_spsc_isr_small.cpp index b55f3cd5..79765f4e 100644 --- a/test/test_queue_spsc_isr_small.cpp +++ b/test/test_queue_spsc_isr_small.cpp @@ -730,5 +730,5 @@ namespace } } #endif - }; + } } diff --git a/test/test_queue_spsc_locked.cpp b/test/test_queue_spsc_locked.cpp index 993e5e78..be60cbab 100644 --- a/test/test_queue_spsc_locked.cpp +++ b/test/test_queue_spsc_locked.cpp @@ -720,5 +720,5 @@ namespace } } #endif - }; + } } diff --git a/test/test_queue_spsc_locked_small.cpp b/test/test_queue_spsc_locked_small.cpp index 644f0a81..edb93fc0 100644 --- a/test/test_queue_spsc_locked_small.cpp +++ b/test/test_queue_spsc_locked_small.cpp @@ -737,5 +737,5 @@ namespace } } #endif - }; + } } diff --git a/test/test_random.cpp b/test/test_random.cpp index 615c5b82..b479d3e8 100644 --- a/test/test_random.cpp +++ b/test/test_random.cpp @@ -411,6 +411,5 @@ namespace CHECK(n <= high); } } - - }; + } } diff --git a/test/test_ratio.cpp b/test/test_ratio.cpp index 76f67fda..cd71a410 100644 --- a/test/test_ratio.cpp +++ b/test/test_ratio.cpp @@ -225,6 +225,5 @@ namespace CHECK((etl::ratio_greater_equal_v)); #endif } - }; - + } } diff --git a/test/test_reference_flat_map.cpp b/test/test_reference_flat_map.cpp index f16bf664..47df8185 100644 --- a/test/test_reference_flat_map.cpp +++ b/test/test_reference_flat_map.cpp @@ -976,5 +976,5 @@ namespace CHECK(initial1 != different); } - }; + } } diff --git a/test/test_reference_flat_multimap.cpp b/test/test_reference_flat_multimap.cpp index 2c68e161..ef04031c 100644 --- a/test/test_reference_flat_multimap.cpp +++ b/test/test_reference_flat_multimap.cpp @@ -918,5 +918,5 @@ namespace CHECK_EQUAL(compare_data.count(4), data.count(Key(4))); CHECK_EQUAL(compare_data.count(5), data.count(Key(5))); } - }; + } } diff --git a/test/test_reference_flat_multiset.cpp b/test/test_reference_flat_multiset.cpp index 52f55c94..7927776a 100644 --- a/test/test_reference_flat_multiset.cpp +++ b/test/test_reference_flat_multiset.cpp @@ -837,5 +837,5 @@ namespace CHECK_EQUAL(compare_data.count(N3), data.count(N3)); CHECK_EQUAL(compare_data.count(N4), data.count(N4)); } - }; + } } diff --git a/test/test_reference_flat_set.cpp b/test/test_reference_flat_set.cpp index be0834a3..4a5ea5a3 100644 --- a/test/test_reference_flat_set.cpp +++ b/test/test_reference_flat_set.cpp @@ -836,5 +836,5 @@ namespace CHECK(initial1 != different); } - }; + } } diff --git a/test/test_rescale.cpp b/test/test_rescale.cpp index 9f65dfd5..d57a2403 100644 --- a/test/test_rescale.cpp +++ b/test/test_rescale.cpp @@ -93,5 +93,5 @@ namespace bool isEqual = std::equal(output2.begin(), output2.end(), result2.begin(), Compare()); CHECK(isEqual); } - }; + } } diff --git a/test/test_result.cpp b/test/test_result.cpp index e2af3556..90a38109 100644 --- a/test/test_result.cpp +++ b/test/test_result.cpp @@ -370,5 +370,5 @@ namespace CHECK(output.v != input.v); CHECK(output2.v == input.v); } - }; + } } diff --git a/test/test_rms.cpp b/test/test_rms.cpp index 39ae6753..2dfb803f 100644 --- a/test/test_rms.cpp +++ b/test/test_rms.cpp @@ -66,5 +66,5 @@ namespace CHECK_CLOSE(5.21, result, 0.05); } - }; + } } diff --git a/test/test_rounded_integral_division.cpp b/test/test_rounded_integral_division.cpp index dc91390b..608d39df 100644 --- a/test/test_rounded_integral_division.cpp +++ b/test/test_rounded_integral_division.cpp @@ -891,5 +891,5 @@ namespace CHECK_EQUAL(std::numeric_limits::max(), etl::divide_round_half_odd(std::numeric_limits::max(), uint32_t(1))); CHECK_EQUAL(uint32_t(0U), etl::divide_round_half_odd(uint32_t(1), std::numeric_limits::max())); } - }; + } } diff --git a/test/test_scaled_rounding.cpp b/test/test_scaled_rounding.cpp index 518eada2..39aa4432 100644 --- a/test/test_scaled_rounding.cpp +++ b/test/test_scaled_rounding.cpp @@ -1843,5 +1843,5 @@ namespace CHECK_EQUAL(10, round_zero); } #endif - }; + } } diff --git a/test/test_set.cpp b/test/test_set.cpp index 0865eff8..852b6866 100644 --- a/test/test_set.cpp +++ b/test/test_set.cpp @@ -1468,5 +1468,5 @@ namespace CHECK(!data.contains(99)); CHECK(!data.contains(Key(99))); } - }; + } } diff --git a/test/test_smallest.cpp b/test/test_smallest.cpp index e7aaa290..68b3ce12 100644 --- a/test/test_smallest.cpp +++ b/test/test_smallest.cpp @@ -456,5 +456,5 @@ namespace type = etl::is_same>::value; CHECK(type); } - }; + } } diff --git a/test/test_span_dynamic_extent.cpp b/test/test_span_dynamic_extent.cpp index 1a11fee5..e9045504 100644 --- a/test/test_span_dynamic_extent.cpp +++ b/test/test_span_dynamic_extent.cpp @@ -1539,5 +1539,5 @@ namespace } #include "etl/private/diagnostic_pop.h" - }; + } } diff --git a/test/test_span_fixed_extent.cpp b/test/test_span_fixed_extent.cpp index 70d4350d..137bd9b8 100644 --- a/test/test_span_fixed_extent.cpp +++ b/test/test_span_fixed_extent.cpp @@ -1305,5 +1305,5 @@ namespace } #include "etl/private/diagnostic_pop.h" - }; + } } diff --git a/test/test_stack.cpp b/test/test_stack.cpp index 81d35b46..cd05ddf2 100644 --- a/test/test_stack.cpp +++ b/test/test_stack.cpp @@ -561,5 +561,5 @@ namespace stack.pop_into(i); CHECK_EQUAL(4, i); } - }; + } } diff --git a/test/test_standard_deviation.cpp b/test/test_standard_deviation.cpp index d5e52d98..ea9247dd 100644 --- a/test/test_standard_deviation.cpp +++ b/test/test_standard_deviation.cpp @@ -160,5 +160,5 @@ namespace variance_result = standard_deviation.get_variance(); CHECK_CLOSE(9.17, variance_result, 0.1); } - }; + } } diff --git a/test/test_state_chart.cpp b/test/test_state_chart.cpp index 53454bf6..8a005eba 100644 --- a/test/test_state_chart.cpp +++ b/test/test_state_chart.cpp @@ -599,5 +599,5 @@ namespace motorControl.process_event(EventId::ABORT); CHECK_EQUAL(StateId::IDLE, int(motorControl.get_state_id())); } - }; + } } diff --git a/test/test_state_chart_compile_time.cpp b/test/test_state_chart_compile_time.cpp index f3397834..a12c2a1a 100644 --- a/test/test_state_chart_compile_time.cpp +++ b/test/test_state_chart_compile_time.cpp @@ -608,5 +608,5 @@ namespace motorControlStateChart.process_event(EventId::ABORT); CHECK_EQUAL(StateId::IDLE, int(motorControlStateChart.get_state_id())); } - }; + } } diff --git a/test/test_state_chart_compile_time_with_data_parameter.cpp b/test/test_state_chart_compile_time_with_data_parameter.cpp index 55311a28..407d8ef4 100644 --- a/test/test_state_chart_compile_time_with_data_parameter.cpp +++ b/test/test_state_chart_compile_time_with_data_parameter.cpp @@ -504,5 +504,5 @@ namespace motorControlStateChart.process_event(EventId::ABORT, 5); CHECK_EQUAL(StateId::IDLE, int(motorControlStateChart.get_state_id())); } - }; + } } diff --git a/test/test_state_chart_with_data_parameter.cpp b/test/test_state_chart_with_data_parameter.cpp index 80377a60..23b75b15 100644 --- a/test/test_state_chart_with_data_parameter.cpp +++ b/test/test_state_chart_with_data_parameter.cpp @@ -495,5 +495,5 @@ namespace motorControl.process_event(EventId::ABORT, 5); CHECK_EQUAL(StateId::IDLE, int(motorControl.get_state_id())); } - }; + } } diff --git a/test/test_state_chart_with_rvalue_data_parameter.cpp b/test/test_state_chart_with_rvalue_data_parameter.cpp index 17d8ac4b..97307d33 100644 --- a/test/test_state_chart_with_rvalue_data_parameter.cpp +++ b/test/test_state_chart_with_rvalue_data_parameter.cpp @@ -511,5 +511,5 @@ namespace motorControl.process_event(EventId::ABORT, Data(5)); CHECK_EQUAL(StateId::IDLE, int(motorControl.get_state_id())); } - }; + } } diff --git a/test/test_string_char.cpp b/test/test_string_char.cpp index 6cf70b28..faa28d7e 100644 --- a/test/test_string_char.cpp +++ b/test/test_string_char.cpp @@ -5486,5 +5486,5 @@ namespace CHECK(text1 == sstream_view); } #endif - }; + } } diff --git a/test/test_string_char_external_buffer.cpp b/test/test_string_char_external_buffer.cpp index e644f578..15790f43 100644 --- a/test/test_string_char_external_buffer.cpp +++ b/test/test_string_char_external_buffer.cpp @@ -5787,5 +5787,5 @@ namespace CHECK(text1 == sstream_view); } #endif - }; + } } diff --git a/test/test_string_stream.cpp b/test/test_string_stream.cpp index e765950d..44414771 100644 --- a/test/test_string_stream.cpp +++ b/test/test_string_stream.cpp @@ -326,6 +326,6 @@ namespace CHECK_EQUAL(String(STR("Hello")), istr); } - }; + } } diff --git a/test/test_string_stream_u16.cpp b/test/test_string_stream_u16.cpp index 9a48cc76..043c927f 100644 --- a/test/test_string_stream_u16.cpp +++ b/test/test_string_stream_u16.cpp @@ -286,6 +286,6 @@ namespace CHECK_EQUAL(String(STR("Hello")), istr); } - }; + } } diff --git a/test/test_string_stream_u32.cpp b/test/test_string_stream_u32.cpp index a2213e45..f630b6f6 100644 --- a/test/test_string_stream_u32.cpp +++ b/test/test_string_stream_u32.cpp @@ -286,6 +286,6 @@ namespace CHECK_EQUAL(String(STR("Hello")), istr); } - }; + } } diff --git a/test/test_string_stream_u8.cpp b/test/test_string_stream_u8.cpp index 10b08976..31b86275 100644 --- a/test/test_string_stream_u8.cpp +++ b/test/test_string_stream_u8.cpp @@ -289,7 +289,7 @@ namespace CHECK_EQUAL(String(STR("Hello")), istr); } - }; + } } #endif diff --git a/test/test_string_stream_wchar_t.cpp b/test/test_string_stream_wchar_t.cpp index f594a39a..9f2dae9d 100644 --- a/test/test_string_stream_wchar_t.cpp +++ b/test/test_string_stream_wchar_t.cpp @@ -287,6 +287,6 @@ namespace CHECK_EQUAL(String(STR("Hello")), istr); } - }; + } } diff --git a/test/test_string_u16.cpp b/test/test_string_u16.cpp index a569d269..5cf79d06 100644 --- a/test/test_string_u16.cpp +++ b/test/test_string_u16.cpp @@ -5540,5 +5540,5 @@ namespace #endif CHECK_EQUAL(text.max_size(), text.size()); } - }; + } } diff --git a/test/test_string_u16_external_buffer.cpp b/test/test_string_u16_external_buffer.cpp index 41e60750..b22f43dd 100644 --- a/test/test_string_u16_external_buffer.cpp +++ b/test/test_string_u16_external_buffer.cpp @@ -5868,5 +5868,5 @@ namespace #endif CHECK_EQUAL(text.max_size(), text.size()); } - }; + } } diff --git a/test/test_string_u32.cpp b/test/test_string_u32.cpp index 5201371e..d7913b75 100644 --- a/test/test_string_u32.cpp +++ b/test/test_string_u32.cpp @@ -5540,5 +5540,5 @@ namespace #endif CHECK_EQUAL(text.max_size(), text.size()); } - }; + } } diff --git a/test/test_string_u32_external_buffer.cpp b/test/test_string_u32_external_buffer.cpp index f02a460d..c0b8150b 100644 --- a/test/test_string_u32_external_buffer.cpp +++ b/test/test_string_u32_external_buffer.cpp @@ -5868,5 +5868,5 @@ namespace #endif CHECK_EQUAL(text.max_size(), text.size()); } - }; + } } diff --git a/test/test_string_u8.cpp b/test/test_string_u8.cpp index 65eeb767..98d68d01 100644 --- a/test/test_string_u8.cpp +++ b/test/test_string_u8.cpp @@ -5485,6 +5485,6 @@ namespace #endif CHECK_EQUAL(text.max_size(), text.size()); } - }; + } } #endif \ No newline at end of file diff --git a/test/test_string_u8_external_buffer.cpp b/test/test_string_u8_external_buffer.cpp index 6f4befa5..e161bc13 100644 --- a/test/test_string_u8_external_buffer.cpp +++ b/test/test_string_u8_external_buffer.cpp @@ -5787,7 +5787,7 @@ namespace #endif CHECK_EQUAL(text.max_size(), text.size()); } - }; + } } #endif \ No newline at end of file diff --git a/test/test_string_utilities.cpp b/test/test_string_utilities.cpp index 0bd4fb13..0f450da3 100644 --- a/test/test_string_utilities.cpp +++ b/test/test_string_utilities.cpp @@ -1863,5 +1863,5 @@ namespace CHECK_TRUE(result.truncated); CHECK_FALSE(result.terminated); } - }; + } } diff --git a/test/test_string_utilities_std.cpp b/test/test_string_utilities_std.cpp index bdc3fe72..ea8ad202 100644 --- a/test/test_string_utilities_std.cpp +++ b/test/test_string_utilities_std.cpp @@ -1614,7 +1614,7 @@ namespace CHECK(text == expected); } - }; + } } #endif diff --git a/test/test_string_utilities_std_u16.cpp b/test/test_string_utilities_std_u16.cpp index 20da6ee4..1487947f 100644 --- a/test/test_string_utilities_std_u16.cpp +++ b/test/test_string_utilities_std_u16.cpp @@ -1589,7 +1589,7 @@ namespace CHECK(textview.end() == itr); } - }; + } } #endif diff --git a/test/test_string_utilities_std_u32.cpp b/test/test_string_utilities_std_u32.cpp index fe0e68fa..5688cbcf 100644 --- a/test/test_string_utilities_std_u32.cpp +++ b/test/test_string_utilities_std_u32.cpp @@ -1587,7 +1587,7 @@ namespace CHECK(textview.end() == itr); } - }; + } } #endif diff --git a/test/test_string_utilities_std_u8.cpp b/test/test_string_utilities_std_u8.cpp index 7d762dba..87e2a60f 100644 --- a/test/test_string_utilities_std_u8.cpp +++ b/test/test_string_utilities_std_u8.cpp @@ -1589,7 +1589,7 @@ namespace CHECK(textview.end() == itr); } - }; + } } #endif diff --git a/test/test_string_utilities_std_wchar_t.cpp b/test/test_string_utilities_std_wchar_t.cpp index 994a35a7..fcd16321 100644 --- a/test/test_string_utilities_std_wchar_t.cpp +++ b/test/test_string_utilities_std_wchar_t.cpp @@ -1587,7 +1587,7 @@ namespace CHECK(textview.end() == itr); } - }; + } } #endif diff --git a/test/test_string_utilities_u16.cpp b/test/test_string_utilities_u16.cpp index 55674381..12417262 100644 --- a/test/test_string_utilities_u16.cpp +++ b/test/test_string_utilities_u16.cpp @@ -1632,5 +1632,5 @@ namespace CHECK(textview.end() == itr); } - }; + } } diff --git a/test/test_string_utilities_u32.cpp b/test/test_string_utilities_u32.cpp index 98280105..275267b7 100644 --- a/test/test_string_utilities_u32.cpp +++ b/test/test_string_utilities_u32.cpp @@ -1632,5 +1632,5 @@ namespace CHECK(textview.end() == itr); } - }; + } } diff --git a/test/test_string_utilities_u8.cpp b/test/test_string_utilities_u8.cpp index c5f0da76..9ae4d453 100644 --- a/test/test_string_utilities_u8.cpp +++ b/test/test_string_utilities_u8.cpp @@ -1635,7 +1635,7 @@ namespace CHECK(textview.end() == itr); } - }; + } } #endif diff --git a/test/test_string_utilities_wchar_t.cpp b/test/test_string_utilities_wchar_t.cpp index 8752a9fb..7666e54d 100644 --- a/test/test_string_utilities_wchar_t.cpp +++ b/test/test_string_utilities_wchar_t.cpp @@ -1632,5 +1632,5 @@ namespace CHECK(textview.end() == itr); } - }; + } } diff --git a/test/test_string_view.cpp b/test/test_string_view.cpp index 598f6332..a65b938b 100644 --- a/test/test_string_view.cpp +++ b/test/test_string_view.cpp @@ -1155,5 +1155,5 @@ namespace CHECK_TRUE(u32view == u32sstream_view); } #endif - }; + } } diff --git a/test/test_string_wchar_t.cpp b/test/test_string_wchar_t.cpp index 4ac88729..7e8b576e 100644 --- a/test/test_string_wchar_t.cpp +++ b/test/test_string_wchar_t.cpp @@ -5559,5 +5559,5 @@ namespace CHECK(text1 == sstream_view); } #endif - }; + } } diff --git a/test/test_string_wchar_t_external_buffer.cpp b/test/test_string_wchar_t_external_buffer.cpp index 6b1b5e08..7bc6ca8a 100644 --- a/test/test_string_wchar_t_external_buffer.cpp +++ b/test/test_string_wchar_t_external_buffer.cpp @@ -5890,5 +5890,5 @@ namespace CHECK(text1 == sstream_view); } #endif - }; + } } diff --git a/test/test_task_scheduler.cpp b/test/test_task_scheduler.cpp index 5d33f669..67c72ded 100644 --- a/test/test_task_scheduler.cpp +++ b/test/test_task_scheduler.cpp @@ -287,5 +287,5 @@ namespace CHECK(expected == common.workList); CHECK(common.watchdog_called); } - }; + } } diff --git a/test/test_threshold.cpp b/test/test_threshold.cpp index 47768028..b467d54f 100644 --- a/test/test_threshold.cpp +++ b/test/test_threshold.cpp @@ -133,5 +133,5 @@ namespace bool isEqual = std::equal(output2.begin(), output2.end(), result2b.begin(), Compare()); CHECK(isEqual); } - }; + } } diff --git a/test/test_to_string.cpp b/test/test_to_string.cpp index dfb2ea44..43888a67 100644 --- a/test/test_to_string.cpp +++ b/test/test_to_string.cpp @@ -662,6 +662,6 @@ namespace CHECK_EQUAL(etl::string<20>(STR("-124.0000")).c_str(), result_i.c_str()); CHECK_EQUAL(result_d.c_str(), result_i.c_str()); } - }; + } } diff --git a/test/test_to_u16string.cpp b/test/test_to_u16string.cpp index 5d964070..19d54efb 100644 --- a/test/test_to_u16string.cpp +++ b/test/test_to_u16string.cpp @@ -565,6 +565,6 @@ namespace CHECK(etl::u16string<20>(STR("-124.0000")) == result_i); CHECK(result_d == result_i); } - }; + } } diff --git a/test/test_to_u32string.cpp b/test/test_to_u32string.cpp index a5a75c82..27021f8a 100644 --- a/test/test_to_u32string.cpp +++ b/test/test_to_u32string.cpp @@ -570,6 +570,6 @@ namespace CHECK(etl::u32string<20>(STR("-124.0000")) == result_i); CHECK(result_d == result_i); } - }; + } } diff --git a/test/test_to_u8string.cpp b/test/test_to_u8string.cpp index c7bf6f80..d4376c36 100644 --- a/test/test_to_u8string.cpp +++ b/test/test_to_u8string.cpp @@ -567,7 +567,7 @@ namespace CHECK(etl::u8string<20>(STR("-124.0000")) == result_i); CHECK(result_d == result_i); } - }; + } } #endif diff --git a/test/test_to_wstring.cpp b/test/test_to_wstring.cpp index ca97b3b4..b785fec2 100644 --- a/test/test_to_wstring.cpp +++ b/test/test_to_wstring.cpp @@ -632,6 +632,6 @@ namespace CHECK(etl::wstring<20>(STR("-124.0000")) == result_i); CHECK(result_d == result_i); } - }; + } } diff --git a/test/test_type_def.cpp b/test/test_type_def.cpp index facb2ed8..fc984f7a 100644 --- a/test/test_type_def.cpp +++ b/test/test_type_def.cpp @@ -336,5 +336,5 @@ namespace CHECK_EQUAL(-3, value_minus.get()); } #endif - }; + } } diff --git a/test/test_type_list.cpp b/test/test_type_list.cpp index df37af51..cd53981c 100644 --- a/test/test_type_list.cpp +++ b/test/test_type_list.cpp @@ -261,6 +261,6 @@ namespace //CHECK_FALSE((etl::type_lists_are_convertible_v)); #endif } - }; + } #endif } diff --git a/test/test_type_lookup.cpp b/test/test_type_lookup.cpp index 68a6d7d3..01575cca 100644 --- a/test/test_type_lookup.cpp +++ b/test/test_type_lookup.cpp @@ -425,7 +425,7 @@ namespace CHECK((etl::is_same>::value)); } #endif - }; + } } #include "etl/private/diagnostic_pop.h" diff --git a/test/test_type_select.cpp b/test/test_type_select.cpp index 4cad3dff..1fe370ef 100644 --- a/test/test_type_select.cpp +++ b/test/test_type_select.cpp @@ -182,5 +182,5 @@ namespace CHECK(!(etl::is_same, typename Types16::select_t<15>>::value)); } #endif - }; + } } diff --git a/test/test_type_traits.cpp b/test/test_type_traits.cpp index 76d8b8cc..3083343b 100644 --- a/test/test_type_traits.cpp +++ b/test/test_type_traits.cpp @@ -70,7 +70,7 @@ namespace struct ToAny { ToAny() = default; - template ToAny(T){}; + template ToAny(T){} template operator T() { return T(); } }; @@ -976,693 +976,693 @@ namespace CHECK((etl::is_same::const_pointer>::value)); CHECK((etl::is_same::const_pointer_const>::value)); } - }; - //************************************************************************* - TEST(test_conditional_integral_constant) - { - int v1 = etl::conditional_integral_constant::value; - int v2 = etl::conditional_integral_constant::value; - - CHECK_EQUAL(1, v1); - CHECK_EQUAL(2, v2); - } - - //************************************************************************* - TEST(test_size_of) - { -#if ETL_USING_CPP17 - CHECK_EQUAL(1, etl::size_of_v); - CHECK_EQUAL(1, etl::size_of_v); - CHECK_EQUAL(2, etl::size_of_v); - CHECK_EQUAL(4, etl::size_of_v); - CHECK_EQUAL(20, etl::size_of_v); -#else - CHECK_EQUAL(1, etl::size_of::value); - CHECK_EQUAL(1, etl::size_of::value); - CHECK_EQUAL(2, etl::size_of::value); - CHECK_EQUAL(4, etl::size_of::value); - CHECK_EQUAL(20, etl::size_of::value); -#endif - } - - //************************************************************************* - TEST(test_is_convertible) - { -#if ETL_USING_CPP17 - CHECK((etl::is_convertible_v)); - CHECK((etl::is_convertible_v)); - CHECK((etl::is_convertible_v)); - CHECK((etl::is_convertible_v)); - CHECK((etl::is_convertible_v)); - CHECK((etl::is_convertible_v)); - CHECK((etl::is_convertible_v)); - CHECK(!(etl::is_convertible_v)); - CHECK(!(etl::is_convertible_v)); - CHECK(!(etl::is_convertible_v)); - CHECK(!(etl::is_convertible_v)); -#else - CHECK((etl::is_convertible::value)); - CHECK((etl::is_convertible::value)); - CHECK((etl::is_convertible::value)); - CHECK((etl::is_convertible::value)); - CHECK((etl::is_convertible::value)); - CHECK((etl::is_convertible::value)); - CHECK((etl::is_convertible::value)); - CHECK(!(etl::is_convertible::value)); - CHECK(!(etl::is_convertible::value)); - CHECK(!(etl::is_convertible::value)); - CHECK(!(etl::is_convertible::value)); -#endif - } - - //************************************************************************* - TEST(test_add_lvalue_reference) - { -#if ETL_USING_CPP17 - CHECK(!std::is_lvalue_reference_v::type>); - CHECK(std::is_lvalue_reference_v::type>); - CHECK(std::is_lvalue_reference_v::type>); - CHECK(std::is_lvalue_reference_v::type>); - CHECK(std::is_lvalue_reference_v::type>); -#else -#endif - } - - //************************************************************************* - TEST(test_add_rvalue_reference) - { -#if ETL_USING_CPP17 - CHECK(!std::is_rvalue_reference_v::type>); - CHECK(std::is_rvalue_reference_v::type>); - CHECK(std::is_rvalue_reference_v::type>); - CHECK(!std::is_rvalue_reference_v::type>); - CHECK(std::is_rvalue_reference_v::type>); -#else -#endif - } - - //************************************************************************* - TEST(test_is_lvalue_reference) - { -#if ETL_USING_CPP17 - CHECK_EQUAL(std::is_lvalue_reference_v, etl::is_lvalue_reference_v); - CHECK_EQUAL(std::is_lvalue_reference_v, etl::is_lvalue_reference_v); - CHECK_EQUAL(std::is_lvalue_reference_v, etl::is_lvalue_reference_v); - CHECK_EQUAL(std::is_lvalue_reference_v, etl::is_lvalue_reference_v); - CHECK_EQUAL(std::is_lvalue_reference_v, etl::is_lvalue_reference_v); -#else -#endif - } - - //************************************************************************* - TEST(test_is_rvalue_reference) - { -#if ETL_USING_CPP17 - CHECK_EQUAL(std::is_rvalue_reference_v, etl::is_rvalue_reference_v); - CHECK_EQUAL(std::is_rvalue_reference_v, etl::is_rvalue_reference_v); - CHECK_EQUAL(std::is_rvalue_reference_v, etl::is_rvalue_reference_v); - CHECK_EQUAL(std::is_rvalue_reference_v, etl::is_rvalue_reference_v); - CHECK_EQUAL(std::is_rvalue_reference_v, etl::is_rvalue_reference_v); -#else - CHECK_EQUAL(std::is_rvalue_reference::value, etl::is_rvalue_reference::value); - CHECK_EQUAL(std::is_rvalue_reference::value, etl::is_rvalue_reference::value); - CHECK_EQUAL(std::is_rvalue_reference::value, etl::is_rvalue_reference::value); - CHECK_EQUAL(std::is_rvalue_reference::value, etl::is_rvalue_reference::value); - CHECK_EQUAL(std::is_rvalue_reference::value, etl::is_rvalue_reference::value); -#endif - } - - //************************************************************************* -#if ETL_USING_CPP17 - #define CHECK_EQUAL_FOR_TYPE(type) CHECK_EQUAL(std::is_enum_v, etl::is_enum_v) -#else - #define CHECK_EQUAL_FOR_TYPE(type) CHECK_EQUAL(std::is_enum::value, etl::is_enum::value) -#endif - - TEST(test_is_enum) - { - CHECK_EQUAL_FOR_TYPE(void); - CHECK_EQUAL_FOR_TYPE(void*); - CHECK_EQUAL_FOR_TYPE(int); - CHECK_EQUAL_FOR_TYPE(int*); - CHECK_EQUAL_FOR_TYPE(ToAny); - CHECK_EQUAL_FOR_TYPE(NotDefaultConstructable); - CHECK_EQUAL_FOR_TYPE(Enum); - CHECK_EQUAL_FOR_TYPE(Enum&); - CHECK_EQUAL_FOR_TYPE(Enum&&); - CHECK_EQUAL_FOR_TYPE(Enum*); - CHECK_EQUAL_FOR_TYPE(const Enum); - CHECK_EQUAL_FOR_TYPE(volatile Enum); - CHECK_EQUAL_FOR_TYPE(const volatile Enum); - CHECK_EQUAL_FOR_TYPE(EnumClass); - CHECK_EQUAL_FOR_TYPE(EnumClass&); - CHECK_EQUAL_FOR_TYPE(EnumClass&&); - CHECK_EQUAL_FOR_TYPE(EnumClass*); - CHECK_EQUAL_FOR_TYPE(const EnumClass); - CHECK_EQUAL_FOR_TYPE(volatile EnumClass); - CHECK_EQUAL_FOR_TYPE(const volatile EnumClass); - - } - #undef CHECK_EQUAL_FOR_TYPE - - //************************************************************************* - TEST(test_integral_constants) - { -#if ETL_USING_CPP17 - CHECK_EQUAL(1, (etl::integral_constant_v)); - CHECK((std::is_same_v::value_type>)); - - CHECK_EQUAL(false, etl::bool_constant_v); - CHECK_EQUAL(true, etl::bool_constant_v); - CHECK((std::is_same_v::value_type>)); - - CHECK_EQUAL(true, etl::negation_v>); - CHECK_EQUAL(false, etl::negation_v>); - CHECK((std::is_same_v::value_type>)); -#else - CHECK_EQUAL(1, (etl::integral_constant::value)); - CHECK((std::is_same::value_type>::value)); - - CHECK_EQUAL(false, (etl::bool_constant::value)); - CHECK_EQUAL(true, (etl::bool_constant::value)); - CHECK((std::is_same::value_type>::value)); - - CHECK_EQUAL(true, etl::negation>::value); - CHECK_EQUAL(false, etl::negation>::value); - CHECK((std::is_same::value_type>::value)); -#endif - } - - //************************************************************************* - TEST(test_are_all_same) - { -#if ETL_USING_CPP17 - CHECK((etl::are_all_same_v == true)); - CHECK((etl::are_all_same_v == false)); -#else - CHECK((etl::are_all_same::value == true)); - CHECK((etl::are_all_same::value == false)); -#endif - } - - //************************************************************************* - TEST(test_conjunction) - { -#if ETL_USING_CPP17 - CHECK_TRUE((etl::conjunction_v)); - CHECK_FALSE((etl::conjunction_v)); -#else - CHECK_TRUE((etl::conjunction::value)); - CHECK_FALSE((etl::conjunction::value)); -#endif - } - - //************************************************************************* - TEST(test_disjunction) - { -#if ETL_USING_CPP17 - CHECK_TRUE((etl::disjunction_v)); - CHECK_FALSE((etl::disjunction_v)); -#else - CHECK_TRUE((etl::disjunction::value)); - CHECK_FALSE((etl::disjunction::value)); -#endif - } - - //************************************************************************* - TEST(test_exclusive_disjunction) - { -#if ETL_USING_CPP17 - CHECK_TRUE((etl::exclusive_disjunction_v)); - CHECK_FALSE((etl::exclusive_disjunction_v)); - CHECK_FALSE((etl::exclusive_disjunction_v)); -#else - CHECK_TRUE((etl::exclusive_disjunction::value)); - CHECK_FALSE((etl::exclusive_disjunction::value)); - CHECK_FALSE((etl::exclusive_disjunction::value)); -#endif - } - - //************************************************************************* - TEST(test_is_assignable) - { -#if ETL_USING_CPP17 - CHECK((etl::is_assignable_v) == (std::is_assignable_v)); - CHECK((etl::is_assignable_v) == (std::is_assignable_v)); - CHECK((etl::is_assignable_v) == (std::is_assignable_v)); -#else - CHECK((etl::is_assignable::value) == (std::is_assignable::value)); - CHECK((etl::is_assignable::value) == (std::is_assignable::value)); - CHECK((etl::is_assignable::value) == (std::is_assignable::value)); -#endif - } - - //************************************************************************* - TEST(test_is_lvalue_assignable) - { -#if ETL_USING_STL || defined(ETL_USE_TYPE_TRAITS_BUILTINS) || defined(ETL_USER_DEFINED_TYPE_TRAITS) -#if ETL_USING_CPP17 - CHECK((etl::is_lvalue_assignable_v)); - CHECK(!(etl::is_lvalue_assignable_v)); - CHECK((etl::is_lvalue_assignable_v)); -#else - CHECK((etl::is_lvalue_assignable::value)); - CHECK(!(etl::is_lvalue_assignable::value)); - CHECK((etl::is_lvalue_assignable::value)); -#endif -#endif - } - - //************************************************************************* - TEST(test_is_constructible) - { -#if ETL_USING_CPP17 - CHECK((etl::is_constructible_v) == (std::is_constructible_v)); - CHECK((etl::is_constructible_v) == (std::is_constructible_v)); - CHECK((etl::is_constructible_v) == (std::is_constructible_v)); - CHECK((etl::is_constructible_v) == (std::is_constructible_v)); -#else - CHECK((etl::is_constructible::value) == (std::is_constructible::value)); - CHECK((etl::is_constructible::value) == (std::is_constructible::value)); - CHECK((etl::is_constructible::value) == (std::is_constructible::value)); - CHECK((etl::is_constructible::value) == (std::is_constructible::value)); -#endif - } - - //************************************************************************* - TEST(test_is_default_constructible) - { -#if ETL_USING_CPP17 - CHECK((etl::is_default_constructible_v) == (std::is_default_constructible_v)); - CHECK((etl::is_default_constructible_v) == (std::is_default_constructible_v)); - CHECK((etl::is_default_constructible_v) == (std::is_default_constructible_v)); - CHECK((etl::is_default_constructible_v) == (std::is_default_constructible_v)); -#else - CHECK((etl::is_default_constructible::value) == (std::is_default_constructible::value)); - CHECK((etl::is_default_constructible::value) == (std::is_default_constructible::value)); - CHECK((etl::is_default_constructible::value) == (std::is_default_constructible::value)); - CHECK((etl::is_default_constructible::value) == (std::is_default_constructible::value)); -#endif - } - - //************************************************************************* - TEST(test_is_copy_constructible) - { -#if ETL_USING_CPP17 - CHECK((etl::is_copy_constructible_v) == (std::is_copy_constructible_v)); - CHECK((etl::is_copy_constructible_v) == (std::is_copy_constructible_v)); - CHECK((etl::is_copy_constructible_v) == (std::is_copy_constructible_v)); -#else - CHECK((etl::is_copy_constructible::value) == (std::is_copy_constructible::value)); - CHECK((etl::is_copy_constructible::value) == (std::is_copy_constructible::value)); - CHECK((etl::is_copy_constructible::value) == (std::is_copy_constructible::value)); -#endif - } - - //************************************************************************* - TEST(test_is_move_constructible) - { -#if ETL_USING_CPP17 - CHECK((etl::is_move_constructible_v) == (std::is_move_constructible_v)); - CHECK((etl::is_move_constructible_v) == (std::is_move_constructible_v)); - CHECK((etl::is_move_constructible_v) == (std::is_move_constructible_v)); -#else - CHECK((etl::is_move_constructible::value) == (std::is_move_constructible::value)); - CHECK((etl::is_move_constructible::value) == (std::is_move_constructible::value)); - CHECK((etl::is_move_constructible::value) == (std::is_move_constructible::value)); -#endif - } - - //************************************************************************* - TEST(test_is_trivially_constructible) - { -#if ETL_USING_STL || defined(ETL_USE_TYPE_TRAITS_BUILTINS) || defined(ETL_USER_DEFINED_TYPE_TRAITS) -#if ETL_USING_CPP17 - CHECK((etl::is_trivially_constructible_v) == (std::is_trivially_constructible_v)); - CHECK((etl::is_trivially_constructible_v) == (std::is_trivially_constructible_v)); - CHECK((etl::is_trivially_constructible_v) == (std::is_trivially_constructible_v)); -#else - CHECK((etl::is_trivially_constructible::value) == (std::is_trivially_constructible::value)); - CHECK((etl::is_trivially_constructible::value) == (std::is_trivially_constructible::value)); - CHECK((etl::is_trivially_constructible::value) == (std::is_trivially_constructible::value)); -#endif -#endif - } - - //************************************************************************* - TEST(test_is_trivially_copy_constructible) - { -#if ETL_USING_STL || defined(ETL_USE_TYPE_TRAITS_BUILTINS) || defined(ETL_USER_DEFINED_TYPE_TRAITS) -#if ETL_USING_CPP17 - CHECK((etl::is_trivially_copy_constructible_v) == (std::is_trivially_copy_constructible_v)); - CHECK((etl::is_trivially_copy_constructible_v) == (std::is_trivially_copy_constructible_v)); - CHECK((etl::is_trivially_copy_constructible_v) == (std::is_trivially_copy_constructible_v)); -#else - CHECK((etl::is_trivially_copy_constructible::value) == (std::is_trivially_copy_constructible::value)); - CHECK((etl::is_trivially_copy_constructible::value) == (std::is_trivially_copy_constructible::value)); - CHECK((etl::is_trivially_copy_constructible::value) == (std::is_trivially_copy_constructible::value)); -#endif -#endif - } - - //************************************************************************* - TEST(test_is_trivially_destructible) - { -#if ETL_USING_STL || defined(ETL_USE_TYPE_TRAITS_BUILTINS) || defined(ETL_USER_DEFINED_TYPE_TRAITS) -#if ETL_USING_CPP17 - CHECK((etl::is_trivially_destructible_v) == (std::is_trivially_destructible_v)); - CHECK((etl::is_trivially_destructible_v) == (std::is_trivially_destructible_v)); - CHECK((etl::is_trivially_destructible_v) == (std::is_trivially_destructible_v)); -#else - CHECK((etl::is_trivially_destructible::value) == (std::is_trivially_destructible::value)); - CHECK((etl::is_trivially_destructible::value) == (std::is_trivially_destructible::value)); - CHECK((etl::is_trivially_destructible::value) == (std::is_trivially_destructible::value)); -#endif -#endif - } - - //************************************************************************* - TEST(test_is_trivially_copy_assignable) - { -#if (!(defined(ETL_COMPILER_GCC) && defined(ETL_USE_TYPE_TRAITS_BUILTINS))) -#if ETL_USING_STL || defined(ETL_USE_TYPE_TRAITS_BUILTINS) || defined(ETL_USER_DEFINED_TYPE_TRAITS) -#if ETL_USING_CPP17 - CHECK((etl::is_trivially_copy_assignable_v) == (std::is_trivially_copy_assignable_v)); - CHECK((etl::is_trivially_copy_assignable_v) == (std::is_trivially_copy_assignable_v)); - CHECK((etl::is_trivially_copy_assignable_v) == (std::is_trivially_copy_assignable_v)); -#else - CHECK((etl::is_trivially_copy_assignable::value) == (std::is_trivially_copy_assignable::value)); - CHECK((etl::is_trivially_copy_assignable::value) == (std::is_trivially_copy_assignable::value)); - CHECK((etl::is_trivially_copy_assignable::value) == (std::is_trivially_copy_assignable::value)); -#endif -#endif -#endif - } - - //************************************************************************* - TEST(test_is_trivially_copyable) - { -#if (!(defined(ETL_COMPILER_GCC) && defined(ETL_USE_TYPE_TRAITS_BUILTINS))) -#if ETL_USING_STL || defined(ETL_USE_TYPE_TRAITS_BUILTINS) || defined(ETL_USER_DEFINED_TYPE_TRAITS) -#if ETL_USING_CPP17 - CHECK((etl::is_trivially_copyable_v) == (std::is_trivially_copyable_v)); - CHECK((etl::is_trivially_copyable_v) == (std::is_trivially_copyable_v)); - CHECK((etl::is_trivially_copyable_v) == (std::is_trivially_copyable_v)); -#else - CHECK((etl::is_trivially_copyable::value) == (std::is_trivially_copyable::value)); - CHECK((etl::is_trivially_copyable::value) == (std::is_trivially_copyable::value)); - CHECK((etl::is_trivially_copyable::value) == (std::is_trivially_copyable::value)); -#endif -#endif -#endif - } - - //************************************************************************* - TEST(test_is_base_of_any) - { - struct Base {}; - struct D1 : Base {}; - struct D2 : Base {}; - struct D3 : Base {}; - struct D4 {}; - -#if ETL_USING_CPP17 - CHECK_TRUE(bool(etl::is_base_of_any_v)); - CHECK_FALSE(bool(etl::is_base_of_any_v)); -#else - CHECK_TRUE(bool(etl::is_base_of_any::value)); - CHECK_FALSE(bool(etl::is_base_of_any::value)); -#endif - } - - //************************************************************************* - TEST(test_is_base_of_all) - { - struct Base {}; - struct D1 : Base {}; - struct D2 : Base {}; - struct D3 : Base {}; - struct D4 {}; - -#if ETL_USING_CPP17 - CHECK_TRUE(bool(etl::is_base_of_all_v)); - CHECK_FALSE(bool(etl::is_base_of_all_v)); -#else - CHECK_TRUE(bool(etl::is_base_of_all::value)); - CHECK_FALSE(bool(etl::is_base_of_all::value)); -#endif - } - - //************************************************************************* - TEST(test_nth_base) - { - struct D0 { }; - struct D1 : D0 { using base_type = D0; }; - struct D2 : D1 { using base_type = D1; }; - struct D3 : D2 { using base_type = D2; }; - struct D4 : D3 { using base_type = D3; }; - - CHECK_TRUE((std::is_same>::value)); - CHECK_TRUE((std::is_same>::value)); - CHECK_TRUE((std::is_same>::value)); - CHECK_TRUE((std::is_same>::value)); - CHECK_TRUE((std::is_same>::value)); - } - - //************************************************************************* - TEST(test_type_identity) - { - CHECK_CLOSE(type_identity_test_add(1.5f, 2), 3.5f, 0.01f); - } - - //************************************************************************* -#if ETL_USING_BUILTIN_UNDERLYING_TYPE - TEST(test_underlying_type) - { - enum enum0_t : char + //************************************************************************* + TEST(test_conditional_integral_constant) { - }; + int v1 = etl::conditional_integral_constant::value; + int v2 = etl::conditional_integral_constant::value; - enum enum1_t : uint32_t + CHECK_EQUAL(1, v1); + CHECK_EQUAL(2, v2); + } + + //************************************************************************* + TEST(test_size_of) { - }; + #if ETL_USING_CPP17 + CHECK_EQUAL(1, etl::size_of_v); + CHECK_EQUAL(1, etl::size_of_v); + CHECK_EQUAL(2, etl::size_of_v); + CHECK_EQUAL(4, etl::size_of_v); + CHECK_EQUAL(20, etl::size_of_v); + #else + CHECK_EQUAL(1, etl::size_of::value); + CHECK_EQUAL(1, etl::size_of::value); + CHECK_EQUAL(2, etl::size_of::value); + CHECK_EQUAL(4, etl::size_of::value); + CHECK_EQUAL(20, etl::size_of::value); + #endif + } - enum class enum2_t : short + //************************************************************************* + TEST(test_is_convertible) { - }; + #if ETL_USING_CPP17 + CHECK((etl::is_convertible_v)); + CHECK((etl::is_convertible_v)); + CHECK((etl::is_convertible_v)); + CHECK((etl::is_convertible_v)); + CHECK((etl::is_convertible_v)); + CHECK((etl::is_convertible_v)); + CHECK((etl::is_convertible_v)); + CHECK(!(etl::is_convertible_v)); + CHECK(!(etl::is_convertible_v)); + CHECK(!(etl::is_convertible_v)); + CHECK(!(etl::is_convertible_v)); + #else + CHECK((etl::is_convertible::value)); + CHECK((etl::is_convertible::value)); + CHECK((etl::is_convertible::value)); + CHECK((etl::is_convertible::value)); + CHECK((etl::is_convertible::value)); + CHECK((etl::is_convertible::value)); + CHECK((etl::is_convertible::value)); + CHECK(!(etl::is_convertible::value)); + CHECK(!(etl::is_convertible::value)); + CHECK(!(etl::is_convertible::value)); + CHECK(!(etl::is_convertible::value)); + #endif + } - enum class enum3_t : size_t + //************************************************************************* + TEST(test_add_lvalue_reference) { - }; + #if ETL_USING_CPP17 + CHECK(!std::is_lvalue_reference_v::type>); + CHECK(std::is_lvalue_reference_v::type>); + CHECK(std::is_lvalue_reference_v::type>); + CHECK(std::is_lvalue_reference_v::type>); + CHECK(std::is_lvalue_reference_v::type>); + #else + #endif + } - using enum4_t = enum1_t; - using enum5_t = std::add_const::type; + //************************************************************************* + TEST(test_add_rvalue_reference) + { + #if ETL_USING_CPP17 + CHECK(!std::is_rvalue_reference_v::type>); + CHECK(std::is_rvalue_reference_v::type>); + CHECK(std::is_rvalue_reference_v::type>); + CHECK(!std::is_rvalue_reference_v::type>); + CHECK(std::is_rvalue_reference_v::type>); + #else + #endif + } - CHECK_TRUE((std::is_same::type, char>::value)); - CHECK_TRUE((std::is_same::type, uint32_t>::value)); - CHECK_TRUE((std::is_same::type, short>::value)); - CHECK_TRUE((std::is_same::type, size_t>::value)); - CHECK_TRUE((std::is_same::type, uint32_t>::value)); - CHECK_TRUE((std::is_same::type, short>::value)); -#if ETL_USING_CPP11 - CHECK_TRUE((std::is_same, char>::value)); - CHECK_TRUE((std::is_same, uint32_t>::value)); - CHECK_TRUE((std::is_same, short>::value)); - CHECK_TRUE((std::is_same, size_t>::value)); - CHECK_TRUE((std::is_same, uint32_t>::value)); - CHECK_TRUE((std::is_same, short>::value)); -#endif - } -#endif + //************************************************************************* + TEST(test_is_lvalue_reference) + { + #if ETL_USING_CPP17 + CHECK_EQUAL(std::is_lvalue_reference_v, etl::is_lvalue_reference_v); + CHECK_EQUAL(std::is_lvalue_reference_v, etl::is_lvalue_reference_v); + CHECK_EQUAL(std::is_lvalue_reference_v, etl::is_lvalue_reference_v); + CHECK_EQUAL(std::is_lvalue_reference_v, etl::is_lvalue_reference_v); + CHECK_EQUAL(std::is_lvalue_reference_v, etl::is_lvalue_reference_v); + #else + #endif + } - //************************************************************************* - TEST(test_has_duplicates) - { -#if ETL_USING_CPP17 - CHECK_FALSE((etl::has_duplicates_v)); - CHECK_FALSE((etl::has_duplicates_v)); - CHECK_TRUE((etl::has_duplicates_v)); -#else - CHECK_FALSE((etl::has_duplicates::value)); - CHECK_FALSE((etl::has_duplicates::value)); - CHECK_TRUE((etl::has_duplicates::value)); -#endif - } + //************************************************************************* + TEST(test_is_rvalue_reference) + { + #if ETL_USING_CPP17 + CHECK_EQUAL(std::is_rvalue_reference_v, etl::is_rvalue_reference_v); + CHECK_EQUAL(std::is_rvalue_reference_v, etl::is_rvalue_reference_v); + CHECK_EQUAL(std::is_rvalue_reference_v, etl::is_rvalue_reference_v); + CHECK_EQUAL(std::is_rvalue_reference_v, etl::is_rvalue_reference_v); + CHECK_EQUAL(std::is_rvalue_reference_v, etl::is_rvalue_reference_v); + #else + CHECK_EQUAL(std::is_rvalue_reference::value, etl::is_rvalue_reference::value); + CHECK_EQUAL(std::is_rvalue_reference::value, etl::is_rvalue_reference::value); + CHECK_EQUAL(std::is_rvalue_reference::value, etl::is_rvalue_reference::value); + CHECK_EQUAL(std::is_rvalue_reference::value, etl::is_rvalue_reference::value); + CHECK_EQUAL(std::is_rvalue_reference::value, etl::is_rvalue_reference::value); + #endif + } - //************************************************************************* - TEST(test_has_duplicates_of) - { -#if ETL_USING_CPP17 - CHECK_FALSE((etl::has_duplicates_of_v)); - CHECK_TRUE((etl::has_duplicates_of_v)); // char is duplicated. - CHECK_FALSE((etl::has_duplicates_of_v)); // int is not duplicated. -#else - CHECK_FALSE((etl::has_duplicates_of::value)); - CHECK_TRUE((etl::has_duplicates_of::value)); // char is duplicated. - CHECK_FALSE((etl::has_duplicates_of::value)); // int is not duplicated. -#endif - } + //************************************************************************* + #if ETL_USING_CPP17 + #define CHECK_EQUAL_FOR_TYPE(type) CHECK_EQUAL(std::is_enum_v, etl::is_enum_v) + #else + #define CHECK_EQUAL_FOR_TYPE(type) CHECK_EQUAL(std::is_enum::value, etl::is_enum::value) + #endif - //************************************************************************* - TEST(test_count_of) - { -#if ETL_USING_CPP17 - CHECK_EQUAL(0, (etl::count_of_v)); - CHECK_EQUAL(0, (etl::count_of_v)); - CHECK_EQUAL(1, (etl::count_of_v)); - CHECK_EQUAL(1, (etl::count_of_v)); - CHECK_EQUAL(2, (etl::count_of_v)); -#else - CHECK_EQUAL(0, (etl::count_of::value)); - CHECK_EQUAL(0, (etl::count_of::value)); - CHECK_EQUAL(1, (etl::count_of::value)); - CHECK_EQUAL(1, (etl::count_of::value)); - CHECK_EQUAL(2, (etl::count_of::value)); -#endif - } + TEST(test_is_enum) + { + CHECK_EQUAL_FOR_TYPE(void); + CHECK_EQUAL_FOR_TYPE(void*); + CHECK_EQUAL_FOR_TYPE(int); + CHECK_EQUAL_FOR_TYPE(int*); + CHECK_EQUAL_FOR_TYPE(ToAny); + CHECK_EQUAL_FOR_TYPE(NotDefaultConstructable); + CHECK_EQUAL_FOR_TYPE(Enum); + CHECK_EQUAL_FOR_TYPE(Enum&); + CHECK_EQUAL_FOR_TYPE(Enum&&); + CHECK_EQUAL_FOR_TYPE(Enum*); + CHECK_EQUAL_FOR_TYPE(const Enum); + CHECK_EQUAL_FOR_TYPE(volatile Enum); + CHECK_EQUAL_FOR_TYPE(const volatile Enum); + CHECK_EQUAL_FOR_TYPE(EnumClass); + CHECK_EQUAL_FOR_TYPE(EnumClass&); + CHECK_EQUAL_FOR_TYPE(EnumClass&&); + CHECK_EQUAL_FOR_TYPE(EnumClass*); + CHECK_EQUAL_FOR_TYPE(const EnumClass); + CHECK_EQUAL_FOR_TYPE(volatile EnumClass); + CHECK_EQUAL_FOR_TYPE(const volatile EnumClass); - //************************************************************************* - TEST(test_is_specialization) - { -#if ETL_USING_CPP17 - CHECK_TRUE((etl::is_specialization_v, specialized>)); - CHECK_FALSE((etl::is_specialization_v, specialized>)); -#else - CHECK_TRUE((etl::is_specialization, specialized>::value)); - CHECK_FALSE((etl::is_specialization, specialized>::value)); -#endif - } + } + #undef CHECK_EQUAL_FOR_TYPE -#if ETL_USING_CPP11 - //************************************************************************* - TEST(test_is_constant_evaluated) - { - constexpr bool c0 = etl::is_constant_evaluated(); -#if !ETL_USING_CPP23 && defined(ETL_COMPILER_MICROSOFT) - // Not supported on MSVC via __has_builtin, see determine_builtin_support.h - CHECK_FALSE(c0); -#else - CHECK_TRUE(c0); -#endif + //************************************************************************* + TEST(test_integral_constants) + { + #if ETL_USING_CPP17 + CHECK_EQUAL(1, (etl::integral_constant_v)); + CHECK((std::is_same_v::value_type>)); - volatile int i = 1; - const bool c1 = (((i == 1) && etl::is_constant_evaluated()) ? true : false); - CHECK_FALSE(c1); - } -#endif + CHECK_EQUAL(false, etl::bool_constant_v); + CHECK_EQUAL(true, etl::bool_constant_v); + CHECK((std::is_same_v::value_type>)); - //************************************************************************* - // Basic cv for member function pointers - TEST(test_is_member_function_pointer) - { - CHECK_TRUE((etl::is_member_function_pointer::value)); - CHECK_TRUE((etl::is_member_function_pointer::value)); - CHECK_TRUE((etl::is_member_function_pointer::value)); - CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_EQUAL(true, etl::negation_v>); + CHECK_EQUAL(false, etl::negation_v>); + CHECK((std::is_same_v::value_type>)); + #else + CHECK_EQUAL(1, (etl::integral_constant::value)); + CHECK((std::is_same::value_type>::value)); - CHECK_TRUE((etl::is_member_function_pointer::value)); - CHECK_TRUE((etl::is_member_function_pointer::value)); - CHECK_TRUE((etl::is_member_function_pointer::value)); - CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_EQUAL(false, (etl::bool_constant::value)); + CHECK_EQUAL(true, (etl::bool_constant::value)); + CHECK((std::is_same::value_type>::value)); - CHECK_TRUE((etl::is_member_function_pointer::value)); - CHECK_TRUE((etl::is_member_function_pointer::value)); - CHECK_TRUE((etl::is_member_function_pointer::value)); - CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_EQUAL(true, etl::negation>::value); + CHECK_EQUAL(false, etl::negation>::value); + CHECK((std::is_same::value_type>::value)); + #endif + } -#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE - CHECK_TRUE((etl::is_member_function_pointer::value)); - CHECK_TRUE((etl::is_member_function_pointer::value)); - CHECK_TRUE((etl::is_member_function_pointer::value)); - CHECK_TRUE((etl::is_member_function_pointer::value)); + //************************************************************************* + TEST(test_are_all_same) + { + #if ETL_USING_CPP17 + CHECK((etl::are_all_same_v == true)); + CHECK((etl::are_all_same_v == false)); + #else + CHECK((etl::are_all_same::value == true)); + CHECK((etl::are_all_same::value == false)); + #endif + } - CHECK_TRUE((etl::is_member_function_pointer::value)); - CHECK_TRUE((etl::is_member_function_pointer::value)); - CHECK_TRUE((etl::is_member_function_pointer::value)); - CHECK_TRUE((etl::is_member_function_pointer::value)); + //************************************************************************* + TEST(test_conjunction) + { + #if ETL_USING_CPP17 + CHECK_TRUE((etl::conjunction_v)); + CHECK_FALSE((etl::conjunction_v)); + #else + CHECK_TRUE((etl::conjunction::value)); + CHECK_FALSE((etl::conjunction::value)); + #endif + } - CHECK_TRUE((etl::is_member_function_pointer::value)); - CHECK_TRUE((etl::is_member_function_pointer::value)); - CHECK_TRUE((etl::is_member_function_pointer::value)); - CHECK_TRUE((etl::is_member_function_pointer::value)); -#endif + //************************************************************************* + TEST(test_disjunction) + { + #if ETL_USING_CPP17 + CHECK_TRUE((etl::disjunction_v)); + CHECK_FALSE((etl::disjunction_v)); + #else + CHECK_TRUE((etl::disjunction::value)); + CHECK_FALSE((etl::disjunction::value)); + #endif + } - CHECK_TRUE((etl::is_member_function_pointer::value)); - CHECK_TRUE((etl::is_member_function_pointer::value)); - } + //************************************************************************* + TEST(test_exclusive_disjunction) + { + #if ETL_USING_CPP17 + CHECK_TRUE((etl::exclusive_disjunction_v)); + CHECK_FALSE((etl::exclusive_disjunction_v)); + CHECK_FALSE((etl::exclusive_disjunction_v)); + #else + CHECK_TRUE((etl::exclusive_disjunction::value)); + CHECK_FALSE((etl::exclusive_disjunction::value)); + CHECK_FALSE((etl::exclusive_disjunction::value)); + #endif + } - //************************************************************************* - // Negative tests for member function pointer trait - TEST(test_is_member_function_pointer_negative) - { - (void)f(0); + //************************************************************************* + TEST(test_is_assignable) + { + #if ETL_USING_CPP17 + CHECK((etl::is_assignable_v) == (std::is_assignable_v)); + CHECK((etl::is_assignable_v) == (std::is_assignable_v)); + CHECK((etl::is_assignable_v) == (std::is_assignable_v)); + #else + CHECK((etl::is_assignable::value) == (std::is_assignable::value)); + CHECK((etl::is_assignable::value) == (std::is_assignable::value)); + CHECK((etl::is_assignable::value) == (std::is_assignable::value)); + #endif + } - // Free function pointer - CHECK_FALSE((etl::is_member_function_pointer::value)); + //************************************************************************* + TEST(test_is_lvalue_assignable) + { + #if ETL_USING_STL || defined(ETL_USE_TYPE_TRAITS_BUILTINS) || defined(ETL_USER_DEFINED_TYPE_TRAITS) + #if ETL_USING_CPP17 + CHECK((etl::is_lvalue_assignable_v)); + CHECK(!(etl::is_lvalue_assignable_v)); + CHECK((etl::is_lvalue_assignable_v)); + #else + CHECK((etl::is_lvalue_assignable::value)); + CHECK(!(etl::is_lvalue_assignable::value)); + CHECK((etl::is_lvalue_assignable::value)); + #endif + #endif + } - // Member object pointer - CHECK_FALSE((etl::is_member_function_pointer::value)); + //************************************************************************* + TEST(test_is_constructible) + { + #if ETL_USING_CPP17 + CHECK((etl::is_constructible_v) == (std::is_constructible_v)); + CHECK((etl::is_constructible_v) == (std::is_constructible_v)); + CHECK((etl::is_constructible_v) == (std::is_constructible_v)); + CHECK((etl::is_constructible_v) == (std::is_constructible_v)); + #else + CHECK((etl::is_constructible::value) == (std::is_constructible::value)); + CHECK((etl::is_constructible::value) == (std::is_constructible::value)); + CHECK((etl::is_constructible::value) == (std::is_constructible::value)); + CHECK((etl::is_constructible::value) == (std::is_constructible::value)); + #endif + } - // Plain function type (not pointer) - CHECK_FALSE((etl::is_member_function_pointer::value)); + //************************************************************************* + TEST(test_is_default_constructible) + { + #if ETL_USING_CPP17 + CHECK((etl::is_default_constructible_v) == (std::is_default_constructible_v)); + CHECK((etl::is_default_constructible_v) == (std::is_default_constructible_v)); + CHECK((etl::is_default_constructible_v) == (std::is_default_constructible_v)); + CHECK((etl::is_default_constructible_v) == (std::is_default_constructible_v)); + #else + CHECK((etl::is_default_constructible::value) == (std::is_default_constructible::value)); + CHECK((etl::is_default_constructible::value) == (std::is_default_constructible::value)); + CHECK((etl::is_default_constructible::value) == (std::is_default_constructible::value)); + CHECK((etl::is_default_constructible::value) == (std::is_default_constructible::value)); + #endif + } - // Non-function type - CHECK_FALSE((etl::is_member_function_pointer::value)); - } + //************************************************************************* + TEST(test_is_copy_constructible) + { + #if ETL_USING_CPP17 + CHECK((etl::is_copy_constructible_v) == (std::is_copy_constructible_v)); + CHECK((etl::is_copy_constructible_v) == (std::is_copy_constructible_v)); + CHECK((etl::is_copy_constructible_v) == (std::is_copy_constructible_v)); + #else + CHECK((etl::is_copy_constructible::value) == (std::is_copy_constructible::value)); + CHECK((etl::is_copy_constructible::value) == (std::is_copy_constructible::value)); + CHECK((etl::is_copy_constructible::value) == (std::is_copy_constructible::value)); + #endif + } - //************************************************************************* - // Member object pointer trait - TEST(test_is_member_object_pointer) - { - CHECK_TRUE((etl::is_member_object_pointer::value)); + //************************************************************************* + TEST(test_is_move_constructible) + { + #if ETL_USING_CPP17 + CHECK((etl::is_move_constructible_v) == (std::is_move_constructible_v)); + CHECK((etl::is_move_constructible_v) == (std::is_move_constructible_v)); + CHECK((etl::is_move_constructible_v) == (std::is_move_constructible_v)); + #else + CHECK((etl::is_move_constructible::value) == (std::is_move_constructible::value)); + CHECK((etl::is_move_constructible::value) == (std::is_move_constructible::value)); + CHECK((etl::is_move_constructible::value) == (std::is_move_constructible::value)); + #endif + } - // Not a member object pointer - CHECK_FALSE((etl::is_member_object_pointer::value)); - CHECK_FALSE((etl::is_member_object_pointer::value)); - } + //************************************************************************* + TEST(test_is_trivially_constructible) + { + #if ETL_USING_STL || defined(ETL_USE_TYPE_TRAITS_BUILTINS) || defined(ETL_USER_DEFINED_TYPE_TRAITS) + #if ETL_USING_CPP17 + CHECK((etl::is_trivially_constructible_v) == (std::is_trivially_constructible_v)); + CHECK((etl::is_trivially_constructible_v) == (std::is_trivially_constructible_v)); + CHECK((etl::is_trivially_constructible_v) == (std::is_trivially_constructible_v)); + #else + CHECK((etl::is_trivially_constructible::value) == (std::is_trivially_constructible::value)); + CHECK((etl::is_trivially_constructible::value) == (std::is_trivially_constructible::value)); + CHECK((etl::is_trivially_constructible::value) == (std::is_trivially_constructible::value)); + #endif + #endif + } - //************************************************************************* - // Member pointer (either member object or member function pointer) - TEST(test_is_member_pointer_any) - { - CHECK_TRUE((etl::is_member_pointer::value)); - CHECK_TRUE((etl::is_member_pointer::value)); + //************************************************************************* + TEST(test_is_trivially_copy_constructible) + { + #if ETL_USING_STL || defined(ETL_USE_TYPE_TRAITS_BUILTINS) || defined(ETL_USER_DEFINED_TYPE_TRAITS) + #if ETL_USING_CPP17 + CHECK((etl::is_trivially_copy_constructible_v) == (std::is_trivially_copy_constructible_v)); + CHECK((etl::is_trivially_copy_constructible_v) == (std::is_trivially_copy_constructible_v)); + CHECK((etl::is_trivially_copy_constructible_v) == (std::is_trivially_copy_constructible_v)); + #else + CHECK((etl::is_trivially_copy_constructible::value) == (std::is_trivially_copy_constructible::value)); + CHECK((etl::is_trivially_copy_constructible::value) == (std::is_trivially_copy_constructible::value)); + CHECK((etl::is_trivially_copy_constructible::value) == (std::is_trivially_copy_constructible::value)); + #endif + #endif + } - // Not member pointers - CHECK_FALSE((etl::is_member_pointer::value)); - CHECK_FALSE((etl::is_member_pointer::value)); - } + //************************************************************************* + TEST(test_is_trivially_destructible) + { + #if ETL_USING_STL || defined(ETL_USE_TYPE_TRAITS_BUILTINS) || defined(ETL_USER_DEFINED_TYPE_TRAITS) + #if ETL_USING_CPP17 + CHECK((etl::is_trivially_destructible_v) == (std::is_trivially_destructible_v)); + CHECK((etl::is_trivially_destructible_v) == (std::is_trivially_destructible_v)); + CHECK((etl::is_trivially_destructible_v) == (std::is_trivially_destructible_v)); + #else + CHECK((etl::is_trivially_destructible::value) == (std::is_trivially_destructible::value)); + CHECK((etl::is_trivially_destructible::value) == (std::is_trivially_destructible::value)); + CHECK((etl::is_trivially_destructible::value) == (std::is_trivially_destructible::value)); + #endif + #endif + } - //************************************************************************* - // Function type detection - TEST(test_is_function) - { - (void)f(0); - (void)fvar(); - (void)fvar2(0); - (void)ft(0, 0.0); + //************************************************************************* + TEST(test_is_trivially_copy_assignable) + { + #if (!(defined(ETL_COMPILER_GCC) && defined(ETL_USE_TYPE_TRAITS_BUILTINS))) + #if ETL_USING_STL || defined(ETL_USE_TYPE_TRAITS_BUILTINS) || defined(ETL_USER_DEFINED_TYPE_TRAITS) + #if ETL_USING_CPP17 + CHECK((etl::is_trivially_copy_assignable_v) == (std::is_trivially_copy_assignable_v)); + CHECK((etl::is_trivially_copy_assignable_v) == (std::is_trivially_copy_assignable_v)); + CHECK((etl::is_trivially_copy_assignable_v) == (std::is_trivially_copy_assignable_v)); + #else + CHECK((etl::is_trivially_copy_assignable::value) == (std::is_trivially_copy_assignable::value)); + CHECK((etl::is_trivially_copy_assignable::value) == (std::is_trivially_copy_assignable::value)); + CHECK((etl::is_trivially_copy_assignable::value) == (std::is_trivially_copy_assignable::value)); + #endif + #endif + #endif + } - CHECK_TRUE((etl::is_function::value)); - CHECK_TRUE((etl::is_function::value)); - CHECK_TRUE((etl::is_function::value)); - CHECK_TRUE((etl::is_function)>::value)); + //************************************************************************* + TEST(test_is_trivially_copyable) + { + #if (!(defined(ETL_COMPILER_GCC) && defined(ETL_USE_TYPE_TRAITS_BUILTINS))) + #if ETL_USING_STL || defined(ETL_USE_TYPE_TRAITS_BUILTINS) || defined(ETL_USER_DEFINED_TYPE_TRAITS) + #if ETL_USING_CPP17 + CHECK((etl::is_trivially_copyable_v) == (std::is_trivially_copyable_v)); + CHECK((etl::is_trivially_copyable_v) == (std::is_trivially_copyable_v)); + CHECK((etl::is_trivially_copyable_v) == (std::is_trivially_copyable_v)); + #else + CHECK((etl::is_trivially_copyable::value) == (std::is_trivially_copyable::value)); + CHECK((etl::is_trivially_copyable::value) == (std::is_trivially_copyable::value)); + CHECK((etl::is_trivially_copyable::value) == (std::is_trivially_copyable::value)); + #endif + #endif + #endif + } -#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE - (void)fn(0); - (void)fnvar(); - (void)fnvar2(0); - (void)fnt(0, 0.0); + //************************************************************************* + TEST(test_is_base_of_any) + { + struct Base {}; + struct D1 : Base {}; + struct D2 : Base {}; + struct D3 : Base {}; + struct D4 {}; - CHECK_TRUE((etl::is_function::value)); - CHECK_TRUE((etl::is_function::value)); - CHECK_TRUE((etl::is_function::value)); - CHECK_TRUE((etl::is_function)>::value)); -#endif + #if ETL_USING_CPP17 + CHECK_TRUE(bool(etl::is_base_of_any_v)); + CHECK_FALSE(bool(etl::is_base_of_any_v)); + #else + CHECK_TRUE(bool(etl::is_base_of_any::value)); + CHECK_FALSE(bool(etl::is_base_of_any::value)); + #endif + } - CHECK_FALSE((etl::is_function::value)); - CHECK_FALSE((etl::is_function::value)); - CHECK_FALSE((etl::is_function::value)); - CHECK_FALSE((etl::is_function::value)); // pointer, not function + //************************************************************************* + TEST(test_is_base_of_all) + { + struct Base {}; + struct D1 : Base {}; + struct D2 : Base {}; + struct D3 : Base {}; + struct D4 {}; + + #if ETL_USING_CPP17 + CHECK_TRUE(bool(etl::is_base_of_all_v)); + CHECK_FALSE(bool(etl::is_base_of_all_v)); + #else + CHECK_TRUE(bool(etl::is_base_of_all::value)); + CHECK_FALSE(bool(etl::is_base_of_all::value)); + #endif + } + + //************************************************************************* + TEST(test_nth_base) + { + struct D0 { }; + struct D1 : D0 { using base_type = D0; }; + struct D2 : D1 { using base_type = D1; }; + struct D3 : D2 { using base_type = D2; }; + struct D4 : D3 { using base_type = D3; }; + + CHECK_TRUE((std::is_same>::value)); + CHECK_TRUE((std::is_same>::value)); + CHECK_TRUE((std::is_same>::value)); + CHECK_TRUE((std::is_same>::value)); + CHECK_TRUE((std::is_same>::value)); + } + + //************************************************************************* + TEST(test_type_identity) + { + CHECK_CLOSE(type_identity_test_add(1.5f, 2), 3.5f, 0.01f); + } + + //************************************************************************* + #if ETL_USING_BUILTIN_UNDERLYING_TYPE + TEST(test_underlying_type) + { + enum enum0_t : char + { + }; + + enum enum1_t : uint32_t + { + }; + + enum class enum2_t : short + { + }; + + enum class enum3_t : size_t + { + }; + + using enum4_t = enum1_t; + using enum5_t = std::add_const::type; + + CHECK_TRUE((std::is_same::type, char>::value)); + CHECK_TRUE((std::is_same::type, uint32_t>::value)); + CHECK_TRUE((std::is_same::type, short>::value)); + CHECK_TRUE((std::is_same::type, size_t>::value)); + CHECK_TRUE((std::is_same::type, uint32_t>::value)); + CHECK_TRUE((std::is_same::type, short>::value)); + #if ETL_USING_CPP11 + CHECK_TRUE((std::is_same, char>::value)); + CHECK_TRUE((std::is_same, uint32_t>::value)); + CHECK_TRUE((std::is_same, short>::value)); + CHECK_TRUE((std::is_same, size_t>::value)); + CHECK_TRUE((std::is_same, uint32_t>::value)); + CHECK_TRUE((std::is_same, short>::value)); + #endif + } + #endif + + //************************************************************************* + TEST(test_has_duplicates) + { + #if ETL_USING_CPP17 + CHECK_FALSE((etl::has_duplicates_v)); + CHECK_FALSE((etl::has_duplicates_v)); + CHECK_TRUE((etl::has_duplicates_v)); + #else + CHECK_FALSE((etl::has_duplicates::value)); + CHECK_FALSE((etl::has_duplicates::value)); + CHECK_TRUE((etl::has_duplicates::value)); + #endif + } + + //************************************************************************* + TEST(test_has_duplicates_of) + { + #if ETL_USING_CPP17 + CHECK_FALSE((etl::has_duplicates_of_v)); + CHECK_TRUE((etl::has_duplicates_of_v)); // char is duplicated. + CHECK_FALSE((etl::has_duplicates_of_v)); // int is not duplicated. + #else + CHECK_FALSE((etl::has_duplicates_of::value)); + CHECK_TRUE((etl::has_duplicates_of::value)); // char is duplicated. + CHECK_FALSE((etl::has_duplicates_of::value)); // int is not duplicated. + #endif + } + + //************************************************************************* + TEST(test_count_of) + { + #if ETL_USING_CPP17 + CHECK_EQUAL(0, (etl::count_of_v)); + CHECK_EQUAL(0, (etl::count_of_v)); + CHECK_EQUAL(1, (etl::count_of_v)); + CHECK_EQUAL(1, (etl::count_of_v)); + CHECK_EQUAL(2, (etl::count_of_v)); + #else + CHECK_EQUAL(0, (etl::count_of::value)); + CHECK_EQUAL(0, (etl::count_of::value)); + CHECK_EQUAL(1, (etl::count_of::value)); + CHECK_EQUAL(1, (etl::count_of::value)); + CHECK_EQUAL(2, (etl::count_of::value)); + #endif + } + + //************************************************************************* + TEST(test_is_specialization) + { + #if ETL_USING_CPP17 + CHECK_TRUE((etl::is_specialization_v, specialized>)); + CHECK_FALSE((etl::is_specialization_v, specialized>)); + #else + CHECK_TRUE((etl::is_specialization, specialized>::value)); + CHECK_FALSE((etl::is_specialization, specialized>::value)); + #endif + } + + #if ETL_USING_CPP11 + //************************************************************************* + TEST(test_is_constant_evaluated) + { + constexpr bool c0 = etl::is_constant_evaluated(); + #if !ETL_USING_CPP23 && defined(ETL_COMPILER_MICROSOFT) + // Not supported on MSVC via __has_builtin, see determine_builtin_support.h + CHECK_FALSE(c0); + #else + CHECK_TRUE(c0); + #endif + + volatile int i = 1; + const bool c1 = (((i == 1) && etl::is_constant_evaluated()) ? true : false); + CHECK_FALSE(c1); + } + #endif + + //************************************************************************* + // Basic cv for member function pointers + TEST(test_is_member_function_pointer) + { + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + + #if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + #endif + + CHECK_TRUE((etl::is_member_function_pointer::value)); + CHECK_TRUE((etl::is_member_function_pointer::value)); + } + + //************************************************************************* + // Negative tests for member function pointer trait + TEST(test_is_member_function_pointer_negative) + { + (void)f(0); + + // Free function pointer + CHECK_FALSE((etl::is_member_function_pointer::value)); + + // Member object pointer + CHECK_FALSE((etl::is_member_function_pointer::value)); + + // Plain function type (not pointer) + CHECK_FALSE((etl::is_member_function_pointer::value)); + + // Non-function type + CHECK_FALSE((etl::is_member_function_pointer::value)); + } + + //************************************************************************* + // Member object pointer trait + TEST(test_is_member_object_pointer) + { + CHECK_TRUE((etl::is_member_object_pointer::value)); + + // Not a member object pointer + CHECK_FALSE((etl::is_member_object_pointer::value)); + CHECK_FALSE((etl::is_member_object_pointer::value)); + } + + //************************************************************************* + // Member pointer (either member object or member function pointer) + TEST(test_is_member_pointer_any) + { + CHECK_TRUE((etl::is_member_pointer::value)); + CHECK_TRUE((etl::is_member_pointer::value)); + + // Not member pointers + CHECK_FALSE((etl::is_member_pointer::value)); + CHECK_FALSE((etl::is_member_pointer::value)); + } + + //************************************************************************* + // Function type detection + TEST(test_is_function) + { + (void)f(0); + (void)fvar(); + (void)fvar2(0); + (void)ft(0, 0.0); + + CHECK_TRUE((etl::is_function::value)); + CHECK_TRUE((etl::is_function::value)); + CHECK_TRUE((etl::is_function::value)); + CHECK_TRUE((etl::is_function)>::value)); + + #if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + (void)fn(0); + (void)fnvar(); + (void)fnvar2(0); + (void)fnt(0, 0.0); + + CHECK_TRUE((etl::is_function::value)); + CHECK_TRUE((etl::is_function::value)); + CHECK_TRUE((etl::is_function::value)); + CHECK_TRUE((etl::is_function)>::value)); + #endif + + CHECK_FALSE((etl::is_function::value)); + CHECK_FALSE((etl::is_function::value)); + CHECK_FALSE((etl::is_function::value)); + CHECK_FALSE((etl::is_function::value)); // pointer, not function + } } } diff --git a/test/test_unaligned_type.cpp b/test/test_unaligned_type.cpp index 96827cba..f5be4d09 100644 --- a/test/test_unaligned_type.cpp +++ b/test/test_unaligned_type.cpp @@ -1030,7 +1030,7 @@ namespace CHECK_EQUAL(0x12, bev0); CHECK_EQUAL(0x34, bev1); } - }; + } } #include "etl/private/diagnostic_pop.h" diff --git a/test/test_unaligned_type_ext.cpp b/test/test_unaligned_type_ext.cpp index 5d3b5975..a0ff0183 100644 --- a/test/test_unaligned_type_ext.cpp +++ b/test/test_unaligned_type_ext.cpp @@ -1520,7 +1520,7 @@ namespace CHECK_EQUAL(0x12, bev0); CHECK_EQUAL(0x34, bev1); } - }; + } } #include "etl/private/diagnostic_pop.h" diff --git a/test/test_uncopyable.cpp b/test/test_uncopyable.cpp index f059dfa7..e0750290 100644 --- a/test/test_uncopyable.cpp +++ b/test/test_uncopyable.cpp @@ -62,5 +62,5 @@ namespace uc3 = uc1; // compile error } #endif - }; + } } diff --git a/test/test_unordered_map.cpp b/test/test_unordered_map.cpp index c38fb0dd..f326d037 100644 --- a/test/test_unordered_map.cpp +++ b/test/test_unordered_map.cpp @@ -1431,5 +1431,5 @@ namespace CHECK_TRUE(data.contains("FF")); CHECK_FALSE(data.contains(not_inserted)); } - }; + } } diff --git a/test/test_unordered_multimap.cpp b/test/test_unordered_multimap.cpp index 716636e0..dff743b2 100644 --- a/test/test_unordered_multimap.cpp +++ b/test/test_unordered_multimap.cpp @@ -1248,5 +1248,5 @@ namespace CHECK_TRUE(data.contains("FF")); CHECK_FALSE(data.contains(not_inserted)); } - }; + } } diff --git a/test/test_unordered_multiset.cpp b/test/test_unordered_multiset.cpp index 27bfe310..0992e4e6 100644 --- a/test/test_unordered_multiset.cpp +++ b/test/test_unordered_multiset.cpp @@ -1103,5 +1103,5 @@ namespace CHECK_TRUE(data.contains("FF")); CHECK_FALSE(data.contains(not_inserted)); } - }; + } } diff --git a/test/test_unordered_set.cpp b/test/test_unordered_set.cpp index 189f9761..c9a4ac96 100644 --- a/test/test_unordered_set.cpp +++ b/test/test_unordered_set.cpp @@ -1068,5 +1068,5 @@ namespace CHECK_TRUE(data.contains("FF")); CHECK_FALSE(data.contains(not_inserted)); } - }; + } } diff --git a/test/test_user_type.cpp b/test/test_user_type.cpp index 50523ad4..27c2f95c 100644 --- a/test/test_user_type.cpp +++ b/test/test_user_type.cpp @@ -175,8 +175,8 @@ namespace TEST(test_and_equal) { CompassDirection value = CompassDirection::North; - value &= 0xAAAAAAAAUL; - CompassDirection expected = CompassDirection(CompassDirection::North & 0xAAAAAAAAUL); + value &= static_cast(0xAAAAAAAAUL); + CompassDirection expected = CompassDirection(CompassDirection::North & static_cast(0xAAAAAAAAUL)); CHECK_EQUAL(expected, value); } @@ -185,8 +185,8 @@ namespace TEST(test_or_equal) { CompassDirection value = CompassDirection::North; - value |= 0xAAAAAAAAUL; - CompassDirection expected = CompassDirection(CompassDirection::North | 0xAAAAAAAAUL); + value |= static_cast(0xAAAAAAAAUL); + CompassDirection expected = CompassDirection(CompassDirection::North | static_cast(0xAAAAAAAAUL)); CHECK_EQUAL(expected, value); } @@ -195,8 +195,8 @@ namespace TEST(test_xor_equal) { CompassDirection value = CompassDirection::North; - value ^= 0xAAAAAAAAUL; - CompassDirection expected = CompassDirection(CompassDirection::North ^ 0xAAAAAAAAUL); + value ^= static_cast(0xAAAAAAAAUL); + CompassDirection expected = CompassDirection(CompassDirection::North ^ static_cast(0xAAAAAAAAUL)); CHECK_EQUAL(expected, value); } @@ -220,5 +220,5 @@ namespace CHECK_EQUAL(expected, value); } - }; + } } diff --git a/test/test_utility.cpp b/test/test_utility.cpp index 60c5163c..1757a499 100644 --- a/test/test_utility.cpp +++ b/test/test_utility.cpp @@ -825,43 +825,43 @@ namespace CHECK_EQUAL(a_b[2], 0x34567890); CHECK_EQUAL(a_b[3], 0x09876543); } - }; #if ETL_USING_CPP17 && !defined(ETL_FORCE_CPP11_NONTYPE) - //********************************* - TEST(test_nontype_t_cpp17) - { - // Test with int - CHECK_TRUE(42 == etl::nontype_t<42>::value); + //********************************* + TEST(test_nontype_t_cpp17) + { + // Test with int + CHECK_TRUE(42 == etl::nontype_t<42>::value); - // Test with bool - CHECK_TRUE(true == etl::nontype_t::value); + // Test with bool + CHECK_TRUE(true == etl::nontype_t::value); - // Test with char - CHECK_TRUE('A' == etl::nontype_t<'A'>::value); + // Test with char + CHECK_TRUE('A' == etl::nontype_t<'A'>::value); - // Test with enum - enum class E : uint8_t { A = 1, B = 2 }; - CHECK_TRUE(E::A == etl::nontype_t::value); - CHECK_TRUE(E::B == etl::nontype_t::value); - } + // Test with enum + enum class E : uint8_t { A = 1, B = 2 }; + CHECK_TRUE(E::A == etl::nontype_t::value); + CHECK_TRUE(E::B == etl::nontype_t::value); + } #elif ETL_USING_CPP11 - enum class E : uint8_t { A = 1, B = 2 }; + enum class E : uint8_t { A = 1, B = 2 }; - TEST(test_nontype_t_cpp11) - { - // Test with int - CHECK_TRUE(42 == (etl::nontype_t::value)); + TEST(test_nontype_t_cpp11) + { + // Test with int + CHECK_TRUE(42 == (etl::nontype_t::value)); - // Test with bool - CHECK_TRUE(true == (etl::nontype_t::value)); + // Test with bool + CHECK_TRUE(true == (etl::nontype_t::value)); - // Test with char - CHECK_TRUE('A' == (etl::nontype_t::value)); + // Test with char + CHECK_TRUE('A' == (etl::nontype_t::value)); - // Test with enum - CHECK_TRUE(E::A == (etl::nontype_t::value)); - CHECK_TRUE(E::B == (etl::nontype_t::value)); - } + // Test with enum + CHECK_TRUE(E::A == (etl::nontype_t::value)); + CHECK_TRUE(E::B == (etl::nontype_t::value)); + } #endif + } } diff --git a/test/test_variance.cpp b/test/test_variance.cpp index b09a7c0f..5a63e464 100644 --- a/test/test_variance.cpp +++ b/test/test_variance.cpp @@ -142,5 +142,5 @@ namespace variance_result = variance1.get_variance(); CHECK_CLOSE(9.17, variance_result, 0.1); } - }; + } } diff --git a/test/test_variant_legacy.cpp b/test/test_variant_legacy.cpp index 73c26ef7..e0f8e2f2 100644 --- a/test/test_variant_legacy.cpp +++ b/test/test_variant_legacy.cpp @@ -961,7 +961,7 @@ namespace type = etl::legacy::visit(visitor, variant_const); CHECK_EQUAL(70, type); } - }; + } } #include "etl/private/diagnostic_pop.h" \ No newline at end of file diff --git a/test/test_variant_pool.cpp b/test/test_variant_pool.cpp index a2202709..ece9796c 100644 --- a/test/test_variant_pool.cpp +++ b/test/test_variant_pool.cpp @@ -310,5 +310,5 @@ namespace p = variant_pool2.create(); CHECK_THROW(variant_pool1.destroy(p), etl::pool_object_not_in_pool); } - }; + } } diff --git a/test/test_variant_pool_external_buffer.cpp b/test/test_variant_pool_external_buffer.cpp index 4756d884..411680ac 100644 --- a/test/test_variant_pool_external_buffer.cpp +++ b/test/test_variant_pool_external_buffer.cpp @@ -325,5 +325,5 @@ namespace delete[] buffer1; delete[] buffer2; } - }; + } } diff --git a/test/test_variant_variadic.cpp b/test/test_variant_variadic.cpp index 74518be9..dc8373ac 100644 --- a/test/test_variant_variadic.cpp +++ b/test/test_variant_variadic.cpp @@ -2138,7 +2138,7 @@ namespace CHECK_TRUE(variant1.is_supported_type()); CHECK_FALSE(variant1.is_supported_type()); } - }; + } } #include "etl/private/diagnostic_pop.h" diff --git a/test/test_vector.cpp b/test/test_vector.cpp index f7df1aaf..03f6a615 100644 --- a/test/test_vector.cpp +++ b/test/test_vector.cpp @@ -1620,5 +1620,5 @@ namespace CHECK(std::equal(blank_data.begin(), blank_data.end(), data.begin())); } - }; + } } diff --git a/test/test_vector_external_buffer.cpp b/test/test_vector_external_buffer.cpp index a8b0c07b..912ebc29 100644 --- a/test/test_vector_external_buffer.cpp +++ b/test/test_vector_external_buffer.cpp @@ -1320,5 +1320,5 @@ namespace CHECK_EQUAL(raw[4].i, dest[6].i); CHECK_EQUAL(raw[5].i, dest[7].i); } - }; + } } diff --git a/test/test_vector_non_trivial.cpp b/test/test_vector_non_trivial.cpp index 413ca3cd..aabd0e4a 100644 --- a/test/test_vector_non_trivial.cpp +++ b/test/test_vector_non_trivial.cpp @@ -1407,5 +1407,5 @@ namespace const DataNDC initial2(initial_data.begin(), initial_data.end()); CHECK((initial >= initial2) == (initial_data >= initial_data)); } - }; + } } diff --git a/test/test_vector_pointer.cpp b/test/test_vector_pointer.cpp index aa41eac0..ee6ce915 100644 --- a/test/test_vector_pointer.cpp +++ b/test/test_vector_pointer.cpp @@ -2199,5 +2199,5 @@ namespace CHECK_EQUAL(9, *data[9]); } #endif - }; + } } diff --git a/test/test_vector_pointer_external_buffer.cpp b/test/test_vector_pointer_external_buffer.cpp index 330801d8..e6be4831 100644 --- a/test/test_vector_pointer_external_buffer.cpp +++ b/test/test_vector_pointer_external_buffer.cpp @@ -2013,5 +2013,5 @@ namespace CHECK(i1 == *i2); CHECK(&i1 == i2); } - }; + } } diff --git a/test/test_xor_checksum.cpp b/test/test_xor_checksum.cpp index eb2e450e..95eac2fd 100644 --- a/test/test_xor_checksum.cpp +++ b/test/test_xor_checksum.cpp @@ -144,6 +144,6 @@ namespace CHECK_EQUAL(hash1, hash2); CHECK_EQUAL(hash1, hash3); } - }; + } } diff --git a/test/test_xor_rotate_checksum.cpp b/test/test_xor_rotate_checksum.cpp index 94fd886f..db9a8a12 100644 --- a/test/test_xor_rotate_checksum.cpp +++ b/test/test_xor_rotate_checksum.cpp @@ -153,6 +153,6 @@ namespace CHECK_EQUAL(hash1, hash2); CHECK_EQUAL(hash1, hash3); } - }; + } } diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index af36ac3b..1af8495a 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -3722,9 +3722,6 @@ Tests\Misc - - Tests - Tests\Syntax Checks\Source @@ -3737,6 +3734,9 @@ Tests\State Machines + + Tests\Callbacks & Delegates + From cb2b3fe6f4e778e1bbe5d608ce790b43f9fca3f0 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 16 Dec 2025 10:41:53 +0000 Subject: [PATCH 033/298] Added --pedandic-errors and -Werror to CMakeLists.txt --- test/CMakeLists.txt | 4 ++-- test/syntax_check/CMakeLists.txt | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 2afa0473..00934d8d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -460,7 +460,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") PRIVATE -fno-omit-frame-pointer -fno-common -# -pedantic-errors + -pedantic-errors -Wall -Wextra -Werror @@ -477,7 +477,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") PRIVATE -fno-omit-frame-pointer -fno-common -# -pedantic-errors + -pedantic-errors -Wall -Wextra -Werror diff --git a/test/syntax_check/CMakeLists.txt b/test/syntax_check/CMakeLists.txt index e6316fc7..17e36bff 100644 --- a/test/syntax_check/CMakeLists.txt +++ b/test/syntax_check/CMakeLists.txt @@ -40,6 +40,7 @@ target_compile_options(tests PRIVATE -fsyntax-only -pedantic-errors + -Werror -Wextra-semi ) endif () @@ -48,6 +49,7 @@ target_compile_options(tests PRIVATE -fsyntax-only -pedantic-errors + -Werror -Wextra-semi -Wextra-semi-stmt -Wc++11-extra-semi From 6f11b19cfa457f1099e35e3d8f302ff6f6b9b955 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 17 Dec 2025 09:55:35 +0000 Subject: [PATCH 034/298] Remove legacy VS2019 project --- test/vs2019/.gitignore | 7 - test/vs2019/NatvisFile.natvis | 3 - test/vs2019/cpp.hint | 53 - test/vs2019/etl.sln | 157 - test/vs2019/etl.vcxproj | 13584 ---------------- test/vs2019/etl.vcxproj.filters | 3599 ---- .../etl_initialiser_list.vcxproj | 149 - .../etl_initialiser_list.vcxproj.filters | 22 - 8 files changed, 17574 deletions(-) delete mode 100644 test/vs2019/.gitignore delete mode 100644 test/vs2019/NatvisFile.natvis delete mode 100644 test/vs2019/cpp.hint delete mode 100644 test/vs2019/etl.sln delete mode 100644 test/vs2019/etl.vcxproj delete mode 100644 test/vs2019/etl.vcxproj.filters delete mode 100644 test/vs2019/etl_initialiser_list/etl_initialiser_list.vcxproj delete mode 100644 test/vs2019/etl_initialiser_list/etl_initialiser_list.vcxproj.filters diff --git a/test/vs2019/.gitignore b/test/vs2019/.gitignore deleted file mode 100644 index e3cb4a54..00000000 --- a/test/vs2019/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -/random_clcg.csv -/random_lcg.csv -/random_lsfr.csv -/random_mwc.csv -/random_xorshift.csv -/random_pcg.csv -/random_hash.csv diff --git a/test/vs2019/NatvisFile.natvis b/test/vs2019/NatvisFile.natvis deleted file mode 100644 index e78c2e3b..00000000 --- a/test/vs2019/NatvisFile.natvis +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/test/vs2019/cpp.hint b/test/vs2019/cpp.hint deleted file mode 100644 index 0fd4bafc..00000000 --- a/test/vs2019/cpp.hint +++ /dev/null @@ -1,53 +0,0 @@ -// Hint files help the Visual Studio IDE interpret Visual C++ identifiers -// such as names of functions and macros. -// For more information see https://go.microsoft.com/fwlink/?linkid=865984 -#define ETL_CONSTEXPR -#define ETL_CONSTEXPR14 -#define ETL_CONSTEXPR17 -#define ETL_IF_CONSTEXPR -#define ETL_DELETE -#define ETL_NOEXCEPT -#define ETL_NOEXCEPT_EXPR -#define ETL_NODISCARD -#define ETL_OVERRIDE -#define ETL_FINAL -#define ETL_DEPRECATED -#define ETL_ERROR_TEXT -#define ETL_ASSERT -#define ETL_ERROR -#define ETL_VERBOSE_ERRORS -#define ETL_FILE -#define ETL_NULLPTR -#define ETL_CPP11_SUPPORTED -#define ETL_CPP14_SUPPORTED -#define ETL_CPP17_SUPPORTED - -#define TEST -#define CHECK -#define CHECK_EQUAL -#define CHECK_THROW -// Hint files help the Visual Studio IDE interpret Visual C++ identifiers -// such as names of functions and macros. -// For more information see https://go.microsoft.com/fwlink/?linkid=865984 -#define ETL_ASSERT(b, e) -#define ETL_ASSERT(b, e) {if (!(b)) {etl::error_handler::error((e)); throw((e));}} -#define ETL_ASSERT(b, e) {if (!(b)) {throw((e));}} -#define ETL_ASSERT(b, e) {if(!(b)) {etl::error_handler::error((e));}} -#define ETL_ASSERT(b, e) assert((b)) -// Hint files help the Visual Studio IDE interpret Visual C++ identifiers -// such as names of functions and macros. -// For more information see https://go.microsoft.com/fwlink/?linkid=865984 -#define ETL_NULLPTR -// Hint files help the Visual Studio IDE interpret Visual C++ identifiers -// such as names of functions and macros. -// For more information see https://go.microsoft.com/fwlink/?linkid=865984 -#define ETL_NODISCARD [[nodiscard]] -#define ETL_NODISCARD -// Hint files help the Visual Studio IDE interpret Visual C++ identifiers -// such as names of functions and macros. -// For more information see https://go.microsoft.com/fwlink/?linkid=865984 -#define ETL_CONSTEXPR -// Hint files help the Visual Studio IDE interpret Visual C++ identifiers -// such as names of functions and macros. -// For more information see https://go.microsoft.com/fwlink/?linkid=865984 -#define ETL_NOEXCEPT diff --git a/test/vs2019/etl.sln b/test/vs2019/etl.sln deleted file mode 100644 index e38c4030..00000000 --- a/test/vs2019/etl.sln +++ /dev/null @@ -1,157 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29926.136 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "etl", "etl.vcxproj", "{C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug Intel - No STL|Win32 = Debug Intel - No STL|Win32 - Debug Intel - No STL|x64 = Debug Intel - No STL|x64 - Debug Intel|Win32 = Debug Intel|Win32 - Debug Intel|x64 = Debug Intel|x64 - Debug LLVM - No STL - Force Built-ins|Win32 = Debug LLVM - No STL - Force Built-ins|Win32 - Debug LLVM - No STL - Force Built-ins|x64 = Debug LLVM - No STL - Force Built-ins|x64 - Debug LLVM - No STL|Win32 = Debug LLVM - No STL|Win32 - Debug LLVM - No STL|x64 = Debug LLVM - No STL|x64 - Debug LLVM|Win32 = Debug LLVM|Win32 - Debug LLVM|x64 = Debug LLVM|x64 - Debug MSVC - Force C++03|Win32 = Debug MSVC - Force C++03|Win32 - Debug MSVC - Force C++03|x64 = Debug MSVC - Force C++03|x64 - Debug MSVC - No STL - Auto Built-ins|Win32 = Debug MSVC - No STL - Auto Built-ins|Win32 - Debug MSVC - No STL - Auto Built-ins|x64 = Debug MSVC - No STL - Auto Built-ins|x64 - Debug MSVC - No STL - Force Built-ins|Win32 = Debug MSVC - No STL - Force Built-ins|Win32 - Debug MSVC - No STL - Force Built-ins|x64 = Debug MSVC - No STL - Force Built-ins|x64 - Debug MSVC - No STL|Win32 = Debug MSVC - No STL|Win32 - Debug MSVC - No STL|x64 = Debug MSVC - No STL|x64 - Debug MSVC - No Tests|Win32 = Debug MSVC - No Tests|Win32 - Debug MSVC - No Tests|x64 = Debug MSVC - No Tests|x64 - Debug MSVC - Small Strings|Win32 = Debug MSVC - Small Strings|Win32 - Debug MSVC - Small Strings|x64 = Debug MSVC - Small Strings|x64 - Debug MSVC - String Truncation Is Error|Win32 = Debug MSVC - String Truncation Is Error|Win32 - Debug MSVC - String Truncation Is Error|x64 = Debug MSVC - String Truncation Is Error|x64 - Debug MSVC 64|Win32 = Debug MSVC 64|Win32 - Debug MSVC 64|x64 = Debug MSVC 64|x64 - Debug MSVC C++14 - No STL|Win32 = Debug MSVC C++14 - No STL|Win32 - Debug MSVC C++14 - No STL|x64 = Debug MSVC C++14 - No STL|x64 - Debug MSVC C++14|Win32 = Debug MSVC C++14|Win32 - Debug MSVC C++14|x64 = Debug MSVC C++14|x64 - Debug MSVC C++20 - No STL|Win32 = Debug MSVC C++20 - No STL|Win32 - Debug MSVC C++20 - No STL|x64 = Debug MSVC C++20 - No STL|x64 - Debug MSVC C++20|Win32 = Debug MSVC C++20|Win32 - Debug MSVC C++20|x64 = Debug MSVC C++20|x64 - Debug MSVC|Win32 = Debug MSVC|Win32 - Debug MSVC|x64 = Debug MSVC|x64 - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - MSVC - No STL -O2|Win32 = MSVC - No STL -O2|Win32 - MSVC - No STL -O2|x64 = MSVC - No STL -O2|x64 - MSVC Debug Appveyor|Win32 = MSVC Debug Appveyor|Win32 - MSVC Debug Appveyor|x64 = MSVC Debug Appveyor|x64 - MSVC Debug No STL Appveyor|Win32 = MSVC Debug No STL Appveyor|Win32 - MSVC Debug No STL Appveyor|x64 = MSVC Debug No STL Appveyor|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug Intel - No STL|Win32.ActiveCfg = Debug Intel - No STL|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug Intel - No STL|Win32.Build.0 = Debug Intel - No STL|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug Intel - No STL|x64.ActiveCfg = Debug Intel - No STL|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug Intel - No STL|x64.Build.0 = Debug Intel - No STL|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug Intel|Win32.ActiveCfg = Debug Intel|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug Intel|Win32.Build.0 = Debug Intel|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug Intel|x64.ActiveCfg = Debug Intel|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug Intel|x64.Build.0 = Debug Intel|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug LLVM - No STL - Force Built-ins|Win32.ActiveCfg = Debug|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug LLVM - No STL - Force Built-ins|Win32.Build.0 = Debug|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug LLVM - No STL - Force Built-ins|x64.ActiveCfg = Test2|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug LLVM - No STL - Force Built-ins|x64.Build.0 = Test2|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug LLVM - No STL|Win32.ActiveCfg = Debug LLVM - No STL|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug LLVM - No STL|Win32.Build.0 = Debug LLVM - No STL|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug LLVM - No STL|x64.ActiveCfg = DebugLLVMNoSTL|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug LLVM - No STL|x64.Build.0 = DebugLLVMNoSTL|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug LLVM|Win32.ActiveCfg = Debug LLVM|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug LLVM|Win32.Build.0 = Debug LLVM|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug LLVM|x64.ActiveCfg = Debug LLVM|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug LLVM|x64.Build.0 = Debug LLVM|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC - Force C++03|Win32.ActiveCfg = Debug MSVC - Force C++03|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC - Force C++03|Win32.Build.0 = Debug MSVC - Force C++03|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC - Force C++03|x64.ActiveCfg = Debug MSVC - Force C++03|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC - Force C++03|x64.Build.0 = Debug MSVC - Force C++03|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC - No STL - Auto Built-ins|Win32.ActiveCfg = Debug MSVC - No STL - Built-ins|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC - No STL - Auto Built-ins|Win32.Build.0 = Debug MSVC - No STL - Built-ins|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC - No STL - Auto Built-ins|x64.ActiveCfg = Test1|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC - No STL - Auto Built-ins|x64.Build.0 = Test1|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC - No STL - Force Built-ins|Win32.ActiveCfg = Debug MSVC - No STL - Force Built-ins|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC - No STL - Force Built-ins|Win32.Build.0 = Debug MSVC - No STL - Force Built-ins|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC - No STL - Force Built-ins|x64.ActiveCfg = Debug MSVC - No STL - Force Built-ins|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC - No STL - Force Built-ins|x64.Build.0 = Debug MSVC - No STL - Force Built-ins|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC - No STL|Win32.ActiveCfg = Debug - No STL|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC - No STL|Win32.Build.0 = Debug - No STL|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC - No STL|x64.ActiveCfg = DebugNoSTL|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC - No STL|x64.Build.0 = DebugNoSTL|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC - No Tests|Win32.ActiveCfg = Debug MSVC - No Tests|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC - No Tests|Win32.Build.0 = Debug MSVC - No Tests|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC - No Tests|x64.ActiveCfg = Debug MSVC - No Tests|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC - No Tests|x64.Build.0 = Debug MSVC - No Tests|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC - Small Strings|Win32.ActiveCfg = DebugMSVCSmallStrings|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC - Small Strings|Win32.Build.0 = DebugMSVCSmallStrings|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC - Small Strings|x64.ActiveCfg = DebugMSVCSmallStrings|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC - Small Strings|x64.Build.0 = DebugMSVCSmallStrings|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC - String Truncation Is Error|Win32.ActiveCfg = Debug|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC - String Truncation Is Error|Win32.Build.0 = Debug|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC - String Truncation Is Error|x64.ActiveCfg = DebugStringTruncationIsError|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC - String Truncation Is Error|x64.Build.0 = DebugStringTruncationIsError|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC 64|Win32.ActiveCfg = Debug|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC 64|Win32.Build.0 = Debug|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC 64|x64.ActiveCfg = Debug64|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC 64|x64.Build.0 = Debug64|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC C++14 - No STL|Win32.ActiveCfg = Debug MSVC C++14 - No STL|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC C++14 - No STL|Win32.Build.0 = Debug MSVC C++14 - No STL|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC C++14 - No STL|x64.ActiveCfg = Debug MSVC C++14 - No STL|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC C++14 - No STL|x64.Build.0 = Debug MSVC C++14 - No STL|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC C++14|Win32.ActiveCfg = Debug MSVC C++14|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC C++14|Win32.Build.0 = Debug MSVC C++14|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC C++14|x64.ActiveCfg = Debug MSVC C++14|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC C++14|x64.Build.0 = Debug MSVC C++14|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC C++20 - No STL|Win32.ActiveCfg = Debug MSVC C++20 - No STL|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC C++20 - No STL|Win32.Build.0 = Debug MSVC C++20 - No STL|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC C++20 - No STL|x64.ActiveCfg = Debug MSVC C++20 - No STL|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC C++20 - No STL|x64.Build.0 = Debug MSVC C++20 - No STL|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC C++20|Win32.ActiveCfg = Debug MSVC C++20|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC C++20|Win32.Build.0 = Debug MSVC C++20|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC C++20|x64.ActiveCfg = Debug MSVC C++20|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC C++20|x64.Build.0 = Debug MSVC C++20|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC|Win32.ActiveCfg = Debug|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC|Win32.Build.0 = Debug|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC|x64.ActiveCfg = Debug|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC|x64.Build.0 = Debug|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug|Win32.ActiveCfg = Debug|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug|Win32.Build.0 = Debug|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug|x64.ActiveCfg = Debug|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug|x64.Build.0 = Debug|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.MSVC - No STL -O2|Win32.ActiveCfg = MSVC - No STL -O2|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.MSVC - No STL -O2|Win32.Build.0 = MSVC - No STL -O2|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.MSVC - No STL -O2|x64.ActiveCfg = MSVC - No STL -O2|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.MSVC - No STL -O2|x64.Build.0 = MSVC - No STL -O2|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.MSVC Debug Appveyor|Win32.ActiveCfg = Debug|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.MSVC Debug Appveyor|Win32.Build.0 = Debug|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.MSVC Debug Appveyor|x64.ActiveCfg = MSVC Debug Appveyor|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.MSVC Debug Appveyor|x64.Build.0 = MSVC Debug Appveyor|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.MSVC Debug No STL Appveyor|Win32.ActiveCfg = MSVC Debug No STL Appveyor|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.MSVC Debug No STL Appveyor|Win32.Build.0 = MSVC Debug No STL Appveyor|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.MSVC Debug No STL Appveyor|x64.ActiveCfg = MSVC Debug No STL Appveyor|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.MSVC Debug No STL Appveyor|x64.Build.0 = MSVC Debug No STL Appveyor|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Release|Win32.ActiveCfg = Release|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Release|Win32.Build.0 = Release|Win32 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Release|x64.ActiveCfg = Release|x64 - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {0E35F961-E9EF-40C4-8E3E-2EC79B1D44B8} - EndGlobalSection -EndGlobal diff --git a/test/vs2019/etl.vcxproj b/test/vs2019/etl.vcxproj deleted file mode 100644 index 2a6518f0..00000000 --- a/test/vs2019/etl.vcxproj +++ /dev/null @@ -1,13584 +0,0 @@ - - - - - Debug Clang - Win32 - - - Debug Clang - x64 - - - Debug Intel - No STL - Win32 - - - Debug Intel - No STL - x64 - - - Debug Intel - Win32 - - - Debug Intel - x64 - - - Debug LLVM - No STL - Built-ins - Win32 - - - Debug LLVM - No STL - Built-ins - x64 - - - Debug LLVM C++20 - Win32 - - - Debug LLVM C++20 - x64 - - - Debug LLVM - Win32 - - - Debug LLVM - x64 - - - Debug MSVC - Force C++03 - Win32 - - - Debug MSVC - Force C++03 - x64 - - - Debug MSVC - Force cpp03 - Win32 - - - Debug MSVC - Force cpp03 - x64 - - - Debug MSVC - No STL - Built-ins - Win32 - - - Debug MSVC - No STL - Built-ins - x64 - - - Debug MSVC - No STL - Force Built-ins - Win32 - - - Debug MSVC - No STL - Force Built-ins - x64 - - - Debug MSVC - No STL - Force Constexpr Algorithms - Win32 - - - Debug MSVC - No STL - Force Constexpr Algorithms - x64 - - - Debug MSVC - No Tests - Win32 - - - Debug MSVC - No Tests - x64 - - - Debug MSVC - Small Strings - Win32 - - - Debug MSVC - Small Strings - x64 - - - Debug MSVC - No Checks - Win32 - - - Debug MSVC - No Checks - x64 - - - Debug MSVC C++14 - No STL - Win32 - - - Debug MSVC C++14 - No STL - x64 - - - Debug MSVC C++14 - Win32 - - - Debug MSVC C++14 - x64 - - - Debug MSVC C++20 - No STL - Win32 - - - Debug MSVC C++20 - No STL - x64 - - - Debug MSVC C++20 - Win32 - - - Debug MSVC C++20 - x64 - - - Debug64 - Win32 - - - Debug64 - x64 - - - Debug - No Unit Tests - Win32 - - - Debug - No Unit Tests - x64 - - - Debug LLVM - No STL - Win32 - - - Debug LLVM - No STL - x64 - - - Debug - No STL - Force No Advanced - Win32 - - - Debug - No STL - Force No Advanced - x64 - - - Debug - No STL - Win32 - - - Debug - No STL - x64 - - - Debug - String Truncation Is Error - Win32 - - - Debug - String Truncation Is Error - x64 - - - Debug - Win32 - - - Debug - x64 - - - MSVC - No STL -O2 - Win32 - - - MSVC - No STL -O2 - x64 - - - MSVC Debug - Appveyor - Win32 - - - MSVC Debug - Appveyor - x64 - - - MSVC Debug - No STL - Appveyor - Win32 - - - MSVC Debug - No STL - Appveyor - x64 - - - Release - Win32 - - - Release - x64 - - - - {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB} - Win32Proj - unittest - etl - 10.0 - - - - Application - true - v142 - Unicode - true - - - Application - true - Intel C++ Compiler 2022 - Unicode - false - - - Application - true - Intel C++ Compiler 2022 - Unicode - false - - - Application - true - v142 - Unicode - false - - - Application - true - v142 - Unicode - true - - - Application - true - v142 - Unicode - true - - - Application - true - v142 - Unicode - false - - - Application - true - v142 - Unicode - false - - - Application - true - v142 - Unicode - false - - - Application - true - v142 - Unicode - false - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - true - - - Application - true - v142 - Unicode - true - - - Application - true - v142 - Unicode - false - - - Application - true - v142 - Unicode - false - - - Application - true - v142 - Unicode - false - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - ClangCL - Unicode - false - - - Application - true - ClangCL - Unicode - false - - - Application - true - ClangCL - Unicode - false - - - Application - true - ClangCL - Unicode - - - Application - true - ClangCL - Unicode - - - Application - true - ClangCL - Unicode - false - - - Application - true - ClangCL - Unicode - true - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - - - Application - false - v142 - true - Unicode - - - v142 - - - v142 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - false - true - $(Configuration)\ - - - false - true - $(Configuration)\ - - - false - true - $(Configuration)\ - - - false - false - $(Configuration)\ - - - false - true - $(Configuration)\ - - - false - true - $(Configuration)\ - - - false - true - $(Configuration)\ - - - false - true - $(Configuration)\ - - - false - true - $(Configuration)\ - - - false - true - $(Configuration)\ - $(SolutionDir)$(Configuration)\ - - - false - true - $(Configuration)\ - - - false - true - $(Configuration)\ - - - true - true - \$(IntDir) - - - false - false - $(Configuration)\ - - - false - true - $(Configuration)\ - - - false - true - $(Configuration)\ - - - false - true - $(Configuration)\ - - - true - true - \$(IntDir) - - - false - true - $(Configuration)\ - - - false - true - $(Configuration)\ - - - false - true - $(Configuration)\ - - - false - true - $(Configuration)\ - - - false - true - $(Configuration)\ - - - false - true - $(Configuration)\ - - - false - true - $(Configuration)\ - - - false - true - $(Configuration)\ - - - false - true - \$(IntDir) - - - false - true - \$(IntDir) - - - false - true - $(Configuration)\ - - - false - true - $(Configuration)\ - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - false - true - $(Configuration)\ - - - true - true - - - false - true - - - true - true - - - false - true - - - false - true - - - - - - Level2 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../../unittest-cpp/;../../include;../../test - - - true - stdcpp17 - ProgramDatabase - /Zc:__cplusplus %(AdditionalOptions) - true - - - Console - true - - - "$(OutDir)\etl.exe" - - - - - - - Level2 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;ETL_NO_STL;%(PreprocessorDefinitions) - ../../../unittest-cpp/;../../include;../../test - - - true - stdcpp17 - EditAndContinue - /Zc:__cplusplus %(AdditionalOptions) - true - - - Console - true - - - "$(OutDir)\etl.exe" - - - - - - - Level2 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../../unittest-cpp/;../../include;../../test - - - true - stdcpp17 - EditAndContinue - /Zc:__cplusplus %(AdditionalOptions) - true - - - Console - true - - - "$(OutDir)\etl.exe" - - - - - - - Level2 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../../unittest-cpp/;../../include;../../test - - - true - stdcpp17 - EditAndContinue - /Zc:__cplusplus %(AdditionalOptions) - true - - - Console - true - - - - - - - - - - - Level2 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../../unittest-cpp/;../../include;../../test - - - true - stdcpp20 - EditAndContinue - /Zc:__cplusplus %(AdditionalOptions) - true - - - Console - true - - - "$(OutDir)\etl.exe" - - - - - - - Level2 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../../unittest-cpp/;../../include;../../test - - - true - stdcpp14 - EditAndContinue - /Zc:__cplusplus %(AdditionalOptions) - true - - - Console - true - - - "$(OutDir)\etl.exe" - - - - - - - Level2 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;ETL_NO_STL;%(PreprocessorDefinitions) - ../../../unittest-cpp/;../../include;../../test - - - true - stdcpp20 - EditAndContinue - /Zc:__cplusplus %(AdditionalOptions) - true - - - Console - true - - - "$(OutDir)\etl.exe" - - - - - - - Level2 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;ETL_NO_STL;%(PreprocessorDefinitions) - ../../../unittest-cpp/;../../include;../../test - - - true - stdcpp14 - EditAndContinue - /Zc:__cplusplus %(AdditionalOptions) - true - - - Console - true - - - "$(OutDir)\etl.exe" - - - - - - - Level2 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;ETL_FORCE_TEST_CPP03_IMPLEMENTATION;%(PreprocessorDefinitions) - ../../../unittest-cpp/;../../include;../../test - - - true - stdcpp17 - EditAndContinue - /Zc:__cplusplus %(AdditionalOptions) - true - - - Console - true - - - "$(OutDir)\etl.exe" - - - - - - - Level2 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;ETL_FORCE_TEST_CPP03_IMPLEMENTATION;%(PreprocessorDefinitions) - ../../../unittest-cpp/;../../include;../../test - - - true - stdcpp17 - EditAndContinue - /Zc:__cplusplus %(AdditionalOptions) - true - - - Console - true - - - "$(OutDir)etl.exe" - - - - - - - Level2 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;ETL_DISABLE_STRING_TRUNCATION_CHECKS;ETL_DISABLE_STRING_CLEAR_AFTER_USE;%(PreprocessorDefinitions) - ../../../unittest-cpp/;../../include;../../test - - - false - stdcpp17 - /Zc:__cplusplus %(AdditionalOptions) - true - - - Console - true - - - "$(OutDir)etl.exe" - - - - - - - Level2 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;ETL_TEMPLATE_DEDUCTION_GUIDE_TESTS_DISABLED;%(PreprocessorDefinitions) - ../../../unittest-cpp/;../../include;../../test - - - false - stdcpp17 - /Zc:__cplusplus %(AdditionalOptions) - true - - - Console - true - - - "$(OutDir)etl.exe" - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../../unittest-cpp/;../../include;../../test - - - false - stdcpp17 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level2 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;ETL_NO_CHECKS;%(PreprocessorDefinitions) - ../../../unittest-cpp/;../../include;../../test - - - false - stdcpp17 - /Zc:__cplusplus %(AdditionalOptions) - true - - - Console - true - - - "$(OutDir)etl.exe" - - - - - - - Level2 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;ETL_STRING_TRUNCATION_IS_ERROR;%(PreprocessorDefinitions) - ../../../unittest-cpp/;../../include;../../test - - - false - stdcpp17 - /Zc:__cplusplus %(AdditionalOptions) - true - - - Console - true - - - "$(OutDir)etl.exe" - - - - - - - Level2 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_SILENCE_CXX17_ADAPTOR_TYPEDEFS_DEPRECATION_WARNING;ETL_NO_STL;ETL_FORCE_STD_INITIALIZER_LIST;%(PreprocessorDefinitions) - ./;../../../unittest-cpp/;../../include;../../test - - - true - stdcpp17 - ProgramDatabase - /Zc:__cplusplus %(AdditionalOptions) - true - - - Console - true - - - "$(OutDir)etl.exe" - - - - - - - Level2 - MaxSpeed - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_SILENCE_CXX17_ADAPTOR_TYPEDEFS_DEPRECATION_WARNING;ETL_NO_STL;ETL_FORCE_STD_INITIALIZER_LIST;%(PreprocessorDefinitions) - ./;../../../unittest-cpp/;../../include;../../test - - - true - stdcpp17 - ProgramDatabase - /Zc:__cplusplus %(AdditionalOptions) - true - - - Console - true - - - "$(OutDir)etl.exe" - - - - - - - Level2 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_SILENCE_CXX17_ADAPTOR_TYPEDEFS_DEPRECATION_WARNING;ETL_NO_STL;%(PreprocessorDefinitions) - ./;../../../unittest-cpp/;../../include;../../test - - - true - stdcpp17 - ProgramDatabase - /Zc:__cplusplus %(AdditionalOptions) - true - - - Console - true - - - "$(OutDir)etl.exe" - - - - - - - Level2 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_SILENCE_CXX17_ADAPTOR_TYPEDEFS_DEPRECATION_WARNING;ETL_NO_STL;ETL_USE_MEM_BUILTINS;ETL_USE_TYPE_TRAITS_BUILTINS;ETL_USING_BUILTIN_MEMCPY=0;ETL_USING_BUILTIN_MEMMOVE=0;ETL_USING_BUILTIN_MEMSET=0;%(PreprocessorDefinitions) - ./;../../../unittest-cpp/;../../include;../../test - - - true - stdcpp17 - ProgramDatabase - /Zc:__cplusplus %(AdditionalOptions) - true - - - Console - true - - - "$(OutDir)etl.exe" - - - - - - - Level2 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_SILENCE_CXX17_ADAPTOR_TYPEDEFS_DEPRECATION_WARNING;ETL_NO_STL;ETL_FORCE_CONSTEXPR_ALGORITHMS=1;%(PreprocessorDefinitions) - ./;../../../unittest-cpp/;../../include;../../test - - - true - stdcpp17 - ProgramDatabase - /Zc:__cplusplus %(AdditionalOptions) - true - - - Console - true - - - "$(OutDir)etl.exe" - - - - - - - Level2 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_SILENCE_CXX17_ADAPTOR_TYPEDEFS_DEPRECATION_WARNING;ETL_NO_STL;ETL_TEMPLATE_DEDUCTION_GUIDE_TESTS_DISABLED;%(PreprocessorDefinitions) - ./;../../../unittest-cpp/;../../include;../../test - - - false - stdcpp17 - /Zc:__cplusplus %(AdditionalOptions) - true - - - Console - true - - - "$(OutDir)etl.exe" - - - - - - - Level2 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_SILENCE_CXX17_ADAPTOR_TYPEDEFS_DEPRECATION_WARNING;ETL_NO_STL;ETL_FORCE_NO_ADVANCED_CPP;%(PreprocessorDefinitions) - ../../../unittest-cpp/;../../include;../../test - - - false - stdcpp17 - /Zc:__cplusplus %(AdditionalOptions) - true - - - Console - true - - - "$(OutDir)etl.exe" - - - - - - - Level2 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;__clang__;%(PreprocessorDefinitions) - ../../../unittest-cpp/;../../include;../../test - - - false - stdcpp17 - false - ProgramDatabase - /Zc:__cplusplus %(AdditionalOptions) - true - - - Console - false - - - "$(OutDir)etl.exe" - - - - - - - Level2 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;__clang__;%(PreprocessorDefinitions) - ../../../unittest-cpp/;../../include;../../test - - - false - stdcpp20 - false - ProgramDatabase - /Zc:__cplusplus %(AdditionalOptions) - true - - - Console - false - - - "$(OutDir)etl.exe" - - - - - - - Level2 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;ETL_NO_STL;__clang__;%(PreprocessorDefinitions) - ../../../unittest-cpp/;../../include;../../test - - - false - stdcpp17 - false - ProgramDatabase - /Zc:__cplusplus %(AdditionalOptions) - true - - - Console - false - - - "$(OutDir)etl.exe" - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;ETL_NO_STL;ETL_USE_TYPE_TRAITS_BUILTINS;__clang__;%(PreprocessorDefinitions) - ../../../unittest-cpp/;../../include;../../test - - - false - stdcpp17 - false - ProgramDatabase - -Wno-self-assign /Zc:__cplusplus %(AdditionalOptions) - - - Console - false - - - "$(OutDir)etl.exe" - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;ETL_NO_STL;__clang__;%(PreprocessorDefinitions) - ../../../unittest-cpp/;../../include;../../test - - - false - stdcpp17 - false - ProgramDatabase - -Wno-self-assign /Zc:__cplusplus %(AdditionalOptions) - - - Console - false - - - "$(OutDir)etl.exe" - - - - - - - Level2 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;ETL_NO_STL;ETL_USE_TYPE_TRAITS_BUILTINS;__clang__;%(PreprocessorDefinitions) - ./;../../../unittest-cpp/;../../include;../../test - - - false - stdcpp17 - false - ProgramDatabase - /Zc:__cplusplus %(AdditionalOptions) - true - - - Console - false - - - "$(OutDir)etl.exe" - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../../unittest-cpp/UnitTest++/;../../include;../../test - - - false - stdcpp17 - false - FullDebug - Default - - - Console - false - - - "$(OutDir)etl.exe" - - - - - - - Level2 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../../unittest-cpp/;../../include;../../test - - - false - stdcpp17 - false - FullDebug - Default - /Zc:__cplusplus %(AdditionalOptions) - true - - - Console - false - - - "$(OutDir)etl.exe" - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include/etl;../../test - - - false - stdcpp14 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include/etl;../../test - - - false - stdcpp14 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include/etl;../../test - - - false - stdcpp14 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include/etl;../../test - - - false - stdcpp14 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include/etl;../../test - - - false - stdcpp14 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include/etl;../../test - - - false - stdcpp14 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include/etl;../../test - - - false - stdcpp14 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include/etl;../../test - - - false - stdcpp14 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include/etl;../../test - - - false - stdcpp14 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include/etl;../../test - - - false - stdcpp14 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include/etl;../../test - - - false - stdcpp14 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include/etl;../../test - - - false - stdcpp14 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include/etl;../../test - - - false - stdcpp14 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include/etl;../../test - - - false - stdcpp14 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include/etl;../../test - - - false - stdcpp14 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include/etl;../../test - - - false - stdcpp14 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include/etl;../../test - - - false - stdcpp14 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include/etl;../../test - - - false - stdcpp14 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include/etl;../../test - - - false - stdcpp14 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include/etl;../../test - - - false - stdcpp14 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include/etl;../../test - - - false - stdcpp14 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include/etl;../../test - - - false - stdcpp14 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include/etl;../../test - - - false - stdcpp14 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include/etl;../../test - - - false - stdcpp14 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include/etl;../../test - - - false - stdcpp14 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include/etl;../../test - - - false - stdcpp14 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include/etl;../../test - - - false - stdcpp14 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include/etl;../../test - - - false - stdcpp14 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include/etl;../../test - - - false - stdcpp14 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level2 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../../unittest-cpp/;../../include;../../test - - - false - stdcpp17 - /Zc:__cplusplus %(AdditionalOptions) - true - - - Console - true - - - "$(OutDir)etl.exe" - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../include;../../test - - - false - stdcpp17 - - - Console - true - - - $(OutDir)\etl.exe - - - - - - - Level2 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../../unittest-cpp/;../../include;../../test - - - stdcpp17 - /Zc:__cplusplus %(AdditionalOptions) - true - - - Console - true - - - - - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../src;../../src/c;../../test - - - - - Console - true - - - - - - - - - Level2 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/;../../src - false - /Zc:__cplusplus %(AdditionalOptions) - true - - - Console - true - true - true - - - $(OutDir)\etl.exe - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - ../../unittest-cpp/UnitTest++/;../../src - false - - - Console - true - true - true - - - $(OutDir)\etl.exe - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - - - - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Default - MultiThreadedDLL - - - - - - - - ../../../unittest-cpp - ../../../unittest-cpp - false - false - - - - - - - - - - - - - - - - - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - - - - - - - - true - true - - - true - true - - - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - - - - - - - - - - - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - - - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - - - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - - - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - - - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - - - - - - - - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - - - true - true - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - - - - - - - - - - - - - - - - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - true - - - - - - - - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - stdcpp14 - stdcpp14 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/test/vs2019/etl.vcxproj.filters b/test/vs2019/etl.vcxproj.filters deleted file mode 100644 index 0be9eb80..00000000 --- a/test/vs2019/etl.vcxproj.filters +++ /dev/null @@ -1,3599 +0,0 @@ - - - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - {ecfaf316-dc6d-4dc1-9838-24061047ad63} - - - {53c3a373-0496-4db0-a981-86bf14a1fac9} - - - {dc39d09c-75c9-453f-8feb-9631a200c0f4} - - - {ab41d19f-82fe-4974-a73b-16aebfa1d03f} - - - {d56ca96b-66e1-46cb-83fd-1cd72c51d962} - - - {1c55dd7d-c04b-428c-810b-dd3a08fc4c65} - - - {7028012c-30c4-4993-b2d9-3b1521a610ae} - - - {6be3bc76-e17c-4be0-8b0b-d1053e1a1761} - - - {c1264f38-22fa-4fcb-8cab-f254b1290eab} - - - {39015d44-a7cb-47f0-a7dd-27714f852363} - - - {1c95b9c1-96c0-4c1e-8e5a-e6680d88276c} - - - {0a77d88b-f9f0-456a-be4b-c0a0ce6b437b} - - - {e4a699ae-e7f3-418e-bf9f-211c21f7f4b2} - - - {7371282e-fddc-4269-891b-e909f74ff8e9} - - - {4d08353c-b393-47c7-a9eb-c9f2f8c25887} - - - {0bcdf7f9-8e2b-4f70-932b-bde56404f421} - - - {da88d71d-e5ea-4c26-9807-94616d31addb} - - - {0eaad66f-3ce3-4952-8ae8-c935e6aa7c1d} - - - {0d5824b1-3ef9-43e0-b2d5-15d6246b843e} - - - {c25471f3-451a-4279-925d-cbdcec912ef8} - - - {586d2c92-e504-4dea-9b1f-42d725a5272c} - - - {74399f00-a7a3-47e3-9b27-d01fb2b5ce87} - - - {afc65d0e-d846-4e30-8723-06c8cefa3a36} - - - {ffb65df4-d5c7-44ab-a9c7-1150ddce2d6f} - - - {3353062c-e8dc-4095-b7cf-d11fc952263e} - - - {49e974a8-2dcc-40e6-b4ca-bad29f0cde52} - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {8a3300fa-c2cd-44dd-8582-692f97ec4dc0} - - - {ca522a34-8cf0-4f64-8ca1-33f52f65a9a7} - - - {ba2bf848-6023-4906-a0d4-14a4c8fba0e5} - - - {527f4d9a-8968-4352-8cdf-f6ccc391dcf9} - - - {57b110fa-b3d8-4cc4-9619-ca510a29c213} - - - {5b76fd56-eb83-489f-b9a6-798c07c5fa76} - - - {562466b5-677d-4448-9e9e-f70805cd71ad} - - - {66b8d39a-b610-4d5e-925a-4995f2ac74b2} - - - {a1af709b-90d3-4506-b742-3231d0fff1f5} - - - {43578ed8-b61d-4210-b5d4-bb4a26351934} - - - {c75cedd3-8b6c-4662-b965-aecbe7fd5d1c} - - - {da470864-7708-4e89-a24c-93a9ca2c4856} - - - {0873470d-a6d9-445c-bbc0-33252978ecff} - - - {b42bb316-6e55-4336-a72a-fc5f28d82ea5} - - - {a300635d-25da-4af6-b7e7-1e27ec9df921} - - - {e260d680-649f-41b5-844d-c736a252dcb5} - - - {21e56de9-b458-4395-9949-3abfb1f5723b} - - - {d115746e-4d33-41b4-b88f-9fb2ca225286} - - - {a1417994-24a2-40ae-a934-ea318299f91c} - - - {126a3068-3048-4210-8cdf-41ec9e2e1436} - - - {a8738fb5-ff9c-40c2-b3c0-4843ca55097c} - - - {89fc701f-b9ea-4ff3-beac-199c003c4b3e} - - - {d266eb8f-3f48-4625-98d8-47b6cd9f13a5} - - - {66f5995b-c1a1-4bc7-b09a-b0148613d77a} - - - {3820f2db-3b02-48c1-ac8c-c3ee4507ee45} - - - {2682377b-6037-4163-9097-3e3e9824e215} - - - {d37e1c04-f45f-4513-99cc-debbbcf7dead} - - - {236aa242-d71f-48bd-9169-cfa7cbff9f10} - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - {d138997a-b860-4420-9f45-87e9e2c52f3b} - - - {dc898ba2-50f4-4c3d-abee-039670df8582} - - - {a05ae045-3218-4ca2-9f25-08cc977898df} - - - {4dd0f57a-eeab-4910-a243-42c0950f0536} - - - {2759f13a-3c3c-4e91-a2f0-a300f1f50f77} - - - {107d7e33-580f-4dc5-be11-a4b2076c2c10} - - - {4ee68175-3bc2-4d30-b8bf-be7261124979} - - - {ba688ff7-bea4-4f7e-bfab-1033d3401426} - - - {ba80408c-0198-432a-a213-e4e2db946aab} - - - {0014395b-c658-4903-a15f-d21acb676d79} - - - {69ed2e1e-f009-4a1a-abf2-a9144142b533} - - - {78498646-3058-4d15-9d21-2243ca5d5cd4} - - - {19d7da41-01e8-4449-8b9b-14be81447752} - - - {de372ec9-d193-4956-871f-065414a9d3be} - - - - - ETL\Utilities - - - ETL\Utilities - - - ETL\Utilities - - - ETL\Containers - - - ETL\Containers - - - ETL\Containers - - - ETL\Containers - - - ETL\Containers - - - ETL\Utilities - - - ETL\Utilities - - - ETL\Utilities - - - ETL\Utilities - - - ETL\Utilities - - - ETL\Utilities - - - ETL\Patterns - - - ETL\Patterns - - - ETL\Utilities - - - ETL\Containers - - - ETL\Containers - - - ETL\Maths - - - ETL\Containers - - - ETL\Containers - - - ETL\Utilities - - - ETL\Utilities - - - ETL\Containers - - - ETL\Utilities - - - ETL\Utilities - - - ETL\Containers - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Utilities - - - ETL\Utilities - - - ETL\Utilities - - - ETL\Maths - - - ETL\Containers - - - ETL\Utilities - - - ETL\Utilities - - - ETL\Containers - - - ETL\Containers - - - ETL\Containers - - - ETL\Utilities - - - ETL\Containers - - - ETL\Containers - - - ETL\Containers - - - ETL\Containers - - - ETL\Containers - - - ETL\Containers - - - ETL\Containers - - - ETL\Utilities - - - ETL\Containers - - - ETL\Containers - - - ETL\Containers - - - ETL\Containers - - - ETL\Utilities - - - ETL\Utilities - - - ETL\Private - - - ETL\Utilities - - - ETL\Containers - - - ETL\Utilities - - - ETL\Containers - - - ETL\Containers - - - ETL\Utilities - - - ETL\Utilities - - - ETL\Utilities - - - ETL\Utilities - - - ETL\Containers - - - ETL\Containers - - - ETL\Containers - - - ETL\Containers - - - ETL\Frameworks - - - ETL\Containers - - - ETL\Frameworks - - - ETL\Frameworks - - - ETL\Maths - - - ETL\Utilities - - - ETL\Utilities - - - ETL\Maths - - - ETL\Utilities - - - ETL\Utilities - - - ETL\Frameworks - - - ETL\Frameworks - - - ETL\Utilities - - - ETL\Profiles - - - ETL\Profiles - - - ETL\Profiles - - - ETL\Profiles - - - ETL\Profiles - - - ETL\Profiles - - - ETL\Profiles - - - ETL\Profiles - - - ETL\Profiles - - - ETL\Profiles - - - ETL\Profiles - - - ETL\Utilities\Atomic - - - ETL\Containers - - - ETL\Containers - - - ETL\Containers - - - ETL\Utilities - - - ETL\Utilities\Atomic - - - ETL\Utilities\Atomic - - - ETL\Containers - - - ETL\Containers - - - ETL\Containers - - - ETL\Utilities\Mutex - - - ETL\Utilities\Mutex - - - ETL\Utilities\Mutex - - - ETL\Utilities - - - ETL\Maths - - - ETL\Maths - - - ETL\Utilities - - - ETL\Utilities - - - ETL\Maths - - - ETL\Profiles - - - ETL\Private - - - ETL\Profiles - - - ETL\Profiles - - - ETL\Profiles - - - ETL\Profiles - - - ETL\Profiles - - - ETL\Maths - - - ETL\Utilities - - - ETL\Private - - - ETL\Private - - - ETL\Private - - - ETL\Frameworks - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Frameworks - - - ETL\Containers - - - ETL\Utilities - - - ETL\Private - - - ETL\Containers - - - ETL\Utilities - - - ETL\Frameworks - - - ETL\Strings - - - ETL\Strings - - - ETL\Strings - - - ETL\Strings - - - ETL\Strings - - - ETL\Strings - - - ETL\Strings - - - ETL\Strings - - - ETL\Strings - - - ETL\Strings - - - ETL\Strings - - - ETL\Strings - - - ETL\Strings - - - ETL\Strings - - - ETL\Utilities - - - ETL\Profiles - - - ETL\Profiles - - - ETL\Profiles - - - ETL\Profiles - - - ETL\Profiles - - - ETL\Containers - - - ETL\Profiles - - - ETL\Profiles - - - ETL\Profiles - - - ETL\Private - - - ETL\Utilities - - - ETL\Utilities\Mutex - - - ETL\Utilities - - - ETL\Containers - - - ETL\Profiles - - - ETL\Profiles - - - ETL\Profiles - - - ETL\Profiles - - - ETL\Profiles - - - ETL\Profiles - - - ETL\Profiles - - - ETL\Utilities\Generators - - - ETL\Utilities\Generators - - - ETL\Utilities\Generators - - - ETL\Utilities\Generators - - - ETL\Utilities\Generators - - - ETL\Frameworks\Generators - - - ETL\Containers\Generators - - - ETL\Utilities - - - ETL\Strings - - - ETL\Strings - - - ETL\Strings - - - ETL\Strings - - - ETL\Strings - - - ETL\Strings - - - ETL\Pseudo Containers - - - ETL\Strings - - - ETL\Containers - - - ETL\Utilities - - - ETL\Utilities\Atomic - - - ETL\Containers - - - ETL\Utilities - - - ETL\Utilities\Mutex - - - ETL\Arduino - - - ETL\Utilities - - - ETL\Containers - - - ETL\Containers - - - ETL\Utilities - - - ETL\Utilities - - - ETL\Containers - - - ETL\Containers - - - ETL\Patterns - - - ETL\Containers - - - Tests\Sanity Checks\C++03 - - - Tests\Sanity Checks\C++11 - - - Tests\Sanity Checks\C++14 - - - Tests\Sanity Checks\C++17 - - - ETL\Private - - - ETL\Private - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Maths - - - ETL\Frameworks - - - ETL\Private - - - ETL\Private - - - ETL\Utilities - - - ETL\Containers - - - ETL\Private - - - ETL\Patterns - - - ETL\Patterns - - - ETL\Utilities - - - ETL\Utilities - - - ETL\Containers - - - ETL\Utilities\Mutex - - - ETL\Containers - - - ETL\Utilities - - - ETL\Private - - - ETL\Frameworks - - - ETL\Frameworks - - - ETL\Private - - - ETL\Private - - - ETL\Utilities - - - ETL\Utilities - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\CRC - - - ETL\Maths\Hash - - - ETL\Maths\Hash - - - ETL\Maths\Hash - - - ETL\Maths\Hash - - - ETL\Maths\Hash - - - ETL\Maths\Hash - - - ETL\Maths\Hash - - - ETL\Maths\Hash - - - Tests\Test Support - - - Tests\Test Support - - - Tests\Test Support - - - Tests\Test Support - - - Tests\Test Support - - - ETL\Profiles - - - ETL\Patterns - - - ETL\Utilities - - - ETL\Utilities - - - ETL\Frameworks - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files - - - UnitTest++\Header Files\Win32 - - - ETL\Messaging - - - ETL\Messaging - - - ETL\Messaging - - - ETL\Messaging - - - ETL\Messaging - - - ETL\Messaging - - - ETL\Messaging - - - ETL\Messaging - - - ETL\Messaging - - - ETL\Messaging - - - ETL\Messaging - - - ETL\Messaging - - - ETL\Messaging - - - ETL\Messaging - - - ETL\Messaging\Generators - - - ETL\Messaging\Generators - - - ETL\Containers - - - Tests\Initializer List - - - Tests\Error Handler\Log Errors - - - Tests\Error Handler\Exceptions - - - ETL\Private - - - ETL\Private - - - ETL\Private - - - ETL\Private - - - ETL\Messaging - - - ETL\Private - - - ETL\Private - - - ETL\Containers - - - ETL\Utilities - - - ETL\Private - - - ETL\Strings - - - ETL\Containers - - - Tests\Error Handler\Exceptions_And_Log_Errors - - - ETL\Utilities - - - ETL\Private - - - - - Tests\Strings - - - Tests\Strings - - - Tests\Strings - - - Tests\Strings - - - Tests\Strings - - - Tests\Strings - - - Tests\Strings - - - Tests\Strings - - - Tests\Strings - - - Tests\Strings - - - Tests\Strings - - - Tests\Strings - - - Tests\Strings - - - Tests\Strings - - - Tests\Strings - - - Tests\Strings - - - Tests\Strings - - - Tests\Strings - - - Tests\Strings - - - Tests\Strings - - - Tests\Strings - - - Tests\Strings - - - Tests\Strings - - - Tests\Strings - - - Tests\Strings - - - Tests\Messaging - - - Tests\Messaging - - - Tests\Messaging - - - Tests\Messaging - - - Tests\Messaging - - - Tests\Messaging - - - Tests\Messaging - - - Tests\Messaging - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\Hashes - - - Tests\Hashes - - - Tests\Hashes - - - Tests\Hashes - - - Tests\Hashes - - - Tests\Hashes - - - Tests\Hashes - - - Tests\Hashes - - - Tests\Hashes - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Queues - - - Tests\Queues - - - Tests\Queues - - - Tests\Queues - - - Tests\Queues - - - Tests\Queues - - - Tests\Queues - - - Tests\Queues - - - Tests\Queues - - - Tests\Queues - - - Tests\Queues - - - Tests\Queues - - - Tests\Queues - - - Tests\Queues - - - Tests\Callbacks & Delegates - - - Tests\Callbacks & Delegates - - - Tests\Callbacks & Delegates - - - Tests\Callbacks & Delegates - - - Tests\Callbacks & Delegates - - - Tests\Callbacks & Delegates - - - Tests\Callbacks & Delegates - - - Tests\Callback Timers - - - Tests\Callback Timers - - - Tests\Callback Timers - - - Tests\Strings - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Queues - - - Tests\State Machines - - - Tests\State Machines - - - Tests\State Machines - - - Tests\State Machines - - - Tests\State Machines - - - Tests\State Machines - - - Tests\State Machines - - - Tests\Algorithms - - - Tests\Algorithms - - - Tests\Algorithms - - - Tests\Algorithms - - - Tests\Algorithms - - - Tests\Algorithms - - - Tests\Algorithms - - - Tests\Algorithms - - - Tests\Algorithms - - - Tests\Algorithms - - - Tests\Algorithms - - - Tests\Algorithms - - - Tests\Algorithms - - - Tests\Algorithms - - - Tests\Algorithms - - - Tests\Algorithms - - - Tests\Algorithms - - - Tests\Binary - - - Tests\Binary - - - Tests\Binary - - - Tests\Binary - - - Tests\Binary - - - Tests\Hashes - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Test Support - - - Tests\Test Support - - - Tests\Strings - - - Tests\Containers - - - Tests\Algorithms - - - Tests\Types - - - Tests\Types - - - Tests\Types - - - Tests\Types - - - Tests\Types - - - Tests\Types - - - Tests\Types - - - Tests\Types - - - Tests\Types - - - Tests\Types - - - Tests\Types - - - Tests\Types - - - Tests\Algorithms - - - Tests\Types - - - Tests\Types - - - Tests\Patterns - - - Tests\Patterns - - - Tests\Queues - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\CRC - - - Tests\Maths - - - Tests\Maths - - - Tests\Maths - - - Tests\Maths - - - Tests\Maths - - - Tests\Maths - - - Tests\Maths - - - Tests\Maths - - - Tests\Maths - - - Tests\Maths - - - Tests\Maths - - - Tests\Maths - - - Tests\Maths - - - Tests\Algorithms - - - Tests\Memory & Iterators - - - Tests\Memory & Iterators - - - Tests\Memory & Iterators - - - Tests\Memory & Iterators - - - Tests\Memory & Iterators - - - Tests\Memory & Iterators - - - Tests\Maths - - - Tests\Maths - - - Tests\Errors - - - Tests\Errors - - - Tests\Patterns - - - Tests\Tasks - - - Tests\Misc - - - Tests\Misc - - - Tests\Misc - - - Tests\Misc - - - Tests\Misc - - - Tests\Misc - - - Tests\Misc - - - Tests\Misc - - - Tests\Misc - - - Tests - - - Tests - - - Tests - - - Tests - - - Tests\Memory & Iterators - - - Tests\Patterns - - - Tests\Binary - - - Tests\Misc - - - Tests\Callback Timers - - - Tests\Messaging - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Types - - - UnitTest++\Source Files - - - UnitTest++\Source Files - - - UnitTest++\Source Files - - - UnitTest++\Source Files - - - UnitTest++\Source Files - - - UnitTest++\Source Files - - - UnitTest++\Source Files - - - UnitTest++\Source Files - - - UnitTest++\Source Files - - - UnitTest++\Source Files - - - UnitTest++\Source Files - - - UnitTest++\Source Files - - - UnitTest++\Source Files - - - UnitTest++\Source Files - - - UnitTest++\Source Files - - - UnitTest++\Source Files - - - UnitTest++\Source Files - - - UnitTest++\Source Files - - - UnitTest++\Source Files - - - UnitTest++\Source Files - - - UnitTest++\Source Files\Win32 - - - Tests\Types - - - Tests\Patterns - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Binary - - - Tests\Containers - - - Tests\Atomic - - - Tests\Binary - - - Tests\Binary - - - Tests\Binary - - - Tests\Sanity Checks\Source - - - Tests\Containers - - - Tests\Containers - - - Tests\Containers - - - Tests\Initializer List - - - Tests\Error Handler\Log Errors - - - Tests\Error Handler\Exceptions - - - Tests\Messaging - - - Tests\Sanity Checks\Source - - - Tests\Misc - - - Tests\Binary - - - Tests\Sanity Checks\Source - - - Tests\Binary - - - Tests\Memory & Iterators - - - Tests\Sanity Checks\Source - - - Tests\Binary - - - Tests\Binary - - - Tests\Strings - - - Tests\Strings - - - Tests\Strings - - - Tests\Strings - - - Tests\Sanity Checks\Source - - - Tests\CRC - - - Tests\Misc - - - Tests\Containers - - - Tests\Containers - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Error Handler\Exceptions_And_Log_Errors - - - - - Resource Files - - - Resource Files\Images - - - Resource Files\Images - - - Resource Files - - - Resource Files - - - Resource Files - - - Resource Files\Generators - - - Resource Files\Generators - - - Resource Files\Generators - - - Resource Files\Generators - - - Resource Files\Generators - - - Resource Files\Generators - - - Resource Files\Generators - - - Resource Files\Generators - - - Resource Files\Generators - - - Resource Files\Generators - - - Resource Files\CI\CircleCI - - - Resource Files\CI\Appveyor - - - Resource Files\CI\Github - - - Resource Files\CI\Github - - - Resource Files\CI\Github - - - Tests\Scripts - - - Tests\Scripts - - - Resource Files - - - Resource Files\Git - - - Resource Files\Git - - - Resource Files\Git - - - Resource Files - - - Resource Files\Arduino - - - Resource Files\Arduino - - - Resource Files\CMake - - - Resource Files\CMake - - - Resource Files\CMake - - - Tests\Scripts - - - Tests\Scripts - - - Tests\Test Support - - - Tests\Scripts - - - Tests\Scripts - - - Tests\Scripts - - - - - Resource Files - - - Resource Files - - - Resource Files\CMake - - - Tests\Sanity Checks\C++03 - - - Tests\Sanity Checks\C++11 - - - Tests\Sanity Checks\C++14 - - - Tests\Sanity Checks\C++17 - - - Tests\Sanity Checks\Logs - - - Tests\Test Support - - - Resource Files - - - Tests\Initializer List - - - Tests\Error Handler\Log Errors - - - Tests\Error Handler\Exceptions - - - Tests\Error Handler\Exceptions_And_Log_Errors - - - - - Resource Files\Images - - - Resource Files\Images - - - Resource Files\Images - - - Resource Files\Images - - - Resource Files\Images - - - Resource Files\Images - - - - - Resource Files - - - \ No newline at end of file diff --git a/test/vs2019/etl_initialiser_list/etl_initialiser_list.vcxproj b/test/vs2019/etl_initialiser_list/etl_initialiser_list.vcxproj deleted file mode 100644 index f708ac4d..00000000 --- a/test/vs2019/etl_initialiser_list/etl_initialiser_list.vcxproj +++ /dev/null @@ -1,149 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 16.0 - Win32Proj - {0523db70-0955-4eb0-a042-04514987a602} - etlinitialiserlist - 10.0 - - - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - - - - - - - - - - - - - - - - - - - - - true - - - false - - - true - - - false - - - - Level3 - true - WIN32;_DEBUG;_CONSOLE;ETL_NO_STL;ETL_IN_UNIT_TEST_INITIALIZER_LIST;%(PreprocessorDefinitions) - true - ../../../include;%(AdditionalIncludeDirectories) - stdcpp17 - - - Console - true - - - - - Level3 - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - true - true - - - - - Level3 - true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - - - - - Level3 - true - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - true - true - - - - - - - - - \ No newline at end of file diff --git a/test/vs2019/etl_initialiser_list/etl_initialiser_list.vcxproj.filters b/test/vs2019/etl_initialiser_list/etl_initialiser_list.vcxproj.filters deleted file mode 100644 index e3f6e7ba..00000000 --- a/test/vs2019/etl_initialiser_list/etl_initialiser_list.vcxproj.filters +++ /dev/null @@ -1,22 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - \ No newline at end of file From 33f7bbc43de4b7917c275a530d274c8a950cad44 Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Sat, 13 Dec 2025 08:46:14 +0100 Subject: [PATCH 035/298] Various cleanup (#1238) * Fix typo for remainder in rounded_integral_division.h * Use etl::make_unsigned instead of std::make_unsigned * Fix divide_round_half_down and divide_round_half_odd --- include/etl/rounded_integral_division.h | 39 ++++++++++++++++--------- test/test_rounded_integral_division.cpp | 4 +-- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/include/etl/rounded_integral_division.h b/include/etl/rounded_integral_division.h index 417b3143..ea277db3 100644 --- a/include/etl/rounded_integral_division.h +++ b/include/etl/rounded_integral_division.h @@ -414,7 +414,7 @@ namespace etl const T quotient = numerator / denominator; // Work with magnitudes in unsigned form (avoids abs() overflow) - typedef typename std::make_unsigned::type utype; + typedef typename etl::make_unsigned::type utype; utype abs_remainder = remainder < 0 ? utype(0) - utype(remainder) : utype(remainder); utype abs_denominator = denominator < 0 ? utype(0) - utype(denominator) : utype(denominator); @@ -519,16 +519,18 @@ namespace etl T>::type divide_round_half_down(T numerator, T denominator) ETL_NOEXCEPT { - const T quotient = numerator / denominator; - const T remainder = numerator % denominator; - const T abs_denominator = etl::absolute(denominator); - const T abs_remainderainder = etl::absolute(remainder); + const T quotient = numerator / denominator; + const T remainder = numerator % denominator; + + typedef typename etl::make_unsigned::type utype; + const utype abs_denominator = etl::absolute_unsigned(denominator); + const utype abs_remainder = etl::absolute_unsigned(remainder); // Direction: +1 if result should be more positive, -1 if more negative - const T direction = ((numerator >= 0) == (denominator >= 0)) ? 1 : -1; + const T direction = private_rounded_integral_division::are_same_sign(numerator, denominator) ? 1 : -1; // Only round away from zero if remainder is strictly greater than half the divisor - return abs_remainderainder > (abs_denominator / 2) ? quotient + direction : quotient; + return abs_remainder > (abs_denominator / 2U) ? quotient + direction : quotient; } //*************************************************************************** @@ -730,17 +732,26 @@ namespace etl T>::type divide_round_half_odd(T numerator, T denominator) ETL_NOEXCEPT { - const T quotient = numerator / denominator; - const T remainder = numerator % denominator; - const T abs_denominator = etl::absolute(denominator); - const T abs_remainderainder = etl::absolute(remainder); - const T direction = ((numerator >= 0) == (denominator >= 0)) ? 1 : -1; + const T quotient = numerator / denominator; + const T remainder = numerator % denominator; - if ((abs_remainderainder * 2) < abs_denominator) + typedef typename etl::make_unsigned::type utype; + const utype abs_denominator = etl::absolute_unsigned(denominator); + const utype abs_remainder = etl::absolute_unsigned(remainder); + const utype half = abs_denominator / 2U; + const T direction = private_rounded_integral_division::are_same_sign(numerator, denominator) ? 1 : -1; + + // Odd divisor => no exact-half case; 'half' is floor(abs_denominator/2). + if ((abs_denominator & 1U) != 0U) + { + return (abs_remainder > half) ? quotient + direction : quotient; + } + + if (abs_remainder < half) { return quotient; } - else if ((abs_remainderainder * 2) > abs_denominator) + else if (abs_remainder > half) { return quotient + direction; } diff --git a/test/test_rounded_integral_division.cpp b/test/test_rounded_integral_division.cpp index 608d39df..c03dc8e5 100644 --- a/test/test_rounded_integral_division.cpp +++ b/test/test_rounded_integral_division.cpp @@ -624,7 +624,7 @@ namespace CHECK_EQUAL(std::numeric_limits::max(), etl::divide_round_half_down(std::numeric_limits::max(), int32_t(1))); CHECK_EQUAL(int32_t(0), etl::divide_round_half_down(int32_t(1), std::numeric_limits::max())); CHECK_EQUAL(std::numeric_limits::min(), etl::divide_round_half_down(std::numeric_limits::min(), int32_t(1))); - CHECK_EQUAL(int32_t(-1), etl::divide_round_half_down(int32_t(1), std::numeric_limits::min())); + CHECK_EQUAL(int32_t(0), etl::divide_round_half_down(int32_t(1), std::numeric_limits::min())); } //************************************************************************* @@ -840,7 +840,7 @@ namespace CHECK_EQUAL(std::numeric_limits::max(), etl::divide_round_half_odd(std::numeric_limits::max(), int32_t(1))); CHECK_EQUAL(int32_t(0), etl::divide_round_half_odd(int32_t(1), std::numeric_limits::max())); CHECK_EQUAL(std::numeric_limits::min(), etl::divide_round_half_odd(std::numeric_limits::min(), int32_t(1))); - CHECK_EQUAL(int32_t(-1), etl::divide_round_half_odd(int32_t(1), std::numeric_limits::min())); + CHECK_EQUAL(int32_t(0), etl::divide_round_half_odd(int32_t(1), std::numeric_limits::min())); } //************************************************************************* From 636ed523bd7c6880366ee9498e4a61df1a724af6 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 20 Dec 2025 12:51:01 +0000 Subject: [PATCH 036/298] Enhanced test and syntax check scripts to add non-scrolling command line header --- .gitignore | 1 + test/run-syntax-checks.sh | 40 +++++++++++++++++++++++++++++ test/run-tests.sh | 54 ++++++++++++++++++++++++++++++++++----- 3 files changed, 89 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 068e7602..ced27dae 100644 --- a/.gitignore +++ b/.gitignore @@ -411,3 +411,4 @@ examples/UniquePtrWithPool/UniquePtrWithPool test/vs2022/Debug Clang C++20 - Optimised -O2 include/etl/header_file_list.txt temp +test/syntax_check/build-make diff --git a/test/run-syntax-checks.sh b/test/run-syntax-checks.sh index 18a65523..9991a54e 100644 --- a/test/run-syntax-checks.sh +++ b/test/run-syntax-checks.sh @@ -5,11 +5,32 @@ echo -e configuration_name="Configuration Name Not Set" +# Define colours FailColour='\033[38;2;255;128;128m' PassColour='\033[38;2;128;255;128m' TitleColour='\033[38;2;107;210;255m' HelpColour='\033[38;2;250;180;250m' NoColour='\033[0m' +CommandColour='\033[38;2;255;255;128m' + +# Save cursor position +tput sc + +# Clear screen +tput clear + +# Write fixed header on line 1 +tput cup 0 0 +echo $CommandColour "run-syntax-checks.sh" $1 $2 $3 $4 $5 $NoColour + +# Define scrolling region from line 2 to bottom +tput csr 2 $(($(tput lines) - 1)) + +# Restore cursor position +tput rc + +# Move cursor to start of scrollable area +tput cup 1 0 ParseGitBranch() { @@ -81,6 +102,25 @@ ChecksCompleted() echo "$NoColour" } +cleanup() +{ + # Reset scroll region to full screen + tput csr 0 $(($(tput lines) - 1)) + # Move cursor to a safe line (bottom of terminal) + tput cup $(($(tput lines) - 1)) 0 +} + +ctrl_c() +{ + # Reset scroll region to full screen + tput csr 0 $(($(tput lines) - 1)) + # Move cursor to a safe line (bottom of terminal) + tput cup $(($(tput lines) - 1)) 0 +} + +trap ctrl_c INT +trap cleanup EXIT + cd syntax_check || exit 1 echo "" > log.txt diff --git a/test/run-tests.sh b/test/run-tests.sh index e914114b..8f756794 100755 --- a/test/run-tests.sh +++ b/test/run-tests.sh @@ -4,16 +4,37 @@ shopt -s xpg_echo clear -export ASAN_OPTIONS=symbol_line=1 -export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-14/bin//llvm-symbolizer - -configuration_name="Configuration Name Not Set" - +# Define colours FailColour='\033[38;2;255;128;128m' PassColour='\033[38;2;128;255;128m' TitleColour='\033[38;2;107;210;255m' HelpColour='\033[38;2;250;180;250m' NoColour='\033[0m' +CommandColour='\033[38;2;255;255;128m' + +# Save cursor position +tput sc + +# Clear screen +tput clear + +# Write fixed header on line 1 +tput cup 0 0 +echo $CommandColour "run-tests.sh" $1 $2 $3 $4 $5 $NoColour + +# Define scrolling region from line 2 to bottom +tput csr 2 $(($(tput lines) - 1)) + +# Restore cursor position +tput rc + +# Move cursor to start of scrollable area +tput cup 1 0 + +export ASAN_OPTIONS=symbol_line=1 +export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-14/bin//llvm-symbolizer + +configuration_name="Configuration Name Not Set" ParseGitBranch() { @@ -179,10 +200,31 @@ fi etl_version_raw=$(cat ../version.txt) etl_version=$(echo $etl_version_raw | sed -e 's/\r//g') # Remove trailing \r +cleanup() +{ + # Reset scroll region to full screen + tput csr 0 $(($(tput lines) - 1)) + # Move cursor to a safe line (bottom of terminal) + tput cup $(($(tput lines) - 1)) 0 +} + +ctrl_c() +{ + # Reset scroll region to full screen + tput csr 0 $(($(tput lines) - 1)) + # Move cursor to a safe line (bottom of terminal) + tput cup $(($(tput lines) - 1)) 0 +} + +trap ctrl_c INT +trap cleanup EXIT + +cd syntax_check || exit 1 +echo "" > log.txt + #****************************************************************************** # Get the compiler versions #****************************************************************************** - while read i ; do CC=`echo $i | cut -d, -f1 | sed -e 's/ *$//'` MSG=`echo $i | cut -d, -f2 | sed -e 's/ *$//'` From 3c36e696f561c68586d1f4799b879cafddf55b43 Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Sat, 13 Dec 2025 08:34:24 +0100 Subject: [PATCH 037/298] Bugfixes for compile errors in optimized tests (#1235) * Fix optimized tests by suppressing warning from STL * Fix uninitialized buffer in hash for month_weekday * Fix overlapping memcpy with memmove * Fix random out of bounds index in __builtin_memmove Suppressing compiler warning * Fix array bounds warnings from static casts in message_router In compiled code, casting to wrong message types is generated, even though the code paths are supposed to be never taken due to runtime msg id checks. Therefore, the warnings can be suppressed. * Fix syntax errors in base64 decoder tests * Fix test failure in test_rounded_integral_division.cpp when optimized When building tests optimized, test_round_to_half_even_signed_limits fails due to the fact that etl::absolute(std::numeric_limits::min()) < 0 --- include/etl/basic_string.h | 2 +- .../etl/generators/message_router_generator.h | 18 ++++ include/etl/memory.h | 4 + include/etl/message_router.h | 102 ++++++++++++++++++ include/etl/private/chrono/month_weekday.h | 6 +- .../diagnostic_stringop_overflow_push.h | 43 ++++++++ include/etl/rounded_integral_division.h | 34 ++++-- test/test_base64_RFC2152_decoder.cpp | 26 ++++- test/test_base64_RFC3501_decoder.cpp | 26 ++++- ...64_RFC4648_URL_decoder_with_no_padding.cpp | 26 ++++- ...ase64_RFC4648_URL_decoder_with_padding.cpp | 26 ++++- ...base64_RFC4648_decoder_with_no_padding.cpp | 26 ++++- ...st_base64_RFC4648_decoder_with_padding.cpp | 26 ++++- test/test_multi_span.cpp | 4 + test/test_rounded_integral_division.cpp | 3 +- test/test_string_char.cpp | 2 + test/unit_test_framework.h | 2 + 17 files changed, 355 insertions(+), 21 deletions(-) create mode 100644 include/etl/private/diagnostic_stringop_overflow_push.h diff --git a/include/etl/basic_string.h b/include/etl/basic_string.h index d98adf1b..7232a6d0 100644 --- a/include/etl/basic_string.h +++ b/include/etl/basic_string.h @@ -2601,7 +2601,7 @@ namespace etl etl::mem_copy(s, insert_length, &p_buffer[remove_index]); // Move tail left. - etl::mem_copy(&p_buffer[tail_index], tail_length, &p_buffer[remove_index + insert_length]); + etl::mem_move(&p_buffer[tail_index], tail_length, &p_buffer[remove_index + insert_length]); } current_size = remove_index + insert_length + tail_length; diff --git a/include/etl/generators/message_router_generator.h b/include/etl/generators/message_router_generator.h index a1c38d78..868a51ab 100644 --- a/include/etl/generators/message_router_generator.h +++ b/include/etl/generators/message_router_generator.h @@ -465,7 +465,9 @@ namespace etl } else { +#include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive_unknown(msg); +#include "etl/private/diagnostic_pop.h" } } } @@ -473,6 +475,7 @@ namespace etl template ::value, int>::type = 0> void receive(const TMessage& msg) { +#include "etl/private/diagnostic_array_bounds_push.h" if constexpr (etl::is_one_of::value) { static_cast(this)->on_receive(msg); @@ -488,6 +491,7 @@ namespace etl static_cast(this)->on_receive_unknown(msg); } } +#include "etl/private/diagnostic_pop.h" } //********************************************** @@ -524,7 +528,9 @@ namespace etl { if (TMessage::ID == msg.get_message_id()) { +#include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive(static_cast(msg)); +#include "etl/private/diagnostic_pop.h" return true; } else @@ -618,6 +624,7 @@ namespace etl cog.outl(" {") cog.outl(" const etl::message_id_t id = msg.get_message_id();") cog.outl("") + cog.outl("#include \"etl/private/diagnostic_array_bounds_push.h\"") cog.outl(" switch (id)") cog.outl(" {") for n in range(1, int(Handlers) + 1): @@ -637,6 +644,7 @@ namespace etl cog.outl(" break;") cog.outl(" }") cog.outl(" }") + cog.outl("#include \"etl/private/diagnostic_pop.h\"") cog.outl(" }") cog.outl("") cog.outl(" template ") @@ -646,7 +654,9 @@ namespace etl cog.outl("T%s>::value, void>::type" % int(Handlers)) cog.outl(" receive(const TMessage& msg)") cog.outl(" {") + cog.outl("#include \"etl/private/diagnostic_array_bounds_push.h\"") cog.outl(" static_cast(this)->on_receive(msg);") + cog.outl("#include \"etl/private/diagnostic_pop.h\"") cog.outl(" }") cog.outl("") cog.outl(" template ") @@ -662,7 +672,9 @@ namespace etl cog.outl(" }") cog.outl(" else") cog.outl(" {") + cog.outl("#include \"etl/private/diagnostic_array_bounds_push.h\"") cog.outl(" static_cast(this)->on_receive_unknown(msg);") + cog.outl("#include \"etl/private/diagnostic_pop.h\"") cog.outl(" }") cog.outl(" }") cog.outl("") @@ -786,6 +798,7 @@ namespace etl cog.outl(" {") cog.outl(" const size_t id = msg.get_message_id();") cog.outl("") + cog.outl("#include \"etl/private/diagnostic_array_bounds_push.h\"") cog.outl(" switch (id)") cog.outl(" {") for t in range(1, n + 1): @@ -805,6 +818,7 @@ namespace etl cog.outl(" break;") cog.outl(" }") cog.outl(" }") + cog.outl("#include \"etl/private/diagnostic_pop.h\"") cog.outl(" }") cog.outl("") cog.outl(" template ") @@ -814,7 +828,9 @@ namespace etl cog.outl("T%s>::value, void>::type" % n) cog.outl(" receive(const TMessage& msg)") cog.outl(" {") + cog.outl("#include \"etl/private/diagnostic_array_bounds_push.h\"") cog.outl(" static_cast(this)->on_receive(msg);") + cog.outl("#include \"etl/private/diagnostic_pop.h\"") cog.outl(" }") cog.outl("") cog.outl(" template ") @@ -830,7 +846,9 @@ namespace etl cog.outl(" }") cog.outl(" else") cog.outl(" {") + cog.outl("#include \"etl/private/diagnostic_array_bounds_push.h\"") cog.outl(" static_cast(this)->on_receive_unknown(msg);") + cog.outl("#include \"etl/private/diagnostic_pop.h\"") cog.outl(" }") cog.outl(" }") cog.outl("") diff --git a/include/etl/memory.h b/include/etl/memory.h index ffe7b7ef..57b89879 100644 --- a/include/etl/memory.h +++ b/include/etl/memory.h @@ -2366,9 +2366,13 @@ namespace etl ETL_STATIC_ASSERT(etl::is_trivially_copyable::value, "Cannot mem_move a non trivially copyable type"); #if ETL_USING_BUILTIN_MEMMOVE +#include "etl/private/diagnostic_array_bounds_push.h" +#include "etl/private/diagnostic_stringop_overread_push.h" __builtin_memmove(reinterpret_cast(db), reinterpret_cast(sb), sizeof(T) * n); +#include "etl/private/diagnostic_pop.h" +#include "etl/private/diagnostic_pop.h" #else ::memmove(reinterpret_cast(db), reinterpret_cast(sb), diff --git a/include/etl/message_router.h b/include/etl/message_router.h index d3c1053f..cc6ea40c 100644 --- a/include/etl/message_router.h +++ b/include/etl/message_router.h @@ -453,7 +453,9 @@ namespace etl } else { +#include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive_unknown(msg); +#include "etl/private/diagnostic_pop.h" } } } @@ -461,6 +463,7 @@ namespace etl template ::value, int>::type = 0> void receive(const TMessage& msg) { +#include "etl/private/diagnostic_array_bounds_push.h" if constexpr (etl::is_one_of::value) { static_cast(this)->on_receive(msg); @@ -476,6 +479,7 @@ namespace etl static_cast(this)->on_receive_unknown(msg); } } +#include "etl/private/diagnostic_pop.h" } //********************************************** @@ -512,7 +516,9 @@ namespace etl { if (TMessage::ID == msg.get_message_id()) { +#include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive(static_cast(msg)); +#include "etl/private/diagnostic_pop.h" return true; } else @@ -593,6 +599,7 @@ namespace etl { const etl::message_id_t id = msg.get_message_id(); + #include "etl/private/diagnostic_array_bounds_push.h" switch (id) { case T1::ID: static_cast(this)->on_receive(static_cast(msg)); break; @@ -624,13 +631,16 @@ namespace etl break; } } + #include "etl/private/diagnostic_pop.h" } template typename etl::enable_if::value && etl::is_one_of::value, void>::type receive(const TMessage& msg) { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive(msg); + #include "etl/private/diagnostic_pop.h" } template @@ -643,7 +653,9 @@ namespace etl } else { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive_unknown(msg); + #include "etl/private/diagnostic_pop.h" } } @@ -738,6 +750,7 @@ namespace etl { const size_t id = msg.get_message_id(); + #include "etl/private/diagnostic_array_bounds_push.h" switch (id) { case T1::ID: static_cast(this)->on_receive(static_cast(msg)); break; @@ -768,13 +781,16 @@ namespace etl break; } } + #include "etl/private/diagnostic_pop.h" } template typename etl::enable_if::value && etl::is_one_of::value, void>::type receive(const TMessage& msg) { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive(msg); + #include "etl/private/diagnostic_pop.h" } template @@ -787,7 +803,9 @@ namespace etl } else { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive_unknown(msg); + #include "etl/private/diagnostic_pop.h" } } @@ -883,6 +901,7 @@ namespace etl { const size_t id = msg.get_message_id(); + #include "etl/private/diagnostic_array_bounds_push.h" switch (id) { case T1::ID: static_cast(this)->on_receive(static_cast(msg)); break; @@ -912,13 +931,16 @@ namespace etl break; } } + #include "etl/private/diagnostic_pop.h" } template typename etl::enable_if::value && etl::is_one_of::value, void>::type receive(const TMessage& msg) { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive(msg); + #include "etl/private/diagnostic_pop.h" } template @@ -931,7 +953,9 @@ namespace etl } else { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive_unknown(msg); + #include "etl/private/diagnostic_pop.h" } } @@ -1027,6 +1051,7 @@ namespace etl { const size_t id = msg.get_message_id(); + #include "etl/private/diagnostic_array_bounds_push.h" switch (id) { case T1::ID: static_cast(this)->on_receive(static_cast(msg)); break; @@ -1055,13 +1080,16 @@ namespace etl break; } } + #include "etl/private/diagnostic_pop.h" } template typename etl::enable_if::value && etl::is_one_of::value, void>::type receive(const TMessage& msg) { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive(msg); + #include "etl/private/diagnostic_pop.h" } template @@ -1074,7 +1102,9 @@ namespace etl } else { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive_unknown(msg); + #include "etl/private/diagnostic_pop.h" } } @@ -1169,6 +1199,7 @@ namespace etl { const size_t id = msg.get_message_id(); + #include "etl/private/diagnostic_array_bounds_push.h" switch (id) { case T1::ID: static_cast(this)->on_receive(static_cast(msg)); break; @@ -1196,13 +1227,16 @@ namespace etl break; } } + #include "etl/private/diagnostic_pop.h" } template typename etl::enable_if::value && etl::is_one_of::value, void>::type receive(const TMessage& msg) { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive(msg); + #include "etl/private/diagnostic_pop.h" } template @@ -1215,7 +1249,9 @@ namespace etl } else { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive_unknown(msg); + #include "etl/private/diagnostic_pop.h" } } @@ -1310,6 +1346,7 @@ namespace etl { const size_t id = msg.get_message_id(); + #include "etl/private/diagnostic_array_bounds_push.h" switch (id) { case T1::ID: static_cast(this)->on_receive(static_cast(msg)); break; @@ -1336,13 +1373,16 @@ namespace etl break; } } + #include "etl/private/diagnostic_pop.h" } template typename etl::enable_if::value && etl::is_one_of::value, void>::type receive(const TMessage& msg) { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive(msg); + #include "etl/private/diagnostic_pop.h" } template @@ -1355,7 +1395,9 @@ namespace etl } else { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive_unknown(msg); + #include "etl/private/diagnostic_pop.h" } } @@ -1450,6 +1492,7 @@ namespace etl { const size_t id = msg.get_message_id(); + #include "etl/private/diagnostic_array_bounds_push.h" switch (id) { case T1::ID: static_cast(this)->on_receive(static_cast(msg)); break; @@ -1475,13 +1518,16 @@ namespace etl break; } } + #include "etl/private/diagnostic_pop.h" } template typename etl::enable_if::value && etl::is_one_of::value, void>::type receive(const TMessage& msg) { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive(msg); + #include "etl/private/diagnostic_pop.h" } template @@ -1494,7 +1540,9 @@ namespace etl } else { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive_unknown(msg); + #include "etl/private/diagnostic_pop.h" } } @@ -1589,6 +1637,7 @@ namespace etl { const size_t id = msg.get_message_id(); + #include "etl/private/diagnostic_array_bounds_push.h" switch (id) { case T1::ID: static_cast(this)->on_receive(static_cast(msg)); break; @@ -1613,13 +1662,16 @@ namespace etl break; } } + #include "etl/private/diagnostic_pop.h" } template typename etl::enable_if::value && etl::is_one_of::value, void>::type receive(const TMessage& msg) { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive(msg); + #include "etl/private/diagnostic_pop.h" } template @@ -1632,7 +1684,9 @@ namespace etl } else { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive_unknown(msg); + #include "etl/private/diagnostic_pop.h" } } @@ -1726,6 +1780,7 @@ namespace etl { const size_t id = msg.get_message_id(); + #include "etl/private/diagnostic_array_bounds_push.h" switch (id) { case T1::ID: static_cast(this)->on_receive(static_cast(msg)); break; @@ -1749,13 +1804,16 @@ namespace etl break; } } + #include "etl/private/diagnostic_pop.h" } template typename etl::enable_if::value && etl::is_one_of::value, void>::type receive(const TMessage& msg) { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive(msg); + #include "etl/private/diagnostic_pop.h" } template @@ -1768,7 +1826,9 @@ namespace etl } else { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive_unknown(msg); + #include "etl/private/diagnostic_pop.h" } } @@ -1862,6 +1922,7 @@ namespace etl { const size_t id = msg.get_message_id(); + #include "etl/private/diagnostic_array_bounds_push.h" switch (id) { case T1::ID: static_cast(this)->on_receive(static_cast(msg)); break; @@ -1884,13 +1945,16 @@ namespace etl break; } } + #include "etl/private/diagnostic_pop.h" } template typename etl::enable_if::value && etl::is_one_of::value, void>::type receive(const TMessage& msg) { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive(msg); + #include "etl/private/diagnostic_pop.h" } template @@ -1903,7 +1967,9 @@ namespace etl } else { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive_unknown(msg); + #include "etl/private/diagnostic_pop.h" } } @@ -1996,6 +2062,7 @@ namespace etl { const size_t id = msg.get_message_id(); + #include "etl/private/diagnostic_array_bounds_push.h" switch (id) { case T1::ID: static_cast(this)->on_receive(static_cast(msg)); break; @@ -2017,13 +2084,16 @@ namespace etl break; } } + #include "etl/private/diagnostic_pop.h" } template typename etl::enable_if::value && etl::is_one_of::value, void>::type receive(const TMessage& msg) { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive(msg); + #include "etl/private/diagnostic_pop.h" } template @@ -2036,7 +2106,9 @@ namespace etl } else { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive_unknown(msg); + #include "etl/private/diagnostic_pop.h" } } @@ -2129,6 +2201,7 @@ namespace etl { const size_t id = msg.get_message_id(); + #include "etl/private/diagnostic_array_bounds_push.h" switch (id) { case T1::ID: static_cast(this)->on_receive(static_cast(msg)); break; @@ -2149,13 +2222,16 @@ namespace etl break; } } + #include "etl/private/diagnostic_pop.h" } template typename etl::enable_if::value && etl::is_one_of::value, void>::type receive(const TMessage& msg) { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive(msg); + #include "etl/private/diagnostic_pop.h" } template @@ -2168,7 +2244,9 @@ namespace etl } else { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive_unknown(msg); + #include "etl/private/diagnostic_pop.h" } } @@ -2260,6 +2338,7 @@ namespace etl { const size_t id = msg.get_message_id(); + #include "etl/private/diagnostic_array_bounds_push.h" switch (id) { case T1::ID: static_cast(this)->on_receive(static_cast(msg)); break; @@ -2279,13 +2358,16 @@ namespace etl break; } } + #include "etl/private/diagnostic_pop.h" } template typename etl::enable_if::value && etl::is_one_of::value, void>::type receive(const TMessage& msg) { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive(msg); + #include "etl/private/diagnostic_pop.h" } template @@ -2298,7 +2380,9 @@ namespace etl } else { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive_unknown(msg); + #include "etl/private/diagnostic_pop.h" } } @@ -2390,6 +2474,7 @@ namespace etl { const size_t id = msg.get_message_id(); + #include "etl/private/diagnostic_array_bounds_push.h" switch (id) { case T1::ID: static_cast(this)->on_receive(static_cast(msg)); break; @@ -2408,13 +2493,16 @@ namespace etl break; } } + #include "etl/private/diagnostic_pop.h" } template typename etl::enable_if::value && etl::is_one_of::value, void>::type receive(const TMessage& msg) { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive(msg); + #include "etl/private/diagnostic_pop.h" } template @@ -2427,7 +2515,9 @@ namespace etl } else { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive_unknown(msg); + #include "etl/private/diagnostic_pop.h" } } @@ -2519,6 +2609,7 @@ namespace etl { const size_t id = msg.get_message_id(); + #include "etl/private/diagnostic_array_bounds_push.h" switch (id) { case T1::ID: static_cast(this)->on_receive(static_cast(msg)); break; @@ -2536,13 +2627,16 @@ namespace etl break; } } + #include "etl/private/diagnostic_pop.h" } template typename etl::enable_if::value && etl::is_one_of::value, void>::type receive(const TMessage& msg) { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive(msg); + #include "etl/private/diagnostic_pop.h" } template @@ -2555,7 +2649,9 @@ namespace etl } else { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive_unknown(msg); + #include "etl/private/diagnostic_pop.h" } } @@ -2647,6 +2743,7 @@ namespace etl { const size_t id = msg.get_message_id(); + #include "etl/private/diagnostic_array_bounds_push.h" switch (id) { case T1::ID: static_cast(this)->on_receive(static_cast(msg)); break; @@ -2663,13 +2760,16 @@ namespace etl break; } } + #include "etl/private/diagnostic_pop.h" } template typename etl::enable_if::value && etl::is_one_of::value, void>::type receive(const TMessage& msg) { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive(msg); + #include "etl/private/diagnostic_pop.h" } template @@ -2682,7 +2782,9 @@ namespace etl } else { + #include "etl/private/diagnostic_array_bounds_push.h" static_cast(this)->on_receive_unknown(msg); + #include "etl/private/diagnostic_pop.h" } } diff --git a/include/etl/private/chrono/month_weekday.h b/include/etl/private/chrono/month_weekday.h index 9e05692d..89ac6566 100644 --- a/include/etl/private/chrono/month_weekday.h +++ b/include/etl/private/chrono/month_weekday.h @@ -186,9 +186,9 @@ namespace etl uint8_t buffer[sizeof(a) + sizeof(b) + sizeof(c)]; - memcpy(buffer, &a, sizeof(a)); - memcpy(buffer + sizeof(a), &b, sizeof(b)); - memcpy(buffer + sizeof(b), &b, sizeof(c)); + memcpy(buffer, &a, sizeof(a)); + memcpy(buffer + sizeof(a), &b, sizeof(b)); + memcpy(buffer + sizeof(a) + sizeof(b), &c, sizeof(c)); return etl::private_hash::generic_hash(buffer, buffer + sizeof(a) + sizeof(b) + sizeof(c)); } diff --git a/include/etl/private/diagnostic_stringop_overflow_push.h b/include/etl/private/diagnostic_stringop_overflow_push.h new file mode 100644 index 00000000..ee258eef --- /dev/null +++ b/include/etl/private/diagnostic_stringop_overflow_push.h @@ -0,0 +1,43 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +/* + * The header include guard has been intentionally omitted. + * This file is intended to evaluated multiple times by design. + */ + +#if defined(__GNUC__) && (__GNUC__ >= 11) && !defined(__clang__) && !defined(__llvm__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif + +#if defined(__clang__) || defined(__llvm__) + #pragma clang diagnostic push +#endif diff --git a/include/etl/rounded_integral_division.h b/include/etl/rounded_integral_division.h index ea277db3..1aed30a9 100644 --- a/include/etl/rounded_integral_division.h +++ b/include/etl/rounded_integral_division.h @@ -617,22 +617,36 @@ namespace etl { const T quotient = numerator / denominator; const T remainder = numerator % denominator; - const T abs_denominator = etl::absolute(denominator); - const T abs_remainderainder = etl::absolute(remainder); const T direction = ((numerator >= 0) == (denominator >= 0)) ? 1 : -1; - if ((abs_remainderainder * 2) < abs_denominator) + // Work with magnitudes in unsigned form (avoids abs() overflow for T::min()). + typedef typename std::make_unsigned::type utype; + const utype abs_denominator = (denominator < 0) ? (utype(0) - utype(denominator)) : utype(denominator); + const utype abs_remainder = (remainder < 0) ? (utype(0) - utype(remainder)) : utype(remainder); + const utype half_denominator = abs_denominator / 2U; + + // Compare without `* 2` to avoid unsigned overflow. + if ((abs_denominator & 1U) == 0U) { - return quotient; - } - else if ((abs_remainderainder * 2) > abs_denominator) - { - return quotient + direction; + // Even denominator: can be exactly half. + if (abs_remainder < half_denominator) + { + return quotient; + } + else if (abs_remainder > half_denominator) + { + return quotient + direction; + } + else + { + // Exactly halfway, round to even + return (quotient & 1) == 0 ? quotient : quotient + direction; + } } else { - // Exactly halfway, round to even - return (quotient & 1) == 0 ? quotient : quotient + direction; + // Odd denominator: no exact half case. + return (abs_remainder <= half_denominator) ? quotient : (quotient + direction); } } diff --git a/test/test_base64_RFC2152_decoder.cpp b/test/test_base64_RFC2152_decoder.cpp index 66642b83..af6e1a87 100644 --- a/test/test_base64_RFC2152_decoder.cpp +++ b/test/test_base64_RFC2152_decoder.cpp @@ -386,8 +386,10 @@ namespace b64.decode_final(encoded[i].data(), encoded[i].size()); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -408,8 +410,10 @@ namespace b64.decode_final(encoded[i].data(), encoded[i].size()); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -447,8 +451,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -486,8 +492,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -508,8 +516,10 @@ namespace b64.decode_final(encoded[i].begin(), encoded[i].end()); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -530,8 +540,10 @@ namespace b64.decode_final(encoded[i].begin(), encoded[i].end()); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -569,8 +581,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -608,8 +622,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -640,8 +656,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -672,8 +690,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -708,8 +728,10 @@ namespace b64.flush(); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(b64.begin(), b64.end()); +#include "etl/private/diagnostic_pop.h" CHECK_EQUAL(expected.size(), actual.size()); CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); @@ -739,8 +761,10 @@ namespace constexpr auto output{ GetConstexprBase64(input) }; +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; std::vector actual(output.begin(), output.end()); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); CHECK_TRUE(codec::safe_output_buffer_size(14) >= output.size()); @@ -755,7 +779,7 @@ namespace #if ETL_USING_EXCEPTIONS CHECK_THROW((b64.decode(encoded[10].data(), encoded[10].size())), etl::base64_overflow); #else - CHECK_FALSE(b64.decode(encoded[10].data(), encoded[10].size()); + CHECK_FALSE(b64.decode(encoded[10].data(), encoded[10].size())); CHECK_TRUE(b64.error()); #endif } diff --git a/test/test_base64_RFC3501_decoder.cpp b/test/test_base64_RFC3501_decoder.cpp index 1c5e14e6..0e750518 100644 --- a/test/test_base64_RFC3501_decoder.cpp +++ b/test/test_base64_RFC3501_decoder.cpp @@ -383,8 +383,10 @@ namespace b64.decode_final(encoded[i].data(), encoded[i].size()); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -405,8 +407,10 @@ namespace b64.decode_final(encoded[i].data(), encoded[i].size()); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -444,8 +448,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -483,8 +489,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -505,8 +513,10 @@ namespace b64.decode_final(encoded[i].begin(), encoded[i].end()); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -527,8 +537,10 @@ namespace b64.decode_final(encoded[i].begin(), encoded[i].end()); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -566,8 +578,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -605,8 +619,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -637,8 +653,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -669,8 +687,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -705,8 +725,10 @@ namespace b64.flush(); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(b64.begin(), b64.end()); +#include "etl/private/diagnostic_pop.h" CHECK_EQUAL(expected.size(), actual.size()); CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); @@ -736,8 +758,10 @@ namespace constexpr auto output{ GetConstexprBase64(input) }; +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; std::vector actual(output.begin(), output.end()); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); CHECK_TRUE(codec::safe_output_buffer_size(14) >= output.size()); @@ -752,7 +776,7 @@ namespace #if ETL_USING_EXCEPTIONS CHECK_THROW((b64.decode(encoded[10].data(), encoded[10].size())), etl::base64_overflow); #else - CHECK_FALSE(b64.decode(encoded[10].data(), encoded[10].size()); + CHECK_FALSE(b64.decode(encoded[10].data(), encoded[10].size())); CHECK_TRUE(b64.error()); #endif } diff --git a/test/test_base64_RFC4648_URL_decoder_with_no_padding.cpp b/test/test_base64_RFC4648_URL_decoder_with_no_padding.cpp index 216cde1b..b2d3c01b 100644 --- a/test/test_base64_RFC4648_URL_decoder_with_no_padding.cpp +++ b/test/test_base64_RFC4648_URL_decoder_with_no_padding.cpp @@ -383,8 +383,10 @@ namespace b64.decode_final(encoded[i].data(), encoded[i].size()); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -405,8 +407,10 @@ namespace b64.decode_final(encoded[i].data(), encoded[i].size()); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -444,8 +448,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -483,8 +489,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -505,8 +513,10 @@ namespace b64.decode_final(encoded[i].begin(), encoded[i].end()); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -527,8 +537,10 @@ namespace b64.decode_final(encoded[i].begin(), encoded[i].end()); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -566,8 +578,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -605,8 +619,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -637,8 +653,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -669,8 +687,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -705,8 +725,10 @@ namespace b64.flush(); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(b64.begin(), b64.end()); +#include "etl/private/diagnostic_pop.h" CHECK_EQUAL(expected.size(), actual.size()); CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); @@ -736,8 +758,10 @@ namespace constexpr auto output{ GetConstexprBase64(input) }; +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; std::vector actual(output.begin(), output.end()); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); CHECK_TRUE(codec::safe_output_buffer_size(14) >= output.size()); @@ -752,7 +776,7 @@ namespace #if ETL_USING_EXCEPTIONS CHECK_THROW((b64.decode(encoded[10].data(), encoded[10].size())), etl::base64_overflow); #else - CHECK_FALSE(b64.decode(encoded[10].data(), encoded[10].size()); + CHECK_FALSE(b64.decode(encoded[10].data(), encoded[10].size())); CHECK_TRUE(b64.error()); #endif } diff --git a/test/test_base64_RFC4648_URL_decoder_with_padding.cpp b/test/test_base64_RFC4648_URL_decoder_with_padding.cpp index 990b6613..77c990a3 100644 --- a/test/test_base64_RFC4648_URL_decoder_with_padding.cpp +++ b/test/test_base64_RFC4648_URL_decoder_with_padding.cpp @@ -383,8 +383,10 @@ namespace b64.decode_final(encoded[i].data(), encoded[i].size()); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -405,8 +407,10 @@ namespace b64.decode_final(encoded[i].data(), encoded[i].size()); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -444,8 +448,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -483,8 +489,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -505,8 +513,10 @@ namespace b64.decode_final(encoded[i].begin(), encoded[i].end()); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -527,8 +537,10 @@ namespace b64.decode_final(encoded[i].begin(), encoded[i].end()); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -566,8 +578,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -605,8 +619,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -637,8 +653,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -669,8 +687,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -705,8 +725,10 @@ namespace b64.flush(); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(b64.begin(), b64.end()); +#include "etl/private/diagnostic_pop.h" CHECK_EQUAL(expected.size(), actual.size()); CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); @@ -736,8 +758,10 @@ namespace constexpr auto output{ GetConstexprBase64(input) }; +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; std::vector actual(output.begin(), output.end()); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); CHECK_TRUE(codec::safe_output_buffer_size(14) >= output.size()); @@ -752,7 +776,7 @@ namespace #if ETL_USING_EXCEPTIONS CHECK_THROW((b64.decode(encoded[10].data(), encoded[10].size())), etl::base64_overflow); #else - CHECK_FALSE(b64.decode(encoded[10].data(), encoded[10].size()); + CHECK_FALSE(b64.decode(encoded[10].data(), encoded[10].size())); CHECK_TRUE(b64.error()); #endif } diff --git a/test/test_base64_RFC4648_decoder_with_no_padding.cpp b/test/test_base64_RFC4648_decoder_with_no_padding.cpp index dddfd0eb..a87852f3 100644 --- a/test/test_base64_RFC4648_decoder_with_no_padding.cpp +++ b/test/test_base64_RFC4648_decoder_with_no_padding.cpp @@ -383,8 +383,10 @@ namespace b64.decode_final(encoded[i].data(), encoded[i].size()); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -405,8 +407,10 @@ namespace b64.decode_final(encoded[i].data(), encoded[i].size()); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -444,8 +448,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -483,8 +489,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -505,8 +513,10 @@ namespace b64.decode_final(encoded[i].begin(), encoded[i].end()); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -527,8 +537,10 @@ namespace b64.decode_final(encoded[i].begin(), encoded[i].end()); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -566,8 +578,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -605,8 +619,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -637,8 +653,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -669,8 +687,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -705,8 +725,10 @@ namespace b64.flush(); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(b64.begin(), b64.end()); +#include "etl/private/diagnostic_pop.h" CHECK_EQUAL(expected.size(), actual.size()); CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); @@ -736,8 +758,10 @@ namespace constexpr auto output{ GetConstexprBase64(input) }; +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; std::vector actual(output.begin(), output.end()); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); CHECK_TRUE(codec::safe_output_buffer_size(14) >= output.size()); @@ -752,7 +776,7 @@ namespace #if ETL_USING_EXCEPTIONS CHECK_THROW((b64.decode(encoded[10].data(), encoded[10].size())), etl::base64_overflow); #else - CHECK_FALSE(b64.decode(encoded[10].data(), encoded[10].size()); + CHECK_FALSE(b64.decode(encoded[10].data(), encoded[10].size())); CHECK_TRUE(b64.error()); #endif } diff --git a/test/test_base64_RFC4648_decoder_with_padding.cpp b/test/test_base64_RFC4648_decoder_with_padding.cpp index 0b05fb9d..41e0a2ff 100644 --- a/test/test_base64_RFC4648_decoder_with_padding.cpp +++ b/test/test_base64_RFC4648_decoder_with_padding.cpp @@ -383,8 +383,10 @@ namespace b64.decode_final(encoded[i].data(), encoded[i].size()); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -405,8 +407,10 @@ namespace b64.decode_final(encoded[i].data(), encoded[i].size()); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -444,8 +448,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -483,8 +489,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -505,8 +513,10 @@ namespace b64.decode_final(encoded[i].begin(), encoded[i].end()); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -527,8 +537,10 @@ namespace b64.decode_final(encoded[i].begin(), encoded[i].end()); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -566,8 +578,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -605,8 +619,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -637,8 +653,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -669,8 +687,10 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(received_final_block); CHECK_EQUAL(expected.size(), actual.size()); @@ -705,8 +725,10 @@ namespace b64.flush(); +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(b64.begin(), b64.end()); +#include "etl/private/diagnostic_pop.h" CHECK_EQUAL(expected.size(), actual.size()); CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); @@ -736,8 +758,10 @@ namespace constexpr auto output{ GetConstexprBase64(input) }; +#include "etl/private/diagnostic_null_dereference_push.h" std::vector expected = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; std::vector actual(output.begin(), output.end()); +#include "etl/private/diagnostic_pop.h" CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); CHECK_TRUE(codec::safe_output_buffer_size(14) >= output.size()); @@ -752,7 +776,7 @@ namespace #if ETL_USING_EXCEPTIONS CHECK_THROW((b64.decode(encoded[10].data(), encoded[10].size())), etl::base64_overflow); #else - CHECK_FALSE(b64.decode(encoded[10].data(), encoded[10].size()); + CHECK_FALSE(b64.decode(encoded[10].data(), encoded[10].size())); CHECK_TRUE(b64.error()); #endif } diff --git a/test/test_multi_span.cpp b/test/test_multi_span.cpp index 2c150e35..0ae70810 100644 --- a/test/test_multi_span.cpp +++ b/test/test_multi_span.cpp @@ -557,7 +557,9 @@ namespace while (ms_itr != ms_end_itr) { // Fill the multi span +#include "etl/private/diagnostic_null_dereference_push.h" *ms_itr++ = *exp_itr++; +#include "etl/private/diagnostic_pop.h" } while (ms_itr != ms_end_itr) @@ -625,7 +627,9 @@ namespace for (size_t i = 0; i < expected.size(); ++i) { +#include "etl/private/diagnostic_null_dereference_push.h" *ms_itr = *exp_itr; +#include "etl/private/diagnostic_pop.h" if (i < expected.size() - 1) { diff --git a/test/test_rounded_integral_division.cpp b/test/test_rounded_integral_division.cpp index c03dc8e5..b3269aa0 100644 --- a/test/test_rounded_integral_division.cpp +++ b/test/test_rounded_integral_division.cpp @@ -732,7 +732,8 @@ namespace CHECK_EQUAL(std::numeric_limits::max(), etl::divide_round_half_even(std::numeric_limits::max(), int32_t(1))); CHECK_EQUAL(int32_t(0), etl::divide_round_half_even(int32_t(1), std::numeric_limits::max())); CHECK_EQUAL(std::numeric_limits::min(), etl::divide_round_half_even(std::numeric_limits::min(), int32_t(1))); - CHECK_EQUAL(int32_t(-1), etl::divide_round_half_even(int32_t(1), std::numeric_limits::min())); + CHECK_EQUAL(int32_t(0), etl::divide_round_half_even(int32_t(1), std::numeric_limits::min())); + CHECK_EQUAL(int32_t(1), etl::divide_round_half_even(std::numeric_limits::min(), std::numeric_limits::min())); } //************************************************************************* diff --git a/test/test_string_char.cpp b/test/test_string_char.cpp index faa28d7e..1294bbb9 100644 --- a/test/test_string_char.cpp +++ b/test/test_string_char.cpp @@ -1556,7 +1556,9 @@ namespace Text text2; +#include "etl/private/diagnostic_stringop_overflow_push.h" CHECK_THROW(text.insert(text2.cbegin(), insert_text.cbegin(), insert_text.cend()), etl::string_out_of_bounds); +#include "etl/private/diagnostic_pop.h" } //************************************************************************* diff --git a/test/unit_test_framework.h b/test/unit_test_framework.h index 798a6eae..f5d33b92 100644 --- a/test/unit_test_framework.h +++ b/test/unit_test_framework.h @@ -29,6 +29,8 @@ SOFTWARE. #ifndef ETL_UNIT_TEST_FRAMEWORK_INCLUDED #define ETL_UNIT_TEST_FRAMEWORK_INCLUDED +#include "etl/private/diagnostic_null_dereference_push.h" #include "UnitTest++/UnitTest++.h" +#include "etl/private/diagnostic_pop.h" #endif From 0d792ef13b20abf6873b57c7057876446be2e3ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1nyi=20B=C3=A9la?= <91312503+ivanyib@users.noreply.github.com> Date: Sat, 13 Dec 2025 09:28:29 +0100 Subject: [PATCH 038/298] Exception std based option (#1232) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add ability to derive etl::exception from std::exception * Only add test for exception std base when using STL * Use ETL_NOEXCEPT macro to define a function as noexcept * Rename macro to keep in line with common style * Add using_std_exception to etl::traits --------- Co-authored-by: Béla Iványi --- include/etl/exception.h | 22 ++++++++++++++++++---- include/etl/platform.h | 12 ++++++++++++ test/etl_profile.h | 3 +++ test/test_exception.cpp | 18 +++++++++++++++++- 4 files changed, 50 insertions(+), 5 deletions(-) diff --git a/include/etl/exception.h b/include/etl/exception.h index 49e6adca..4323df78 100644 --- a/include/etl/exception.h +++ b/include/etl/exception.h @@ -33,6 +33,14 @@ SOFTWARE. #include "platform.h" +#if ETL_USING_STD_EXCEPTION +#include + + #define ETL_EXCEPTION_CONSTEXPR +#else + #define ETL_EXCEPTION_CONSTEXPR ETL_CONSTEXPR +#endif + ///\defgroup exception exception /// The base class for all ETL exceptions. ///\ingroup utilities @@ -44,6 +52,9 @@ namespace etl /// A low overhead exception base class. //*************************************************************************** class exception +#if ETL_USING_STD_EXCEPTION + : public std::exception +#endif { public: @@ -54,7 +65,7 @@ namespace etl //************************************************************************* /// Constructor. //************************************************************************* - ETL_CONSTEXPR + ETL_EXCEPTION_CONSTEXPR exception(string_type reason_, string_type file_, numeric_type line_) : reason_text(reason_), file_text(file_), @@ -65,7 +76,7 @@ namespace etl //************************************************************************* /// Constructor. //************************************************************************* - ETL_CONSTEXPR + ETL_EXCEPTION_CONSTEXPR exception(string_type reason_, string_type /*file_*/, numeric_type line_) : reason_text(reason_), line(line_) @@ -77,8 +88,11 @@ namespace etl /// Gets the reason for the exception. /// \return const char* to the reason. //*************************************************************************** - ETL_CONSTEXPR - string_type what() const + ETL_EXCEPTION_CONSTEXPR + string_type what() const ETL_NOEXCEPT +#if ETL_USING_STD_EXCEPTION + override +#endif { return reason_text; } diff --git a/include/etl/platform.h b/include/etl/platform.h index 89fafeef..62a5da60 100644 --- a/include/etl/platform.h +++ b/include/etl/platform.h @@ -293,6 +293,17 @@ SOFTWARE. #define ETL_HAS_VIRTUAL_MESSAGES 1 #endif +//************************************* +// Indicate if etl::exception is to be derived from std::exception. +#if defined(ETL_USE_STD_EXCEPTION) +#if ETL_NOT_USING_STL + #error "Requested std base for etl::exception, but STL is not used" +#endif + #define ETL_USING_STD_EXCEPTION 1 +#else + #define ETL_USING_STD_EXCEPTION 0 +#endif + //************************************* // Indicate if etl::literals::chrono_literals uses ETL verbose style. #if defined(ETL_USE_VERBOSE_CHRONO_LITERALS) && ETL_USING_CPP11 @@ -631,6 +642,7 @@ namespace etl static ETL_CONSTANT bool using_legacy_bitset = (ETL_USING_LEGACY_BITSET == 1); static ETL_CONSTANT bool using_exceptions = (ETL_USING_EXCEPTIONS == 1); static ETL_CONSTANT bool using_libc_wchar_h = (ETL_USING_LIBC_WCHAR_H == 1); + static ETL_CONSTANT bool using_std_exception = (ETL_USING_STD_EXCEPTION == 1); // Has... static ETL_CONSTANT bool has_initializer_list = (ETL_HAS_INITIALIZER_LIST == 1); diff --git a/test/etl_profile.h b/test/etl_profile.h index d29a1093..b6089a40 100644 --- a/test/etl_profile.h +++ b/test/etl_profile.h @@ -44,6 +44,9 @@ SOFTWARE. #define ETL_IN_UNIT_TEST //#define ETL_DEBUG_COUNT #define ETL_ARRAY_VIEW_IS_MUTABLE +#if !defined(ETL_NO_STL) +#define ETL_USE_STD_EXCEPTION +#endif #define ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK #define ETL_CALLBACK_TIMER_USE_ATOMIC_LOCK diff --git a/test/test_exception.cpp b/test/test_exception.cpp index 0a57804f..474eee96 100644 --- a/test/test_exception.cpp +++ b/test/test_exception.cpp @@ -61,5 +61,21 @@ namespace CHECK_EQUAL(123, c.line_number()); } } - } + +#if ETL_USING_STD_EXCEPTION + TEST(test_exception_std_base) + { + etl::exception e("An exception", "Some file", 123); + + try + { + throw e; + } + catch (std::exception& c) + { + CHECK_EQUAL(std::string("An exception"), std::string(c.what())); + } + } +#endif + }; } From 520b4a9f46b7594d2dd56a747320143aec1e2e83 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 21 Dec 2025 07:31:06 +0000 Subject: [PATCH 039/298] Removed redundant semicolon from TEST_SUITE block --- .gitignore | 1 + test/test_exception.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 068e7602..ced27dae 100644 --- a/.gitignore +++ b/.gitignore @@ -411,3 +411,4 @@ examples/UniquePtrWithPool/UniquePtrWithPool test/vs2022/Debug Clang C++20 - Optimised -O2 include/etl/header_file_list.txt temp +test/syntax_check/build-make diff --git a/test/test_exception.cpp b/test/test_exception.cpp index 474eee96..7fe95f10 100644 --- a/test/test_exception.cpp +++ b/test/test_exception.cpp @@ -77,5 +77,5 @@ namespace } } #endif - }; + } } From 269f3ffdfd03d7d209cf33b5856546ccb55941db Mon Sep 17 00:00:00 2001 From: whitfijs-jw <58998493+whitfijs-jw@users.noreply.github.com> Date: Sat, 13 Dec 2025 03:04:38 -0500 Subject: [PATCH 040/298] Topic/expected monadic operations (#1219) * topic/expected-monadic-operations: - added and_then, or_else, transform, and transform_error with simple tests * topic/expected-monadic-operation: - added void TValue specialization operations - updated unit tests to include expected - added is_expected to expected.h, used in and_then to ensure that the returned type is an expected * topic/expected-monadic-operations: - made implementation c++11 compatible * topic/expected-monadic-operations: - started addressing coderabbit feedback * topic/expected-monadic-operations: - adapted invoke to etl - reworked return type deduction - filled in or_else unit tests to be more complete - still need to add invoke unit tests * topic/expected-monadic-operations: -c++14 compliance * topic/expected-monadic-operations: - completed coderabbit suggestions * topic/expected-monadic-operations: - formatting in invoke and expected - added test suite for invoke * topic/expected-monadic-operations: - fixed missing moves for const TValue&& and const TError&& * topic/expected-monadic-operations: - made everything c++11 compatible, very verbose as a result * topic/expected-monadic-operations: - fixed code rabbit rewivew for move semantics in const && overloads * topic/expected-monadic-operations: - moved around a move * topic/expected-monadic-operations: - added etl:: to invoke_result calls that were missing it * topic/expected-monadic-operations: - formatting * topic/expected-monadic-operations: - added invoke for void f() calls for consistency * topic/expected-monadic-operations: - reworked entire thing to be able to handle expected to expected without even more code duplication * topic/expected-monadic-operations: - added trailing return type to maintain c++11 compatibility * topic/expected-monadic-operations: - fixed mismatch between deduced type and return for a few functions * topic/expected-monadic-operations: - replaced calls to get and get with get and get --------- Co-authored-by: Jon Whitfield --- include/etl/expected.h | 340 +++++++++++++++++++++++ include/etl/invoke.h | 148 ++++++++++ test/CMakeLists.txt | 1 + test/test_expected.cpp | 613 ++++++++++++++++++++++++++++++++++++++++- test/test_invoke.cpp | 184 +++++++++++++ 5 files changed, 1285 insertions(+), 1 deletion(-) create mode 100644 include/etl/invoke.h create mode 100644 test/test_invoke.cpp diff --git a/include/etl/expected.h b/include/etl/expected.h index 71c9d303..948df290 100644 --- a/include/etl/expected.h +++ b/include/etl/expected.h @@ -39,9 +39,20 @@ SOFTWARE. #include "utility.h" #include "variant.h" #include "initializer_list.h" +#include "type_traits.h" +#include "invoke.h" namespace etl { + // Forward declaration for is_expected + template class expected; + + template + struct is_expected : etl::false_type {}; + + template + struct is_expected> : etl::true_type {}; + //*************************************************************************** /// Base exception for et::expected //*************************************************************************** @@ -732,6 +743,104 @@ namespace etl } #endif +#if ETL_USING_CPP11 + template ::type>::type> + auto transform(F&& f) & -> expected + { + return transform_impl(etl::forward(f), *this); + } + + template ::type>::type> + auto transform(F&& f) const& -> expected + { + return transform_impl(etl::forward(f), *this); + } + + template ::type>::type> + auto transform(F&& f) && -> expected + { + return transform_impl(etl::forward(f), etl::move(*this)); + } + + template ::type>::type> + auto transform(F&& f) const&& -> expected + { + return transform_impl(etl::forward(f), etl::move(*this)); + } + + template ::type>::type> + auto and_then(F&& f) & -> U + { + return and_then_impl(etl::forward(f), *this); + } + + template ::type>::type> + auto and_then(F&& f) const& -> U + { + return and_then_impl(etl::forward(f), *this); + } + + template ::type>::type> + auto and_then(F&& f) && -> U + { + return and_then_impl(etl::forward(f), etl::move(*this)); + } + + template ::type>::type> + auto and_then(F&& f) const&& -> U + { + return and_then_impl(etl::forward(f), etl::move(*this)); + } + + template ::type>::type> + auto or_else(F&& f) & -> U + { + return or_else_impl(etl::forward(f), *this); + } + + template ::type>::type> + auto or_else(F&& f) const & -> U + { + return or_else_impl(etl::forward(f), *this); + } + + template ::type>::type> + auto or_else(F&& f) && -> U + { + return or_else_impl(etl::forward(f), etl::move(*this)); + } + + template ::type>::type> + auto or_else(F&& f) const && -> U + { + return or_else_impl(etl::forward(f), etl::move(*this)); + } + + template ::type>::type> + auto transform_error(F&& f) & -> expected + { + return transform_error_impl(etl::forward(f), *this); + } + + template ::type>::type> + auto transform_error(F&& f) const & -> expected + { + return transform_error_impl(etl::forward(f), *this); + } + + template ::type>::type> + auto transform_error(F&& f) && -> expected + { + return transform_error_impl(etl::forward(f), etl::move(*this)); + } + + template ::type>::type> + auto transform_error(F&& f) const&& -> expected + { + return transform_error_impl(etl::forward(f), etl::move(*this)); + } +#endif + private: enum @@ -743,6 +852,72 @@ namespace etl typedef etl::variant storage_type; storage_type storage; + + template ::value>::type> + auto transform_impl(F&& f, TExp&& exp) const -> expected + { + if (exp.has_value()) + { + return expected(etl::invoke(etl::forward(f), etl::forward(etl::get(exp.storage)))); + } + else + { + return expected(unexpected(etl::forward(exp).error())); + } + } + + template ::value>::type> + auto transform_impl(F&& f, TExp&& exp) const -> expected + { + if (exp.has_value()) + { + etl::invoke(etl::forward(f), etl::forward(etl::get(exp.storage))); + return expected(); + } + else + { + return expected(unexpected(etl::forward(exp).error())); + } + } + + template ::value && etl::is_expected::value && etl::is_same::value>::type> + auto and_then_impl(F&& f, TExp&& exp) const -> TRet + { + if (exp.has_value()) + { + return etl::invoke(etl::forward(f), etl::forward(etl::get(exp.storage))); + } + else + { + return TRet(unexpected(etl::forward(exp).error())); + } + } + + template ::value && etl::is_expected::value && etl::is_same::value>::type> + auto or_else_impl(F&& f, TExp&& exp) const -> TRet + { + if (exp.has_value()) + { + return TRet(etl::forward(exp).value()); + } + else + { + return etl::invoke(etl::forward(f), etl::forward(etl::get(exp.storage))); + } + } + + template ::value>::type> + auto transform_error_impl(F&& f, TExp&& exp) const -> expected + { + if (exp.has_value()) + { + return expected(etl::forward(exp).value()); + } + else + { + return expected(unexpected(etl::invoke(etl::forward(f), etl::forward(etl::get(exp.storage))))); + } + } }; //***************************************************************************** @@ -942,6 +1117,105 @@ namespace etl swap(storage, other.storage); } +#if ETL_USING_CPP11 + template::type>::type> + auto transform(F&& f) & -> expected + { + return transform_impl(etl::forward(f), *this); + } + + template::type>::type> + auto transform(F&& f) const & -> expected + { + return transform_impl(etl::forward(f), *this); + } + + template::type>::type> + auto transform(F&& f) && -> expected + { + return transform_impl(etl::forward(f), etl::move(*this)); + } + + template::type>::type> + auto transform(F&& f) const && -> expected + { + return transform_impl(etl::forward(f), etl::move(*this)); + } + + template::type>::type> + auto and_then(F&& f) & -> U + { + return and_then_impl(etl::forward(f), *this); + } + + template::type>::type> + auto and_then(F&& f) const & -> U + { + return and_then_impl(etl::forward(f), *this); + } + + template::type>::type> + auto and_then(F&& f) && -> U + { + return and_then_impl(etl::forward(f), etl::move(*this)); + } + + template::type>::type> + auto and_then(F&& f) const && -> U + { + return and_then_impl(etl::forward(f), etl::move(*this)); + } + + template ::type>::type> + auto or_else(F&& f) & -> U + { + return or_else_impl(etl::forward(f), *this); + } + + template ::type>::type> + auto or_else(F&& f) const & -> U + { + return or_else_impl(etl::forward(f), *this); + } + + template ::type>::type> + auto or_else(F&& f) && -> U + { + return or_else_impl(etl::forward(f), etl::move(*this)); + } + + template ::type>::type> + auto or_else(F&& f) const && -> U + { + return or_else_impl(etl::forward(f), etl::move(*this)); + } + + template ::type>::type> + auto transform_error(F&& f) & -> expected + { + return transform_error_impl(etl::forward(f), *this); + } + + template ::type>::type> + auto transform_error(F&& f) const & -> expected + { + return transform_error_impl(etl::forward(f), *this); + } + + template ::type>::type> + auto transform_error(F&& f) && -> expected + { + return transform_error_impl(etl::forward(f), etl::move(*this)); + } + + template ::type>::type> + auto transform_error(F&& f) const && -> expected + { + return transform_error_impl(etl::forward(f), *this); + } +#endif + + private: enum @@ -951,6 +1225,72 @@ namespace etl }; etl::variant storage; + + template ::value>::type> + auto transform_impl(F&& f, TExp&& exp) const -> expected + { + if (exp.has_value()) + { + return expected(etl::invoke(etl::forward(f))); + } + else + { + return expected(unexpected(etl::forward(exp).error())); + } + } + + template ::value>::type> + auto transform_impl(F&& f, TExp&& exp) const -> expected + { + if (exp.has_value()) + { + etl::invoke(etl::forward(f)); + return expected(); + } + else + { + return expected(unexpected(etl::forward(exp).error())); + } + } + + template ::value && etl::is_expected::value && etl::is_same::value>::type> + auto and_then_impl(F&& f, TExp&& exp) const -> TRet + { + if (exp.has_value()) + { + return etl::invoke(etl::forward(f)); + } + else + { + return TRet(unexpected(etl::forward(exp).error())); + } + } + + template ::value && etl::is_expected::value && etl::is_same::value>::type> + auto or_else_impl(F&& f, TExp&& exp) const -> TRet + { + if (exp.has_value()) + { + return TRet(); + } + else + { + return etl::invoke(etl::forward(f), etl::forward(etl::get(exp.storage))); + } + } + + template ::value>::type> + auto transform_error_impl(F&& f, TExp&& exp) const -> expected + { + if (exp.has_value()) + { + return expected(); + } + else + { + return expected(unexpected(etl::invoke(etl::forward(f), etl::forward(etl::get(exp.storage))))); + } + } }; } diff --git a/include/etl/invoke.h b/include/etl/invoke.h new file mode 100644 index 00000000..67606e26 --- /dev/null +++ b/include/etl/invoke.h @@ -0,0 +1,148 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_INVOKE_INCLUDED +#define ETL_INVOKE_INCLUDED + +#include "platform.h" +#include "functional.h" +#include "function_traits.h" +#include "type_traits.h" +#include "utility.h" + +namespace etl { + template struct logical_not_t : etl::integral_constant {}; + + /// is T a function -- a function cannot be const qualified like a variable + template struct is_function : public etl::integral_constant::value> { }; + template struct is_function : public etl::false_type { }; + template struct is_function : public etl::false_type { }; + + /// is T a member pointer + template struct is_member_pointer_helper : etl::false_type {}; + template struct is_member_pointer_helper : etl::true_type {}; + template struct is_member_pointer : is_member_pointer_helper> {}; + + /// is T a member function pointer + template struct is_member_function_pointer_helper : etl::false_type {}; + template struct is_member_function_pointer_helper : public etl::is_function::type {}; + template struct is_member_function_pointer : public is_member_function_pointer_helper>::type {}; + + /// is T a member object pointer + template struct is_member_object_pointer_helper : public etl::false_type { }; + template struct is_member_object_pointer_helper : public logical_not_t>::type { }; + template struct is_member_object_pointer : public is_member_object_pointer_helper>::type {}; + + template < + typename F, + typename ... TArgs, + typename = typename etl::enable_if< + !etl::is_member_pointer>::value>::type + > + ETL_CONSTEXPR auto invoke(F&& f, TArgs&& ... args) + -> decltype(etl::forward(f)(etl::forward(args)...)) { + return etl::forward(f)(etl::forward(args)...); + } + + template < + typename F, + typename T, + typename... TArgs, + typename = typename etl::enable_if< + etl::is_member_function_pointer>::value && + !etl::is_pointer>::value + >::type + > + ETL_CONSTEXPR auto invoke(F&& f, T&& t, TArgs&&... args) + -> decltype((etl::forward(t).*f)(etl::forward(args)...)) + { + return (etl::forward(t).*f)(etl::forward(args)...); + } + + template < + typename F, + typename T, + typename ... TArgs, + typename = typename etl::enable_if< + etl::is_member_function_pointer>::value && + etl::is_pointer>::value + >::type + > + ETL_CONSTEXPR auto invoke(F&& f, T&& t, TArgs&&... args) + -> decltype(((*etl::forward(t)).*f)(etl::forward(args)...)) + { + return ((*etl::forward(t)).*f)(etl::forward(args)...); + } + + template < + typename F, + typename T, + typename = typename etl::enable_if< + etl::is_member_object_pointer>::value && + !etl::is_pointer>::value + >::type + > + ETL_CONSTEXPR auto invoke(F&& f, T&& t) + -> decltype(etl::forward(t).*f) + { + return etl::forward(t).*f; + } + + template < + typename F, + typename T, + typename = typename etl::enable_if< + etl::is_member_object_pointer>::value && + etl::is_pointer>::value + >::type + > + ETL_CONSTEXPR auto invoke(F&& f, T&& t) + -> decltype(((*etl::forward(t)).*f)) + { + return ((*etl::forward(t)).*f); + } + + template struct invoke_result; + + template + struct invoke_result< + F, + etl::void_t(), etl::declval()...))>, + Us... + > { + using type = decltype(etl::invoke(etl::declval(), etl::declval()...)); + }; + + template + using invoke_result_t = typename invoke_result::type; + +} + +#endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 00934d8d..ccfe9001 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -209,6 +209,7 @@ add_executable(etl_tests test_invert.cpp test_io_port.cpp test_iterator.cpp + test_invoke.cpp test_jenkins.cpp test_largest.cpp test_limiter.cpp diff --git a/test/test_expected.cpp b/test/test_expected.cpp index e71a218a..9bfc5650 100644 --- a/test/test_expected.cpp +++ b/test/test_expected.cpp @@ -792,5 +792,616 @@ namespace CHECK_TRUE(test_unexp_1_swap == test_unexp_2); CHECK_TRUE(test_unexp_2_swap == test_unexp_1); } - } + + //************************************************************************* + template + struct value_type_helper + { + static bool check(TExpected& expected) + { + return etl::is_same::type, TValue>::value; + } + }; + + template + struct value_type_helper::value>::type> + { + static bool check(TExpected& expected) + { + (void)expected; + return true; + } + }; + + template + bool check_expected_type_helper(TExpected& expected) + { + + bool value_type_ok = value_type_helper::check(expected); + + bool error_type_ok = etl::is_same::type, TError>::value; + + bool expected_type_ok = etl::is_same::type, etl::expected >::value; + + return value_type_ok && error_type_ok && expected_type_ok; + } + + //************************************************************************* + + TEST(test_or_else) + { + Expected expected = {Value("or_else_with_value")}; + Expected expected_error = {Unexpected(Error("or_else_with_error"))}; + + const Expected expected_const = {Value("const_or_else_with_value")}; + const Expected expected_error_const = {Unexpected(Error("const_or_else_with_error"))}; + + bool error_generated {false}; + + auto expected_out = expected.or_else([&error_generated](Error e) + -> Expected + { + error_generated = true; + return Unexpected(e); + }); + + CHECK_FALSE(error_generated); + CHECK_TRUE(expected_out.has_value()); + CHECK_EQUAL("or_else_with_value", expected_out.value().v); + + auto with_value_type_check = check_expected_type_helper(expected_out); + CHECK_TRUE(with_value_type_check); + + error_generated = false; + auto expected_const_out = expected_const.or_else([&error_generated](const Error& e) -> Expected { + error_generated = true; + return Unexpected(e); + }); + + CHECK_FALSE(error_generated); + CHECK_TRUE(expected_const_out.has_value()); + CHECK_EQUAL("const_or_else_with_value", expected_const_out.value().v); + + error_generated = false; + auto unexpected_out = expected_error.or_else([&error_generated](Error e) -> Expected { + error_generated = true; + return Unexpected(e); + }); + + CHECK_TRUE(error_generated); + CHECK_FALSE(unexpected_out.has_value()); + + auto with_error_type_check = check_expected_type_helper(unexpected_out); + CHECK_TRUE(with_error_type_check); + + CHECK_EQUAL("or_else_with_error", unexpected_out.error().e); + + + error_generated = false; + auto unexpected_const_out = expected_error_const.or_else([&error_generated](const Error& e) -> Expected { + error_generated = true; + return Unexpected(e); + }); + + CHECK_TRUE(error_generated); + CHECK_FALSE(unexpected_const_out.has_value()); + + auto with_error_const_type_check = check_expected_type_helper(unexpected_const_out); + CHECK_TRUE(with_error_const_type_check); + + CHECK_EQUAL("const_or_else_with_error", unexpected_const_out.error().e); + } + + //************************************************************************* + + TEST(test_or_else_move_constructor) { + ExpectedM expected = ExpectedM(ValueM("or_else_with_value")); + ExpectedM expected_error = ExpectedM(UnexpectedM(ErrorM("or_else_with_error"))); + bool error_generated {false}; + + auto expected_out = etl::move(expected).or_else([&error_generated](ErrorM e) -> ExpectedM { + error_generated = true; + UnexpectedM unexpected(etl::move(e)); + return ExpectedM(etl::move(unexpected)); + }); + + CHECK_FALSE(error_generated); + CHECK_TRUE(expected_out.has_value()); + CHECK_EQUAL("or_else_with_value", expected_out.value().v); + + auto with_value_type_check = check_expected_type_helper(expected_out); + CHECK_TRUE(with_value_type_check); + + auto unexpected_out = etl::move(expected_error).or_else([&error_generated](ErrorM e) -> ExpectedM { + error_generated = true; + CHECK_EQUAL("or_else_with_error", e.e); + + UnexpectedM unexpected(etl::move(e)); + return ExpectedM(etl::move(unexpected)); + }); + + CHECK_TRUE(error_generated); + CHECK_FALSE(unexpected_out.has_value()); + + auto with_error_type_check = check_expected_type_helper(unexpected_out); + CHECK_TRUE(with_error_type_check); + + CHECK_EQUAL("or_else_with_error", unexpected_out.error().e); + + //The following should NOT compile. The const & overload should attempt to copy + // const ExpectedM expected_error_const = ExpectedM(ValueM("or_else_with_value")); + // expected_error_const.or_else([&error_generated](ErrorM e) -> const ExpectedM { + // error_generated = true; + // UnexpectedM unexpected(etl::move(e)); + // return ExpectedM(etl::move(unexpected)); + // }); + } + + //************************************************************************* + + TEST(test_or_else_void) { + ExpectedV expected = ExpectedV(); + ExpectedV expected_error = ExpectedV(Unexpected(Error("or_else_with_error"))); + bool error_generated {false}; + + auto expected_out = expected.or_else([&error_generated](Error e) -> ExpectedV { + error_generated = true; + return Unexpected(e); + }); + + CHECK_FALSE(error_generated); + CHECK_TRUE(expected_out.has_value()); + + auto with_value_type_check = check_expected_type_helper(expected_out); + CHECK_TRUE(with_value_type_check); + + auto unexpected_out = expected_error.or_else([&error_generated](Error e) -> ExpectedV { + error_generated = true; + CHECK_EQUAL("or_else_with_error", e.e); + return Unexpected(e); + }); + + CHECK_TRUE(error_generated); + CHECK_FALSE(unexpected_out.has_value()); + + auto with_error_type_check = check_expected_type_helper(unexpected_out); + CHECK_TRUE(with_error_type_check); + + CHECK_EQUAL("or_else_with_error", unexpected_out.error().e); + } + + //************************************************************************* + + TEST(test_or_else_change_error) { + Expected expected_error = {Unexpected(Error("or_else_with_error"))}; + ExpectedV expectedV_error = ExpectedV(Unexpected(Error("or_else_with_error"))); + + auto change_to_string = expectedV_error.or_else([](Error e) -> etl::expected { + return etl::unexpected(e.e.append("_to_string")); + }); + + auto with_error_type_check = check_expected_type_helper(change_to_string); + CHECK_TRUE(with_error_type_check); + + CHECK_EQUAL("or_else_with_error_to_string", change_to_string.error()); + } + + //************************************************************************* + + TEST(test_or_else_change_error_move_constructor) { + ExpectedM expected_error = ExpectedM(UnexpectedM(ErrorM("or_else_with_error"))); + + auto change_to_string = etl::move(expected_error).or_else([](ErrorM e) -> etl::expected { + return etl::unexpected(e.e.append("_to_string")); + }); + + auto with_error_type_check = check_expected_type_helper(change_to_string); + CHECK_TRUE(with_error_type_check); + + CHECK_EQUAL("or_else_with_error_to_string", change_to_string.error()); + } + + //************************************************************************* + + TEST(test_or_else_const_rvalue) { + bool error_generated {false}; + auto temp_expected = Expected(Unexpected(Error("temp_const_error"))); + + auto unexpected_out = static_cast(temp_expected) + .or_else([&error_generated](const Error& e) -> Expected { + error_generated = true; + CHECK_EQUAL("temp_const_error", e.e); + return Expected(Unexpected(etl::move(e))); + }); + + CHECK_TRUE(error_generated); + CHECK_EQUAL("temp_const_error", unexpected_out.error().e); + } + + //************************************************************************* + + TEST(test_transform) { + Expected expected = {Value("transform_with_value")}; + Expected expected_error = {Unexpected(Error("transform_with_error"))}; + const Expected expected_const = {Value("const_transform_with_value")}; + + auto expected_out = expected.transform([](Value v) { + auto s = v.v.append("_transformed"); + return s; + }); + + CHECK_TRUE(expected_out.has_value()); + CHECK_EQUAL("transform_with_value_transformed", expected_out.value()); + + auto with_value_type_check = check_expected_type_helper(expected_out); + CHECK_TRUE(with_value_type_check); + + + auto expected_out_const = expected_const.transform([](const Value& v) { + auto s = v; + return s.v.append("_transformed"); + }); + + CHECK_TRUE(expected_out_const.has_value()); + CHECK_EQUAL("const_transform_with_value_transformed", expected_out_const.value()); + + auto const_with_value_type_check = check_expected_type_helper(expected_out_const); + CHECK_TRUE(const_with_value_type_check); + + auto unexpected_out = expected_error.transform([](Value v) { + auto s = v.v.append("_transformed"); + return s; + }); + + CHECK_FALSE(unexpected_out.has_value()); + + auto with_error_type_check = check_expected_type_helper(unexpected_out); + CHECK_TRUE(with_error_type_check); + + CHECK_EQUAL("transform_with_error", unexpected_out.error().e); + } + + //************************************************************************* + + TEST(test_transform_move_constructor) { + ExpectedM expected = {ValueM("transform_with_value")}; + ExpectedM expected_error = ExpectedM(UnexpectedM(ErrorM("transform_with_error"))); + + auto expected_out = etl::move(expected).transform([](ValueM v) { + auto s = v.v.append("_transformed"); + return etl::move(s); + }); + + CHECK_TRUE(expected_out.has_value()); + CHECK_EQUAL("transform_with_value_transformed", expected_out.value()); + + auto with_value_type_check = check_expected_type_helper(expected_out); + CHECK_TRUE(with_value_type_check); + + auto unexpected_out = etl::move(expected_error).transform([](ValueM v) { + auto s = v.v.append("_transformed"); + return etl::move(s); + }); + + CHECK_FALSE(unexpected_out.has_value()); + + auto with_error_type_check = check_expected_type_helper(unexpected_out); + CHECK_TRUE(with_error_type_check); + + CHECK_EQUAL("transform_with_error", unexpected_out.error().e); + } + + //************************************************************************* + + TEST(test_transform_void) { + ExpectedV expected; + ExpectedV expected_error = {Unexpected(Error("transform_with_error"))}; + + auto expected_out = expected.transform([]() { + std::string s("_transformed"); + return s; + }); + + CHECK_TRUE(expected_out.has_value()); + CHECK_EQUAL("_transformed", expected_out.value()); + + auto with_value_type_check = check_expected_type_helper(expected_out); + CHECK_TRUE(with_value_type_check); + + auto unexpected_out = expected_error.transform([]() { + std::string s("_transformed"); + return s; + }); + + CHECK_FALSE(unexpected_out.has_value()); + + auto with_error_type_check = check_expected_type_helper(unexpected_out); + CHECK_TRUE(with_error_type_check); + + CHECK_EQUAL("transform_with_error", unexpected_out.error().e); + } + + TEST(test_transform_void_move) { + ExpectedVM expected; + ExpectedVM expected_error = {UnexpectedM(ErrorM("transform_with_error"))}; + + auto expected_out = etl::move(expected).transform([]() { + std::string s("_transformed"); + return s; + }); + + CHECK_TRUE(expected_out.has_value()); + CHECK_EQUAL("_transformed", expected_out.value()); + + auto with_value_type_check = check_expected_type_helper(expected_out); + CHECK_TRUE(with_value_type_check); + + auto unexpected_out = etl::move(expected_error).transform([]() { + std::string s("_transformed"); + return s; + }); + + CHECK_FALSE(unexpected_out.has_value()); + + auto with_error_type_check = check_expected_type_helper(unexpected_out); + CHECK_TRUE(with_error_type_check); + + CHECK_EQUAL("transform_with_error", unexpected_out.error().e); + } + + //************************************************************************* + + TEST(test_transform_to_void) { + Expected expected {Value("transform_to_void")}; + + bool executed {false}; + auto expected_out = expected.transform([&executed](Value v) { + (void) v; + executed = true; + CHECK_EQUAL("transform_to_void", v.v); + return; + }); + + auto to_void_type_check = check_expected_type_helper(expected_out); + CHECK_TRUE(to_void_type_check); + + CHECK_TRUE(expected_out.has_value()); + } + + //************************************************************************* + + TEST(test_and_then) { + Expected expected = {Value("and_then_with_value")}; + Expected expected_error = {Unexpected(Error("and_then_with_error"))}; + const Expected expected_const = {Value("const_and_then_with_value")}; + + auto expected_out = expected.and_then([](Value v) -> Expected { + return Value(v.v.append("_and_thened")); + }); + + CHECK_TRUE(expected_out.has_value()); + CHECK_EQUAL("and_then_with_value_and_thened", expected_out.value().v); + + auto with_value_type_check = check_expected_type_helper(expected_out); + CHECK_TRUE(with_value_type_check); + + auto expected_out_const = expected_const.and_then([](const Value& v) -> Expected { + auto s = v; + return Value(s.v.append("_and_thened")); + }); + + CHECK_TRUE(expected_out_const.has_value()); + CHECK_EQUAL("const_and_then_with_value_and_thened", expected_out_const.value().v); + + auto const_with_value_type_check = check_expected_type_helper(expected_out_const); + CHECK_TRUE(const_with_value_type_check); + + auto unexpected_out = expected_error.and_then([](Value v) -> Expected { + return Value(v.v.append("_and_thened")); + }); + + CHECK_FALSE(unexpected_out.has_value()); + + auto with_error_type_check = check_expected_type_helper(unexpected_out); + CHECK_TRUE(with_error_type_check); + + CHECK_EQUAL("and_then_with_error", unexpected_out.error().e); + } + + //************************************************************************* + + TEST(test_and_then_move_constructor) { + ExpectedM expected = ExpectedM(ValueM("and_then_with_value")); + ExpectedM expected_error = ExpectedM(UnexpectedM(ErrorM("and_then_with_error"))); + + auto expected_out = etl::move(expected).and_then([](ValueM v) -> ExpectedM { + return ValueM(etl::move(v.v.append("_and_thened"))); + }); + + CHECK_TRUE(expected_out.has_value()); + CHECK_EQUAL("and_then_with_value_and_thened", expected_out.value().v); + + auto with_value_type_check = check_expected_type_helper(expected_out); + CHECK_TRUE(with_value_type_check); + + auto unexpected_out = etl::move(expected_error).and_then([](ValueM&& v) -> ExpectedM { + return ValueM(v.v.append("_and_thened")); + }); + + CHECK_FALSE(unexpected_out.has_value()); + + auto with_error_type_check = check_expected_type_helper(unexpected_out); + CHECK_TRUE(with_error_type_check); + + CHECK_EQUAL("and_then_with_error", unexpected_out.error().e); + } + + //************************************************************************* + + TEST(test_and_then_void) { + ExpectedV expected; + ExpectedV expected_error = {Unexpected(Error("and_then_with_error"))}; + auto and_thened {false}; + + auto expected_out = expected.and_then([&and_thened]() -> ExpectedV { + and_thened = true; + return ExpectedV(); + }); + + CHECK_TRUE(and_thened); + CHECK_TRUE(expected_out.has_value()); + + auto with_value_type_check = check_expected_type_helper(expected_out); + CHECK_TRUE(with_value_type_check); + + and_thened = false; + auto unexpected_out = expected_error.and_then([&and_thened]() -> ExpectedV { + and_thened = true; + return ExpectedV(); + }); + + CHECK_FALSE(unexpected_out.has_value()); + + auto with_error_type_check = check_expected_type_helper(unexpected_out); + CHECK_TRUE(with_error_type_check); + + CHECK_EQUAL("and_then_with_error", unexpected_out.error().e); + } + + TEST(test_and_then_void_move) { + ExpectedVM expected; + ExpectedVM expected_error = {UnexpectedM(ErrorM("and_then_with_error"))}; + auto and_thened {false}; + + auto expected_out = etl::move(expected).and_then([&and_thened]() -> ExpectedVM { + and_thened = true; + return ExpectedVM(); + }); + + CHECK_TRUE(and_thened); + CHECK_TRUE(expected_out.has_value()); + + auto with_value_type_check = check_expected_type_helper(expected_out); + CHECK_TRUE(with_value_type_check); + + and_thened = false; + auto unexpected_out = etl::move(expected_error).and_then([&and_thened]() -> ExpectedVM { + and_thened = true; + return ExpectedVM(); + }); + + CHECK_FALSE(unexpected_out.has_value()); + + auto with_error_type_check = check_expected_type_helper(unexpected_out); + CHECK_TRUE(with_error_type_check); + + CHECK_EQUAL("and_then_with_error", unexpected_out.error().e); + } + + //************************************************************************* + + TEST(test_transform_error) { + Expected expected = {Value("transform_error_with_value")}; + Expected expected_error = {Unexpected(Error("transform_error_with_error"))}; + + auto expected_out = expected.transform_error([](Error e) { + auto s = e.e.append("_transformed"); + return s; + }); + + CHECK_TRUE(expected_out.has_value()); + CHECK_EQUAL("transform_error_with_value", expected_out.value().v); + + auto with_value_type_check = check_expected_type_helper(expected_out); + CHECK_TRUE(with_value_type_check); + + auto unexpected_out = expected_error.transform_error([](Error e) { + std::string s = e.e.append("_transformed"); + return s; + }); + + CHECK_FALSE(unexpected_out.has_value()); + + auto with_error_type_check = check_expected_type_helper(unexpected_out); + CHECK_TRUE(with_error_type_check); + + CHECK_EQUAL("transform_error_with_error_transformed", unexpected_out.error()); + } + + //************************************************************************* + + TEST(test_transform_error_move_constructor) { + ExpectedM expected = ExpectedM(ValueM("transform_error_with_value")); + ExpectedM expected_error = ExpectedM(UnexpectedM(ErrorM("transform_error_with_error"))); + + auto expected_out = etl::move(expected).transform_error([](ErrorM e) { + auto s = e.e.append("_transformed"); + return s; + }); + + CHECK_TRUE(expected_out.has_value()); + CHECK_EQUAL("transform_error_with_value", expected_out.value().v); + + auto with_value_type_check = check_expected_type_helper(expected_out); + CHECK_TRUE(with_value_type_check); + + auto unexpected_out = etl::move(expected_error).transform_error([](ErrorM e) { + std::string s = e.e.append("_transformed"); + return s; + }); + + CHECK_FALSE(unexpected_out.has_value()); + + auto with_error_type_check = check_expected_type_helper(unexpected_out); + CHECK_TRUE(with_error_type_check); + + CHECK_EQUAL("transform_error_with_error_transformed", unexpected_out.error()); + } + + TEST(test_transform_error_const_rvalue) { + bool error_generated {false}; + auto temp_expected = Expected(Unexpected(Error("temp_const_error"))); + + auto unexpected_out = static_cast(temp_expected) + .transform_error([&error_generated](const Error& e) -> std::string { + error_generated = true; + CHECK_EQUAL("temp_const_error", e.e); + + return e.e; + }); + + CHECK_TRUE(error_generated); + CHECK_EQUAL("temp_const_error", unexpected_out.error()); + } + + TEST(test_transform_error_void_value) { + ExpectedV expected; + ExpectedV expected_error = UnexpectedV(Error("transform_error_void_value")); + bool executed {false}; + + auto expected_out = expected.transform_error([&executed](const Error& e) { + executed = true; + return e.e; + }); + + CHECK_FALSE(executed); + CHECK_TRUE(expected_out.has_value()); + + auto with_value_type_check = check_expected_type_helper(expected_out); + CHECK_TRUE(with_value_type_check); + + auto unexpected_out = expected_error.transform_error([&executed](const Error& e) { + executed = true; + auto s = e.e; + return s.append("_transformed"); + }); + + CHECK_TRUE(executed); + CHECK_EQUAL("transform_error_void_value_transformed", unexpected_out.error()); + + auto with_error_type_check = check_expected_type_helper(unexpected_out); + CHECK_TRUE(with_error_type_check); + + } + }; } diff --git a/test/test_invoke.cpp b/test/test_invoke.cpp new file mode 100644 index 00000000..4c06d926 --- /dev/null +++ b/test/test_invoke.cpp @@ -0,0 +1,184 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "unit_test_framework.h" + +#include "etl/invoke.h" +#include + +namespace +{ + struct TestClass + { + int member_obj = 42; + std::string member_str = "hello"; + + int get_int() + { + return member_obj; + } + + int const_get_int() const + { + return member_obj + 10; + } + void set_int(int v) + { + member_obj = v; + } + static int static_func(int x) + { + return x * 2; + } + }; + + int standalone_func(int a, int b) + { + return a + b; + } + + struct Functor + { + int operator()(int x) const + { + return x * 5; + } + }; + + SUITE(test_invoke) + { + //************************************************************************* + TEST(test_type_traits_functions) + { + CHECK_TRUE(etl::is_function::value); + CHECK_TRUE(!etl::is_function::value); + CHECK_TRUE(!etl::is_function::value); + CHECK_TRUE(!etl::is_function::value); + CHECK_TRUE(!etl::is_function::value); + CHECK_TRUE(!etl::logical_not_t::value); + CHECK_TRUE(etl::logical_not_t::value); + } + + //************************************************************************* + TEST(test_type_traits_member_pointers) + { + using MemObjPtr = int TestClass::*; + using MemFnPtr = int (TestClass::*)(); + + CHECK_TRUE(etl::is_member_pointer::value); + CHECK_TRUE(etl::is_member_pointer::value); + CHECK_TRUE(!etl::is_member_pointer::value); + + CHECK_TRUE(etl::is_member_object_pointer::value); + CHECK_TRUE(!etl::is_member_object_pointer::value); + + CHECK_TRUE(!etl::is_member_function_pointer::value); + CHECK_TRUE(etl::is_member_function_pointer::value); + } + + //************************************************************************* + TEST(test_invoke_callable) + { + CHECK_EQUAL(30, etl::invoke(standalone_func, 10, 20)); + + auto lambda = [](int x) + { return x * 3; }; + CHECK_EQUAL(15, etl::invoke(lambda, 5)); + + Functor f; + CHECK_EQUAL(60, etl::invoke(f, 12)); + + CHECK_EQUAL(8, etl::invoke(TestClass::static_func, 4)); + } + + //************************************************************************* + TEST(test_invoke_mem_func_ptr) + { + TestClass obj; + TestClass* ptr = &obj; + const TestClass const_obj; + + CHECK_EQUAL(42, etl::invoke(&TestClass::get_int, obj)); + CHECK_EQUAL(42, etl::invoke(&TestClass::get_int, ptr)); + CHECK_EQUAL(52, etl::invoke(&TestClass::const_get_int, const_obj)); + + etl::invoke(&TestClass::set_int, obj, 99); + CHECK_EQUAL(99, obj.member_obj); + + etl::invoke(&TestClass::set_int, ptr, 101); + CHECK_EQUAL(101, ptr->member_obj); + } + + //************************************************************************* + TEST(test_invoke_mem_obj_ptr) + { + TestClass obj; + TestClass* ptr = &obj; + + CHECK_EQUAL(42, etl::invoke(&TestClass::member_obj, obj)); + CHECK_EQUAL(42, etl::invoke(&TestClass::member_obj, ptr)); + CHECK_EQUAL("hello", etl::invoke(&TestClass::member_str, obj)); + + etl::invoke(&TestClass::member_obj, obj) = 1000; + CHECK_EQUAL(1000, obj.member_obj); + + etl::invoke(&TestClass::member_obj, ptr) = 2000; + CHECK_EQUAL(2000, ptr->member_obj); + } + + //************************************************************************* + TEST(test_invoke_result_t) + { + using MemFnPtr = decltype(&TestClass::get_int); + using ConstMemFnPtr = decltype(&TestClass::const_get_int); + using MemObjPtr_int = decltype(&TestClass::member_obj); + using FnPtr = int (*)(int, int); + + auto val = etl::is_same, int>::value; + CHECK_TRUE(val); + + val = etl::is_same, int>::value; + CHECK_TRUE(val); + + val = etl::is_same, int>::value; + CHECK_TRUE(val); + + val = etl::is_same, int>::value; + CHECK_TRUE(val); + + val = etl::is_same, int&>::value; + CHECK_TRUE(val); + + val = etl::is_same, const int&>::value; + CHECK_TRUE(val); + + val = etl::is_same, int&>::value; + CHECK_TRUE(val); + } + } +} \ No newline at end of file From 552e0f8b90f677d5677427b4c00d19fa23f235dd Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 18 Dec 2025 16:11:35 +0000 Subject: [PATCH 041/298] Formatting updates --- test/test_expected.cpp | 76 ++++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/test/test_expected.cpp b/test/test_expected.cpp index 9bfc5650..70f5812a 100644 --- a/test/test_expected.cpp +++ b/test/test_expected.cpp @@ -816,7 +816,6 @@ namespace template bool check_expected_type_helper(TExpected& expected) { - bool value_type_ok = value_type_helper::check(expected); bool error_type_ok = etl::is_same::type, TError>::value; @@ -827,7 +826,6 @@ namespace } //************************************************************************* - TEST(test_or_else) { Expected expected = {Value("or_else_with_value")}; @@ -893,8 +891,8 @@ namespace } //************************************************************************* - - TEST(test_or_else_move_constructor) { + TEST(test_or_else_move_constructor) + { ExpectedM expected = ExpectedM(ValueM("or_else_with_value")); ExpectedM expected_error = ExpectedM(UnexpectedM(ErrorM("or_else_with_error"))); bool error_generated {false}; @@ -938,8 +936,8 @@ namespace } //************************************************************************* - - TEST(test_or_else_void) { + TEST(test_or_else_void) + { ExpectedV expected = ExpectedV(); ExpectedV expected_error = ExpectedV(Unexpected(Error("or_else_with_error"))); bool error_generated {false}; @@ -971,8 +969,8 @@ namespace } //************************************************************************* - - TEST(test_or_else_change_error) { + TEST(test_or_else_change_error) + { Expected expected_error = {Unexpected(Error("or_else_with_error"))}; ExpectedV expectedV_error = ExpectedV(Unexpected(Error("or_else_with_error"))); @@ -987,8 +985,8 @@ namespace } //************************************************************************* - - TEST(test_or_else_change_error_move_constructor) { + TEST(test_or_else_change_error_move_constructor) + { ExpectedM expected_error = ExpectedM(UnexpectedM(ErrorM("or_else_with_error"))); auto change_to_string = etl::move(expected_error).or_else([](ErrorM e) -> etl::expected { @@ -1002,8 +1000,8 @@ namespace } //************************************************************************* - - TEST(test_or_else_const_rvalue) { + TEST(test_or_else_const_rvalue) + { bool error_generated {false}; auto temp_expected = Expected(Unexpected(Error("temp_const_error"))); @@ -1019,8 +1017,8 @@ namespace } //************************************************************************* - - TEST(test_transform) { + TEST(test_transform) + { Expected expected = {Value("transform_with_value")}; Expected expected_error = {Unexpected(Error("transform_with_error"))}; const Expected expected_const = {Value("const_transform_with_value")}; @@ -1062,8 +1060,8 @@ namespace } //************************************************************************* - - TEST(test_transform_move_constructor) { + TEST(test_transform_move_constructor) + { ExpectedM expected = {ValueM("transform_with_value")}; ExpectedM expected_error = ExpectedM(UnexpectedM(ErrorM("transform_with_error"))); @@ -1092,8 +1090,8 @@ namespace } //************************************************************************* - - TEST(test_transform_void) { + TEST(test_transform_void) + { ExpectedV expected; ExpectedV expected_error = {Unexpected(Error("transform_with_error"))}; @@ -1150,8 +1148,8 @@ namespace } //************************************************************************* - - TEST(test_transform_to_void) { + TEST(test_transform_to_void) + { Expected expected {Value("transform_to_void")}; bool executed {false}; @@ -1168,9 +1166,9 @@ namespace CHECK_TRUE(expected_out.has_value()); } - //************************************************************************* - - TEST(test_and_then) { + //************************************************************************* + TEST(test_and_then) + { Expected expected = {Value("and_then_with_value")}; Expected expected_error = {Unexpected(Error("and_then_with_error"))}; const Expected expected_const = {Value("const_and_then_with_value")}; @@ -1209,8 +1207,8 @@ namespace } //************************************************************************* - - TEST(test_and_then_move_constructor) { + TEST(test_and_then_move_constructor) + { ExpectedM expected = ExpectedM(ValueM("and_then_with_value")); ExpectedM expected_error = ExpectedM(UnexpectedM(ErrorM("and_then_with_error"))); @@ -1236,9 +1234,9 @@ namespace CHECK_EQUAL("and_then_with_error", unexpected_out.error().e); } - //************************************************************************* - - TEST(test_and_then_void) { + //************************************************************************* + TEST(test_and_then_void) + { ExpectedV expected; ExpectedV expected_error = {Unexpected(Error("and_then_with_error"))}; auto and_thened {false}; @@ -1268,7 +1266,9 @@ namespace CHECK_EQUAL("and_then_with_error", unexpected_out.error().e); } - TEST(test_and_then_void_move) { + //************************************************************************* + TEST(test_and_then_void_move) + { ExpectedVM expected; ExpectedVM expected_error = {UnexpectedM(ErrorM("and_then_with_error"))}; auto and_thened {false}; @@ -1299,8 +1299,8 @@ namespace } //************************************************************************* - - TEST(test_transform_error) { + TEST(test_transform_error) + { Expected expected = {Value("transform_error_with_value")}; Expected expected_error = {Unexpected(Error("transform_error_with_error"))}; @@ -1329,8 +1329,8 @@ namespace } //************************************************************************* - - TEST(test_transform_error_move_constructor) { + TEST(test_transform_error_move_constructor) + { ExpectedM expected = ExpectedM(ValueM("transform_error_with_value")); ExpectedM expected_error = ExpectedM(UnexpectedM(ErrorM("transform_error_with_error"))); @@ -1358,7 +1358,9 @@ namespace CHECK_EQUAL("transform_error_with_error_transformed", unexpected_out.error()); } - TEST(test_transform_error_const_rvalue) { + //************************************************************************* + TEST(test_transform_error_const_rvalue) + { bool error_generated {false}; auto temp_expected = Expected(Unexpected(Error("temp_const_error"))); @@ -1374,7 +1376,9 @@ namespace CHECK_EQUAL("temp_const_error", unexpected_out.error()); } - TEST(test_transform_error_void_value) { + //************************************************************************* + TEST(test_transform_error_void_value) + { ExpectedV expected; ExpectedV expected_error = UnexpectedV(Error("transform_error_void_value")); bool executed {false}; @@ -1403,5 +1407,5 @@ namespace CHECK_TRUE(with_error_type_check); } - }; + } } From 1ac82dc83eb364e25de8e24a0d0bbd8fdc0bd304 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Fri, 19 Dec 2025 08:26:07 +0000 Subject: [PATCH 042/298] Updated invoke.h from the code in the inplace_function branch --- include/etl/invoke.h | 339 +++++++++++++++++++++++++++++++------------ 1 file changed, 250 insertions(+), 89 deletions(-) diff --git a/include/etl/invoke.h b/include/etl/invoke.h index 67606e26..3f86350c 100644 --- a/include/etl/invoke.h +++ b/include/etl/invoke.h @@ -36,113 +36,274 @@ SOFTWARE. #include "function_traits.h" #include "type_traits.h" #include "utility.h" +#include "type_list.h" -namespace etl { - template struct logical_not_t : etl::integral_constant {}; +#if ETL_USING_CPP11 - /// is T a function -- a function cannot be const qualified like a variable - template struct is_function : public etl::integral_constant::value> { }; - template struct is_function : public etl::false_type { }; - template struct is_function : public etl::false_type { }; +namespace etl +{ + //**************************************************************************** + // invoke implementation + //**************************************************************************** - /// is T a member pointer - template struct is_member_pointer_helper : etl::false_type {}; - template struct is_member_pointer_helper : etl::true_type {}; - template struct is_member_pointer : is_member_pointer_helper> {}; - - /// is T a member function pointer - template struct is_member_function_pointer_helper : etl::false_type {}; - template struct is_member_function_pointer_helper : public etl::is_function::type {}; - template struct is_member_function_pointer : public is_member_function_pointer_helper>::type {}; - - /// is T a member object pointer - template struct is_member_object_pointer_helper : public etl::false_type { }; - template struct is_member_object_pointer_helper : public logical_not_t>::type { }; - template struct is_member_object_pointer : public is_member_object_pointer_helper>::type {}; - - template < - typename F, - typename ... TArgs, - typename = typename etl::enable_if< - !etl::is_member_pointer>::value>::type - > - ETL_CONSTEXPR auto invoke(F&& f, TArgs&& ... args) - -> decltype(etl::forward(f)(etl::forward(args)...)) { - return etl::forward(f)(etl::forward(args)...); - } - - template < - typename F, - typename T, - typename... TArgs, - typename = typename etl::enable_if< - etl::is_member_function_pointer>::value && - !etl::is_pointer>::value - >::type - > - ETL_CONSTEXPR auto invoke(F&& f, T&& t, TArgs&&... args) - -> decltype((etl::forward(t).*f)(etl::forward(args)...)) + //**************************************************************************** + /// Pointer to member function + reference_wrapper + template >::value && + etl::is_reference_wrapper>::value>> + ETL_CONSTEXPR auto invoke(TFunction&& f, TRefWrapper&& ref_wrapper, TArgs&&... args) + -> decltype((ref_wrapper.get().*f)(etl::forward(args)...)) { - return (etl::forward(t).*f)(etl::forward(args)...); + return (ref_wrapper.get().*f)(etl::forward(args)...); } - template < - typename F, - typename T, - typename ... TArgs, - typename = typename etl::enable_if< - etl::is_member_function_pointer>::value && - etl::is_pointer>::value - >::type - > - ETL_CONSTEXPR auto invoke(F&& f, T&& t, TArgs&&... args) - -> decltype(((*etl::forward(t)).*f)(etl::forward(args)...)) + //**************************************************************************** + /// Pointer to member function + pointer to object + template >::value && + etl::is_pointer>::value>> + ETL_CONSTEXPR auto invoke(TFunction&& f, TPtr&& ptr, TArgs&&... args) + -> decltype(((*etl::forward(ptr)).*f)(etl::forward(args)...)) { - return ((*etl::forward(t)).*f)(etl::forward(args)...); + return ((*etl::forward(ptr)).*f)(etl::forward(args)...); } - template < - typename F, - typename T, - typename = typename etl::enable_if< - etl::is_member_object_pointer>::value && - !etl::is_pointer>::value - >::type - > - ETL_CONSTEXPR auto invoke(F&& f, T&& t) - -> decltype(etl::forward(t).*f) + //**************************************************************************** + /// Pointer to member function + object (or derived) reference + template >::value && + !etl::is_pointer>::value && + !is_reference_wrapper>::value>> + ETL_CONSTEXPR auto invoke(TFunction&& f, TObject&& obj, TArgs&&... args) + -> decltype((etl::forward(obj).*f)(etl::forward(args)...)) { - return etl::forward(t).*f; + return (etl::forward(obj).*f)(etl::forward(args)...); } - template < - typename F, - typename T, - typename = typename etl::enable_if< - etl::is_member_object_pointer>::value && - etl::is_pointer>::value - >::type - > - ETL_CONSTEXPR auto invoke(F&& f, T&& t) - -> decltype(((*etl::forward(t)).*f)) + //**************************************************************************** + /// Pointer to member object + reference_wrapper + template >::value && + etl::is_reference_wrapper>::value>> + ETL_CONSTEXPR auto invoke(TFunction&& f, TRefWrapper&& ref_wrapper) + -> decltype(ref_wrapper.get().*f) { - return ((*etl::forward(t)).*f); + return ref_wrapper.get().*f; } - template struct invoke_result; + //**************************************************************************** + /// Pointer to member object + pointer to object + template >::value && + etl::is_pointer>::value>> + ETL_CONSTEXPR auto invoke(TFunction&& f, TPtr&& ptr) + -> decltype(((*etl::forward(ptr)).*f)) + { + return ((*etl::forward(ptr)).*f); + } - template - struct invoke_result< - F, - etl::void_t(), etl::declval()...))>, - Us... - > { - using type = decltype(etl::invoke(etl::declval(), etl::declval()...)); + //**************************************************************************** + /// Pointer to member object + object (or derived) reference + template >::value && + !etl::is_pointer>::value && + !is_reference_wrapper>::value>> + ETL_CONSTEXPR auto invoke(TFunction&& f, TObject&& obj) + -> decltype(etl::forward(obj).*f) + { + return etl::forward(obj).*f; + } + + //**************************************************************************** + /// General callable (function object / lambda / function pointer) + template >::value>> + ETL_CONSTEXPR auto invoke(TFunction&& f, TArgs&&... args) + -> decltype(etl::forward(f)(etl::forward(args)...)) + { + return etl::forward(f)(etl::forward(args)...); + } + + //**************************************************************************** + // is_invocable implementation + //**************************************************************************** + namespace private_invoke + { + //******************************************* + // Core detection of invocability. + // Succeeds if the invocation expression is well-formed. + template + struct is_invocable_expr + { + template + static auto test(int) -> decltype((void)etl::invoke(etl::declval(), etl::declval()...), etl::true_type{}); + + template + static etl::false_type test(...); + + using type = decltype(test(0)); + + static ETL_CONSTANT bool value = type::value; + }; + + //******************************************* + // Core detection of invocability. + // Succeeds if the invocation expression is well-formed. + // Using etl::type_list for the argument list. + template + struct is_invocable_expr> + { + template + static auto test(int) -> decltype((void)etl::invoke(etl::declval(), etl::declval()...), etl::true_type{}); + + template + static etl::false_type test(...); + + using type = decltype(test(0)); + + static ETL_CONSTANT bool value = type::value; + }; + + //******************************************* + // Map raw function type to pointer. + template + using effective_callable_t = etl::conditional_t>::value, + etl::add_pointer_t>, + TFunction>; + } + + //**************************************************************************** + /// invoke_result + template + struct invoke_result; + + template + struct invoke_result(), etl::declval()...))>, + TArgs...> + { + using type = decltype(etl::invoke(etl::declval(), etl::declval()...)); }; - template - using invoke_result_t = typename invoke_result::type; + template + using invoke_result_t = typename invoke_result::type; + + //**************************************************************************** + /// is_invocable + template + struct is_invocable + : etl::bool_constant, TArgs...>::value> + { + }; + + //**************************************************************************** + // Specialization to allow `etl::type_list<...>` as the second template parameter. + template + struct is_invocable> + : is_invocable + { + }; + + //**************************************************************************** + // is_invocable_r + template + struct is_invocable_r + : etl::conditional_t::value, + etl::is_invocable, + etl::conditional_t::value, + etl::bool_constant, TReturn>::value>, + etl::false_type>> + { + }; + + //**************************************************************************** + // Specialization to allow `etl::type_list<...>` as the second template parameter. + template + struct is_invocable_r> + : is_invocable_r + { + }; + + //**************************************************************************** + // Specialization to allow `etl::type_list<...>` when there is a preceding object argument. + template + struct is_invocable> + : is_invocable + { + }; + + //**************************************************************************** + // Specialization for is_invocable_r with a preceding object argument. + template + struct is_invocable_r> + : is_invocable_r + { + }; + +#if ETL_USING_CPP17 + //**************************************************************************** + /// is_nothrow_invocable + template + struct is_nothrow_invocable + : etl::bool_constant::value && + etl::function_traits>::is_noexcept> + { + }; + + //**************************************************************************** + /// is_nothrow_invocable_r + template + struct is_nothrow_invocable_r + : etl::bool_constant::value && + etl::function_traits>::is_noexcept && + (etl::is_same::value || + etl::is_nothrow_convertible, TReturn>::value)> + { + }; + + //**************************************************************************** + /// is_nothrow_invocable_r> + template + struct is_nothrow_invocable_r> + : etl::bool_constant::value && + etl::function_traits>::is_noexcept && + (etl::is_same::value || + etl::is_nothrow_convertible, TReturn>::value)> + { + }; + + //**************************************************************************** + // Specialization to allow `etl::type_list<...>` when there is a preceding object argument + // for the nothrow-with-return trait. + template + struct is_nothrow_invocable_r> + : is_nothrow_invocable_r + {}; +#endif + +#if ETL_USING_CPP17 + template + inline constexpr bool is_invocable_v = is_invocable::value; + + template + inline constexpr bool is_invocable_r_v = is_invocable_r::value; + template + inline constexpr bool is_nothrow_invocable_v = is_nothrow_invocable::value; + + template + inline constexpr bool is_nothrow_invocable_r_v = is_nothrow_invocable_r::value; +#endif } -#endif +#endif // ETL_USING_CPP11 +#endif // ETL_INVOKE_INCLUDED From 054fca0e254379b5a0e7e03a28adab1eca7a9e9a Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Fri, 19 Dec 2025 08:26:27 +0000 Subject: [PATCH 043/298] Updated functional.h from the code in the inplace_function branch --- include/etl/functional.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/etl/functional.h b/include/etl/functional.h index 9f7f811d..0f0172ec 100644 --- a/include/etl/functional.h +++ b/include/etl/functional.h @@ -143,6 +143,21 @@ namespace etl using unwrap_ref_decay_t = typename unwrap_ref_decay::type; #endif + //*************************************************************************** + // is_reference_wrapper + // Detect etl::reference_wrapper + //*************************************************************************** + template + struct is_reference_wrapper : etl::false_type {}; + + template + struct is_reference_wrapper > : etl::true_type {}; + +#if ETL_USING_CPP17 + template + inline constexpr bool is_reference_wrapper_v = is_reference_wrapper::value; +#endif + //*************************************************************************** /// unary_function //*************************************************************************** From 1f1e2c54c39edda603e883e610dc8f9a6f184e21 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Fri, 19 Dec 2025 08:27:06 +0000 Subject: [PATCH 044/298] Updated VS2022 project to include invoke.h --- test/vs2022/etl.vcxproj | 1 + 1 file changed, 1 insertion(+) diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 095d407d..42e8bee6 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -3542,6 +3542,7 @@ + From 702dda43735fb3deb612a00a844fe367ffc0bcfb Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 20 Dec 2025 09:39:50 +0000 Subject: [PATCH 045/298] Synchronised etl::invoke_result with that in the etl::inplace_function branch --- include/etl/invoke.h | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/include/etl/invoke.h b/include/etl/invoke.h index 3f86350c..efd0dc07 100644 --- a/include/etl/invoke.h +++ b/include/etl/invoke.h @@ -183,19 +183,34 @@ namespace etl //**************************************************************************** /// invoke_result - template - struct invoke_result; + template + struct invoke_result + { + using type = void; + }; + //******************************************* template struct invoke_result(), etl::declval()...))>, - TArgs...> + TArgs...> { using type = decltype(etl::invoke(etl::declval(), etl::declval()...)); }; + //******************************************* + // Specialization to allow `etl::type_list<...>` as the second template parameter. template - using invoke_result_t = typename invoke_result::type; + struct invoke_result(), etl::declval()...))>, + etl::type_list> + { + using type = decltype(etl::invoke(etl::declval(), etl::declval()...)); + }; + + //******************************************* + template + using invoke_result_t = typename invoke_result::type; //**************************************************************************** /// is_invocable From 8d2f91de9fe743d7d5510b47c80e484c631aea81 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 20 Dec 2025 10:19:24 +0000 Subject: [PATCH 046/298] Updated test_invoke --- test/test_invoke.cpp | 2 -- test/vs2022/etl.vcxproj | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/test/test_invoke.cpp b/test/test_invoke.cpp index 4c06d926..4e4bf10b 100644 --- a/test/test_invoke.cpp +++ b/test/test_invoke.cpp @@ -80,8 +80,6 @@ namespace CHECK_TRUE(!etl::is_function::value); CHECK_TRUE(!etl::is_function::value); CHECK_TRUE(!etl::is_function::value); - CHECK_TRUE(!etl::logical_not_t::value); - CHECK_TRUE(etl::logical_not_t::value); } //************************************************************************* diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 42e8bee6..91113892 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -10304,6 +10304,7 @@ + From b2a4b4410c006ea5d52ef60c76bd34d9628870d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20R=C3=BCthing?= Date: Sat, 13 Dec 2025 09:26:25 +0100 Subject: [PATCH 047/298] Spare more Resources for non-verbose Errors (#1214) * Spare more Resources for non-verbose Errors At the moment we only remove the __FILE__ in case ETL_VERBOSE_ERRORS is not set. However, we also want to remove the error text which can consume quite some resources and without the file name the line number is also not very useful. * Introduce separate ETL_MINIMAL_ERRORS to keep backwards compatability To not break runtime backwards compatability, instead of removing the text in case of ETL_VERBOSE_ERRORS not defined, we introduce a second flag ETL_MINIMAL_ERRORS which is mutually exclusive. The semantic is as follows: - ETL_VERBOSE_ERRORS: We use verbose text, file names and line numbers. - ETL_MINIMAL_ERRORS: We do not use anything. - ETL_VERBOSE_ERRORS and ETL_MINIMAL_ERRORS: Issue an error. - non defined: We use terse text without file names nor line numbers. --------- Co-authored-by: John Wellbelove --- include/etl/error_handler.h | 24 ++++++++++++++++-------- include/etl/exception.h | 36 ++++++++++++++++++++++++------------ include/etl/platform.h | 6 ++++++ 3 files changed, 46 insertions(+), 20 deletions(-) diff --git a/include/etl/error_handler.h b/include/etl/error_handler.h index 425f68ef..2fb10011 100644 --- a/include/etl/error_handler.h +++ b/include/etl/error_handler.h @@ -397,15 +397,23 @@ namespace etl //************************************* #if defined(ETL_VERBOSE_ERRORS) - #define ETL_ERROR(e) (e(__FILE__, __LINE__)) // Make an exception with the file name and line number. - #define ETL_ERROR_WITH_VALUE(e, v) (e(__FILE__, __LINE__, (v))) // Make an exception with the file name, line number and value. - #define ETL_ERROR_TEXT(verbose_text, terse_text) (verbose_text) // Use the verbose text. - #define ETL_ERROR_GENERIC(text) (etl::exception((text),__FILE__, __LINE__)) // Make a generic exception with a message, file name and line number. + // include everything, file name, line number, verbose text + #define ETL_ERROR(e) (e(__FILE__, __LINE__)) + #define ETL_ERROR_WITH_VALUE(e, v) (e(__FILE__, __LINE__, (v))) + #define ETL_ERROR_TEXT(verbose_text, terse_text) (verbose_text) + #define ETL_ERROR_GENERIC(text) (etl::exception((text), __FILE__, __LINE__)) +#elif defined(ETL_MINIMAL_ERRORS) + // include nothing, no file name, no line number, no text + #define ETL_ERROR(e) (e("", -1)) + #define ETL_ERROR_WITH_VALUE(e, v) (e("", -1, (v))) + #define ETL_ERROR_TEXT(verbose_text, terse_text) ("") + #define ETL_ERROR_GENERIC(text) (etl::exception("", "", -1)) #else - #define ETL_ERROR(e) (e("", __LINE__)) // Make an exception with the line number. - #define ETL_ERROR_WITH_VALUE(e, v) (e("", __LINE__, (v))) // Make an exception with the file name, line number and value. - #define ETL_ERROR_TEXT(verbose_text, terse_text) (terse_text) // Use the terse text. - #define ETL_ERROR_GENERIC(text) (etl::exception((text),"", __LINE__)) // Make a generic exception with a message and line number. + // include only terse text, no file name, no line number + #define ETL_ERROR(e) (e("", -1)) + #define ETL_ERROR_WITH_VALUE(e, v) (e("", -1, (v))) + #define ETL_ERROR_TEXT(verbose_text, terse_text) (terse_text) + #define ETL_ERROR_GENERIC(text) (etl::exception((text),"", -1)) #endif #endif diff --git a/include/etl/exception.h b/include/etl/exception.h index 4323df78..c73fef1c 100644 --- a/include/etl/exception.h +++ b/include/etl/exception.h @@ -60,26 +60,27 @@ namespace etl typedef const char* string_type; typedef int numeric_type; - -#if defined(ETL_VERBOSE_ERRORS) + //************************************************************************* /// Constructor. //************************************************************************* - ETL_EXCEPTION_CONSTEXPR +#if defined(ETL_VERBOSE_ERRORS) + ETL_CONSTEXPR exception(string_type reason_, string_type file_, numeric_type line_) : reason_text(reason_), file_text(file_), line(line_) { } +#elif defined(ETL_MINIMAL_ERRORS) + ETL_CONSTEXPR + exception(string_type /*reason_*/, string_type /*file_*/, numeric_type /*line_*/) + { + } #else - //************************************************************************* - /// Constructor. - //************************************************************************* - ETL_EXCEPTION_CONSTEXPR - exception(string_type reason_, string_type /*file_*/, numeric_type line_) - : reason_text(reason_), - line(line_) + ETL_CONSTEXPR + exception(string_type reason_, string_type /*file_*/, numeric_type /*line_*/) + : reason_text(reason_) { } #endif @@ -94,7 +95,11 @@ namespace etl override #endif { +#if !defined(ETL_MINIMAL_ERRORS) return reason_text; +#else + return ""; +#endif } @@ -119,16 +124,23 @@ namespace etl ETL_CONSTEXPR numeric_type line_number() const { +#if defined(ETL_VERBOSE_ERRORS) return line; +#else + return -1; +#endif } private: - string_type reason_text; ///< The reason for the exception. +#if !defined(ETL_MINIMAL_ERRORS) + string_type reason_text; ///< The reason for the exception. +#endif + #if defined(ETL_VERBOSE_ERRORS) string_type file_text; ///< The file for the exception. -#endif numeric_type line; ///< The line for the exception. +#endif }; } diff --git a/include/etl/platform.h b/include/etl/platform.h index 62a5da60..116daeb4 100644 --- a/include/etl/platform.h +++ b/include/etl/platform.h @@ -83,6 +83,12 @@ SOFTWARE. #define ETL_IS_DEBUG_BUILD 0 #endif +//************************************* +// Do a validity check for error settings, only one is allowed. +#if defined(ETL_VERBOSE_ERRORS) && defined(ETL_MINIMAL_ERRORS) + #error "ETL_VERBOSE_ERRORS and ETL_MINIMAL_ERRORS are mutually exclusive" +#endif + //************************************* // Helper macros, so we don't have to use double negatives. // The ETL will use the STL, unless ETL_NO_STL is defined. From e85d29b1dd077b5653a486fa7b06644874b3a3a7 Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Sat, 13 Dec 2025 09:07:06 +0100 Subject: [PATCH 048/298] Added concepts.h and tests (#1213) --- include/etl/concepts.h | 132 +++++++++ .../etl/generators/type_traits_generator.h | 270 ++++++++++++++++-- include/etl/type_traits.h | 270 ++++++++++++++++-- test/CMakeLists.txt | 1 + test/test_concepts.cpp | 141 +++++++++ test/test_type_traits.cpp | 3 + 6 files changed, 781 insertions(+), 36 deletions(-) create mode 100644 include/etl/concepts.h create mode 100644 test/test_concepts.cpp diff --git a/include/etl/concepts.h b/include/etl/concepts.h new file mode 100644 index 00000000..e1555871 --- /dev/null +++ b/include/etl/concepts.h @@ -0,0 +1,132 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 BMW AG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_CONCEPTS_INCLUDED +#define ETL_CONCEPTS_INCLUDED + +#include "platform.h" + +#include "utility.h" +#include "type_traits.h" + +#if ETL_USING_CPP20 + +#if ETL_USING_STL + #include +#endif + +namespace etl +{ + +#if ETL_USING_STL + + using std::same_as; + using std::derived_from; + using std::convertible_to; + using std::common_reference_with; + using std::common_with; + using std::integral; + using std::signed_integral; + using std::unsigned_integral; + using std::floating_point; + using std::assignable_from; + +#else // not ETL_USING_STL + + namespace private_concepts + { + template + concept same_as_helper = etl::is_same_v; + } + + template + concept same_as = private_concepts::same_as_helper && private_concepts::same_as_helper; + + template + concept derived_from = + etl::is_base_of_v && + etl::is_convertible_v; + + template + concept convertible_to = + etl::is_convertible_v && + requires { + static_cast(etl::declval()); + }; + + template< class T, class U > + concept common_reference_with = + etl::same_as, etl::common_reference_t> && + etl::convertible_to> && + etl::convertible_to>; + + template + concept common_with = + etl::same_as, etl::common_type_t> && + requires { + static_cast>(etl::declval()); + static_cast>(etl::declval()); + } && + etl::common_reference_with< + etl::add_lvalue_reference_t, + etl::add_lvalue_reference_t> && + etl::common_reference_with< + etl::add_lvalue_reference_t>, + etl::common_reference_t< + etl::add_lvalue_reference_t, + etl::add_lvalue_reference_t>>; + + template + concept integral = etl::is_integral_v; + + template + concept signed_integral = etl::integral && etl::is_signed_v; + + template + concept unsigned_integral = etl::integral && !etl::signed_integral; + + template + concept floating_point = etl::is_floating_point_v; + + template + concept assignable_from = + etl::is_lvalue_reference_v && + etl::common_reference_with< + const etl::remove_reference_t&, + const etl::remove_reference_t&> && + requires(LHS lhs, RHS&& rhs) { + { lhs = etl::forward(rhs) } -> etl::same_as; + }; + +#endif +} + +#endif +#endif diff --git a/include/etl/generators/type_traits_generator.h b/include/etl/generators/type_traits_generator.h index 43096f7b..68c937f8 100644 --- a/include/etl/generators/type_traits_generator.h +++ b/include/etl/generators/type_traits_generator.h @@ -652,8 +652,48 @@ namespace etl using decay_t = typename decay::type; #endif + //*************************************************************************** + /// is_class + namespace private_type_traits + { + template char test(int T::*); // Match for classes. + + struct dummy { char c[2]; }; + template dummy test(...); // Match for non-classes. + } + + template + struct is_class : etl::bool_constant(0)) == 1U> {}; + +#if ETL_USING_CPP17 + template + inline constexpr bool is_class_v = is_class::value; +#endif + //*************************************************************************** /// is_base_of +#if ETL_USING_CPP11 + namespace private_type_traits + { + template + etl::true_type test_ptr_conv(const volatile B*); + template + etl::false_type test_ptr_conv(const volatile void*); + + template + auto test_is_base_of(int) -> decltype(test_ptr_conv(static_cast(nullptr))); + template + auto test_is_base_of(...) -> etl::true_type; // private or ambiguous base + } + + template + struct is_base_of: etl::integral_constant< + bool, + etl::is_class::value && + etl::is_class::value && + decltype(private_type_traits::test_is_base_of(0))::value + > {}; +#else template::value || etl::is_fundamental::value || etl::is_array::value)> @@ -675,30 +715,13 @@ namespace etl { static const bool value = false; }; +#endif #if ETL_USING_CPP17 template inline constexpr bool is_base_of_v = is_base_of::value; #endif - //*************************************************************************** - /// is_class - namespace private_type_traits - { - template char test(int T::*); // Match for classes. - - struct dummy { char c[2]; }; - template dummy test(...); // Match for non-classes. - } - - template - struct is_class : etl::bool_constant(0)) == 1U> {}; - -#if ETL_USING_CPP17 - template - inline constexpr bool is_class_v = is_class::value; -#endif - //*************************************************************************** /// add_lvalue_reference template struct add_lvalue_reference { typedef T& type; }; @@ -2800,6 +2823,217 @@ typedef integral_constant true_type; template inline constexpr bool is_member_object_pointer_v = etl::is_member_object_pointer::value; #endif + +#if ETL_USING_CPP20 + template + struct common_reference; + + template + using common_reference_t = typename etl::common_reference::type; + + template class TQual, template class UQual> + struct basic_common_reference + { + }; + + // If sizeof...(T) is 0: no member + template <> + struct common_reference<> + { + }; + + // If sizeof...(T) is 1 + template + struct common_reference + { + using type = T; + }; + + namespace private_type_traits + { + template + using cond_res = decltype(false ? etl::declval()() : etl::declval()()); + + template + struct copy_cv + { + template + using apply = To; + }; + + template + struct copy_cv + { + template + using apply = const To; + }; + + template + struct copy_cv + { + template + using apply = volatile To; + }; + + template + struct copy_cv + { + template + using apply = const volatile To; + }; + + template + using copy_cv_t = typename copy_cv::template apply; + + template + struct copy_cvref + { + template + using apply = copy_cv_t; + }; + + template + struct copy_cvref + { + template + using apply = add_lvalue_reference_t>; + }; + + template + struct copy_cvref + { + template + using apply = add_lvalue_reference_t>; + }; + + template + using copy_cvref_t = typename copy_cvref::template apply; + + template + struct xref + { + template + using apply = copy_cvref_t; + }; + + template , class T2_RR = remove_reference_t> + struct common_ref; + + template + using common_ref_t = typename common_ref::type; + + template + using cv_cond_res = cond_res&, copy_cv_t&>; + + template + requires requires { typename cv_cond_res; } && + is_reference_v> + struct common_ref + { + using type = cv_cond_res; + }; + + template + using common_ref_rr = remove_reference_t>&&; + + template + requires requires { typename common_ref_rr; } && + is_convertible_v> && + is_convertible_v> + struct common_ref + { + using type = common_ref_rr; + }; + + template + using common_ref_cr = common_ref_t; + + template + requires requires { typename common_ref_cr; } && + is_convertible_v> + struct common_ref + { + using type = common_ref_cr; + }; + + template + struct common_ref: common_ref + { + }; + + template + struct common_ref + { + }; + + template + struct common_reference_impl3; + + template + struct common_reference_impl2: common_reference_impl3 + { + }; + + template + struct common_reference_impl1: common_reference_impl2 + { + }; + } + + // If sizeof...(T) is 2 + template + struct common_reference: private_type_traits::common_reference_impl1 + { + }; + + namespace private_type_traits + { + template + requires is_reference_v && is_reference_v && requires { typename common_ref_t; } && + is_convertible_v, add_pointer_t>> && + is_convertible_v, add_pointer_t>> + struct common_reference_impl1 + { + using type = common_ref_t; + }; + + template + using basic_common_reference_t = + typename basic_common_reference, + remove_cvref_t, + xref::template apply, + xref::template apply>::type; + + template + requires requires { typename basic_common_reference_t; } + struct common_reference_impl2 + { + using type = basic_common_reference_t; + }; + + template + requires requires { typename cond_res; } + struct common_reference_impl3 + { + using type = cond_res; + }; + + template + struct common_reference_impl3: common_type + { + }; + } + + template + requires requires { typename common_reference_t; } + struct common_reference : common_reference, T3, TArgs...> {}; + + template + struct common_reference + { + }; + +#endif } // Helper macros diff --git a/include/etl/type_traits.h b/include/etl/type_traits.h index dbb56fc0..26cd6aef 100644 --- a/include/etl/type_traits.h +++ b/include/etl/type_traits.h @@ -640,8 +640,48 @@ namespace etl using decay_t = typename decay::type; #endif + //*************************************************************************** + /// is_class + namespace private_type_traits + { + template char test(int T::*); // Match for classes. + + struct dummy { char c[2]; }; + template dummy test(...); // Match for non-classes. + } + + template + struct is_class : etl::bool_constant(0)) == 1U> {}; + +#if ETL_USING_CPP17 + template + inline constexpr bool is_class_v = is_class::value; +#endif + //*************************************************************************** /// is_base_of +#if ETL_USING_CPP11 + namespace private_type_traits + { + template + etl::true_type test_ptr_conv(const volatile B*); + template + etl::false_type test_ptr_conv(const volatile void*); + + template + auto test_is_base_of(int) -> decltype(test_ptr_conv(static_cast(nullptr))); + template + auto test_is_base_of(...) -> etl::true_type; // private or ambiguous base + } + + template + struct is_base_of: etl::integral_constant< + bool, + etl::is_class::value && + etl::is_class::value && + decltype(private_type_traits::test_is_base_of(0))::value + > {}; +#else template::value || etl::is_fundamental::value || etl::is_array::value)> @@ -663,30 +703,13 @@ namespace etl { static const bool value = false; }; +#endif #if ETL_USING_CPP17 template inline constexpr bool is_base_of_v = is_base_of::value; #endif - //*************************************************************************** - /// is_class - namespace private_type_traits - { - template char test(int T::*); // Match for classes. - - struct dummy { char c[2]; }; - template dummy test(...); // Match for non-classes. - } - - template - struct is_class : etl::bool_constant(0)) == 1U> {}; - -#if ETL_USING_CPP17 - template - inline constexpr bool is_class_v = is_class::value; -#endif - //*************************************************************************** /// add_lvalue_reference template struct add_lvalue_reference { typedef T& type; }; @@ -2793,6 +2816,217 @@ typedef integral_constant true_type; template inline constexpr bool is_member_object_pointer_v = etl::is_member_object_pointer::value; #endif + +#if ETL_USING_CPP20 + template + struct common_reference; + + template + using common_reference_t = typename etl::common_reference::type; + + template class TQual, template class UQual> + struct basic_common_reference + { + }; + + // If sizeof...(T) is 0: no member + template <> + struct common_reference<> + { + }; + + // If sizeof...(T) is 1 + template + struct common_reference + { + using type = T; + }; + + namespace private_type_traits + { + template + using cond_res = decltype(false ? etl::declval()() : etl::declval()()); + + template + struct copy_cv + { + template + using apply = To; + }; + + template + struct copy_cv + { + template + using apply = const To; + }; + + template + struct copy_cv + { + template + using apply = volatile To; + }; + + template + struct copy_cv + { + template + using apply = const volatile To; + }; + + template + using copy_cv_t = typename copy_cv::template apply; + + template + struct copy_cvref + { + template + using apply = copy_cv_t; + }; + + template + struct copy_cvref + { + template + using apply = add_lvalue_reference_t>; + }; + + template + struct copy_cvref + { + template + using apply = add_lvalue_reference_t>; + }; + + template + using copy_cvref_t = typename copy_cvref::template apply; + + template + struct xref + { + template + using apply = copy_cvref_t; + }; + + template , class T2_RR = remove_reference_t> + struct common_ref; + + template + using common_ref_t = typename common_ref::type; + + template + using cv_cond_res = cond_res&, copy_cv_t&>; + + template + requires requires { typename cv_cond_res; } && + is_reference_v> + struct common_ref + { + using type = cv_cond_res; + }; + + template + using common_ref_rr = remove_reference_t>&&; + + template + requires requires { typename common_ref_rr; } && + is_convertible_v> && + is_convertible_v> + struct common_ref + { + using type = common_ref_rr; + }; + + template + using common_ref_cr = common_ref_t; + + template + requires requires { typename common_ref_cr; } && + is_convertible_v> + struct common_ref + { + using type = common_ref_cr; + }; + + template + struct common_ref: common_ref + { + }; + + template + struct common_ref + { + }; + + template + struct common_reference_impl3; + + template + struct common_reference_impl2: common_reference_impl3 + { + }; + + template + struct common_reference_impl1: common_reference_impl2 + { + }; + } + + // If sizeof...(T) is 2 + template + struct common_reference: private_type_traits::common_reference_impl1 + { + }; + + namespace private_type_traits + { + template + requires is_reference_v && is_reference_v && requires { typename common_ref_t; } && + is_convertible_v, add_pointer_t>> && + is_convertible_v, add_pointer_t>> + struct common_reference_impl1 + { + using type = common_ref_t; + }; + + template + using basic_common_reference_t = + typename basic_common_reference, + remove_cvref_t, + xref::template apply, + xref::template apply>::type; + + template + requires requires { typename basic_common_reference_t; } + struct common_reference_impl2 + { + using type = basic_common_reference_t; + }; + + template + requires requires { typename cond_res; } + struct common_reference_impl3 + { + using type = cond_res; + }; + + template + struct common_reference_impl3: common_type + { + }; + } + + template + requires requires { typename common_reference_t; } + struct common_reference : common_reference, T3, TArgs...> {}; + + template + struct common_reference + { + }; + +#endif } // Helper macros diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ccfe9001..7866cd5d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -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 diff --git a/test/test_concepts.cpp b/test/test_concepts.cpp new file mode 100644 index 00000000..3d10b092 --- /dev/null +++ b/test/test_concepts.cpp @@ -0,0 +1,141 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 BMW AG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "unit_test_framework.h" + +#include "etl/concepts.h" + +#include +#include + +#if ETL_USING_CPP20 +namespace +{ + class A + {}; + + class B + {}; + + class C: public A + {}; + + class D: private A + {}; + + SUITE(test_concepts) + { + //************************************************************************* + TEST(test_same_as) + { + static_assert(etl::same_as == true); + static_assert(etl::same_as == false); + } + + //************************************************************************* + TEST(test_derived_from) + { + static_assert(etl::derived_from == true); + static_assert(etl::derived_from == false); + static_assert(etl::derived_from == true); + static_assert(etl::derived_from == false); + } + + //************************************************************************* + TEST(test_convertible_to) + { + static_assert(etl::convertible_to == true); + } + + //************************************************************************* + TEST(test_common_reference_with) + { + static_assert(etl::common_reference_with == true); + } + + //************************************************************************* + TEST(test_common_with) + { + static_assert(etl::common_with == true); + } + + //************************************************************************* + TEST(test_integral) + { + static_assert(etl::integral == true); + static_assert(etl::integral == true); + static_assert(etl::integral == false); + static_assert(etl::integral == false); + } + + //************************************************************************* + TEST(test_signed_integral) + { + static_assert(etl::signed_integral == false); + static_assert(etl::signed_integral == true); + static_assert(etl::signed_integral == false); + static_assert(etl::signed_integral == false); + static_assert(etl::signed_integral == false); + } + + //************************************************************************* + TEST(test_unsigned_integral) + { + static_assert(etl::unsigned_integral == true); + static_assert(etl::unsigned_integral == false); + static_assert(etl::unsigned_integral == true); + static_assert(etl::unsigned_integral == false); + static_assert(etl::unsigned_integral == false); + } + + //************************************************************************* + TEST(test_floating_point) + { + static_assert(etl::floating_point == false); + static_assert(etl::floating_point == false); + static_assert(etl::floating_point == false); + static_assert(etl::floating_point == true); + static_assert(etl::floating_point == true); + static_assert(etl::floating_point == true); + static_assert(etl::floating_point == false); + } + + //************************************************************************* + TEST(test_assignable_from) + { + static_assert(etl::assignable_from == true); + static_assert(etl::assignable_from == false); + static_assert(etl::assignable_from == true); + static_assert(etl::assignable_from == false); + static_assert(etl::assignable_from == false); + static_assert(etl::assignable_from == false); + static_assert(etl::assignable_from&, int> == false); + } + } +} +#endif diff --git a/test/test_type_traits.cpp b/test/test_type_traits.cpp index 3083343b..73d83c22 100644 --- a/test/test_type_traits.cpp +++ b/test/test_type_traits.cpp @@ -821,6 +821,7 @@ namespace struct A { }; struct B : public A { }; struct C { }; + struct D : private A { }; CHECK((std::is_base_of::value) == (etl::is_base_of::value)); CHECK((std::is_base_of::value) == (etl::is_base_of::value)); @@ -831,6 +832,8 @@ namespace CHECK((std::is_base_of::value) == (etl::is_base_of::value)); CHECK((std::is_base_of::value) == (etl::is_base_of::value)); CHECK((std::is_base_of::value) == (etl::is_base_of::value)); + CHECK((std::is_base_of::value) == (etl::is_base_of::value)); + CHECK((std::is_base_of::value) == (etl::is_base_of::value)); CHECK((std::is_base_of::value) == (etl::is_base_of::value)); CHECK((std::is_base_of::value) == (etl::is_base_of::value)); From a948ffe686b0013644a339ace3ba988d0c971251 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 18 Dec 2025 09:40:01 +0000 Subject: [PATCH 049/298] Added concepts.h to VS2022 project. Added concepts.h to syntax check CMakeLists.txt --- include/etl/concepts.h | 34 ++++++++++++++++++++---------- test/syntax_check/CMakeLists.txt | 1 + test/syntax_check/concepts.h.t.cpp | 28 ++++++++++++++++++++++++ test/vs2022/etl.vcxproj | 22 +++++++++++++++++++ 4 files changed, 74 insertions(+), 11 deletions(-) create mode 100644 test/syntax_check/concepts.h.t.cpp diff --git a/include/etl/concepts.h b/include/etl/concepts.h index e1555871..4e40783d 100644 --- a/include/etl/concepts.h +++ b/include/etl/concepts.h @@ -62,32 +62,37 @@ namespace etl namespace private_concepts { - template + template concept same_as_helper = etl::is_same_v; } - template + //*************************************************************************** + template concept same_as = private_concepts::same_as_helper && private_concepts::same_as_helper; - template + //*************************************************************************** + template concept derived_from = etl::is_base_of_v && etl::is_convertible_v; - template + //*************************************************************************** + template concept convertible_to = etl::is_convertible_v && requires { static_cast(etl::declval()); }; - template< class T, class U > + //*************************************************************************** + template< class T, typename U > concept common_reference_with = etl::same_as, etl::common_reference_t> && etl::convertible_to> && etl::convertible_to>; - template + //*************************************************************************** + template concept common_with = etl::same_as, etl::common_type_t> && requires { @@ -103,19 +108,24 @@ namespace etl etl::add_lvalue_reference_t, etl::add_lvalue_reference_t>>; - template + //*************************************************************************** + template concept integral = etl::is_integral_v; - template + //*************************************************************************** + template concept signed_integral = etl::integral && etl::is_signed_v; - template + //*************************************************************************** + template concept unsigned_integral = etl::integral && !etl::signed_integral; - template + //*************************************************************************** + template concept floating_point = etl::is_floating_point_v; - template + //*************************************************************************** + template concept assignable_from = etl::is_lvalue_reference_v && etl::common_reference_with< @@ -128,5 +138,7 @@ namespace etl #endif } +#else + #error This header requires C++20. Please set the compiler standard to at least C++20. #endif #endif diff --git a/test/syntax_check/CMakeLists.txt b/test/syntax_check/CMakeLists.txt index 17e36bff..6cedf381 100644 --- a/test/syntax_check/CMakeLists.txt +++ b/test/syntax_check/CMakeLists.txt @@ -114,6 +114,7 @@ target_sources(tests PRIVATE char_traits.h.t.cpp checksum.h.t.cpp chrono.h.t.cpp + concepts.h.t.cpp circular_buffer.h.t.cpp circular_iterator.h.t.cpp closure.h.t.cpp diff --git a/test/syntax_check/concepts.h.t.cpp b/test/syntax_check/concepts.h.t.cpp new file mode 100644 index 00000000..8b973c5b --- /dev/null +++ b/test/syntax_check/concepts.h.t.cpp @@ -0,0 +1,28 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 John Wellbelove +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 91113892..da763fab 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -3476,6 +3476,7 @@ + @@ -5133,6 +5134,26 @@ true true + + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true true @@ -10224,6 +10245,7 @@ + From fc951ff9e2011e8e902584c5e7fd38807ab2ce19 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 18 Dec 2025 16:14:23 +0000 Subject: [PATCH 050/298] Disabled header include if #include #if ETL_USING_CPP20 +#include "etl/concepts.h" + namespace { class A From f548cfc602d66d2c3125ee7f76c385938c4d1386 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Fri, 19 Dec 2025 07:37:24 +0000 Subject: [PATCH 051/298] Fixed C++ standard check for concepts --- include/etl/concepts.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/etl/concepts.h b/include/etl/concepts.h index 4e40783d..16be5b79 100644 --- a/include/etl/concepts.h +++ b/include/etl/concepts.h @@ -36,6 +36,10 @@ SOFTWARE. #include "utility.h" #include "type_traits.h" +#if ETL_NOT_USING_CPP20 && !defined(ETL_IN_UNIT_TEST) + #error NOT SUPPORTED FOR BELOW C++20 +#endif + #if ETL_USING_CPP20 #if ETL_USING_STL @@ -137,8 +141,5 @@ namespace etl #endif } - -#else - #error This header requires C++20. Please set the compiler standard to at least C++20. #endif #endif From 8c90eb8ba823206405d6324422abb1c5a99d7fa8 Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Sat, 13 Dec 2025 09:09:03 +0100 Subject: [PATCH 052/298] Add etl::format (#1204) * Synchronize on C++ 17 for "Windows - STL" and "Windows - No STL" MSVC C++20 handles char* differently on iteration * Add etl::format This adds etl::format, guided by std::format, avoiding dynamic memory allocation --- .github/workflows/msvc.yml | 2 +- include/etl/file_error_numbers.h | 1 + include/etl/format.h | 2244 ++++++++++++++++++++++++++++++ include/etl/print.h | 117 ++ test/CMakeLists.txt | 2 + test/test_format.cpp | 490 +++++++ test/test_print.cpp | 82 ++ 7 files changed, 2937 insertions(+), 1 deletion(-) create mode 100644 include/etl/format.h create mode 100644 include/etl/print.h create mode 100644 test/test_format.cpp create mode 100644 test/test_print.cpp diff --git a/.github/workflows/msvc.yml b/.github/workflows/msvc.yml index 466e8171..08180a9e 100644 --- a/.github/workflows/msvc.yml +++ b/.github/workflows/msvc.yml @@ -22,7 +22,7 @@ jobs: - name: Build run: | - cmake -G "Visual Studio 17 2022" -AWin32 -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=20 ./ + cmake -G "Visual Studio 17 2022" -AWin32 -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=17 ./ MSBuild.exe -version MSBuild.exe .\etl.sln diff --git a/include/etl/file_error_numbers.h b/include/etl/file_error_numbers.h index d6733308..b3e08814 100644 --- a/include/etl/file_error_numbers.h +++ b/include/etl/file_error_numbers.h @@ -109,4 +109,5 @@ SOFTWARE. #define ETL_ALGORITHM_FILE_ID "76" #define ETL_NOT_NULL_FILE_ID "77" #define ETL_SIGNAL_FILE_ID "78" +#define ETL_FORMAT_FILE_ID "79" #endif diff --git a/include/etl/format.h b/include/etl/format.h new file mode 100644 index 00000000..e65df98b --- /dev/null +++ b/include/etl/format.h @@ -0,0 +1,2244 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 BMW AG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_FORMAT_INCLUDED +#define ETL_FORMAT_INCLUDED + +#include "platform.h" + +#include "algorithm.h" +#include "array.h" +#include "array_view.h" +#include "error_handler.h" +#include "limits.h" +#include "math.h" +#include "optional.h" +#include "span.h" +#include "string.h" +#include "string_view.h" +#include "type_traits.h" +#include "utility.h" +#include "variant.h" +#include "visitor.h" + +#include + +#if ETL_USING_CPP11 + +namespace etl +{ + class format_exception : public etl::exception + { + public: + + format_exception(string_type reason_, string_type file_name_, numeric_type line_number_) + : exception(reason_, file_name_, line_number_) + { + } + }; + + class bad_format_string_exception : public etl::format_exception + { + public: + + bad_format_string_exception(string_type file_name_, numeric_type line_number_) + : etl::format_exception(ETL_ERROR_TEXT("format:bad", ETL_FORMAT_FILE_ID"A"), file_name_, line_number_) + { + } + }; + + template + ETL_CONSTEXPR14 bool check_f(const char* fmt) + { + // to be implemented later + //return fmt[0] == 0; // actual check + + (void)fmt; + return true; + } + + inline void please_note_this_is_error_message_1() noexcept {} + + template + struct basic_format_string + { + inline ETL_CONSTEVAL basic_format_string(const char* fmt) + : _sv(fmt) + { + bool format_string_ok = check_f(fmt); + + if (!format_string_ok) + { + //if (etl::is_constant_evaluated()) // compile time error path + //{ + // // calling a non-constexpr function in a consteval context to trigger a compile error + // please_note_this_is_error_message_1(); + //} + //else // run time error path + //{ + ETL_ASSERT_FAIL_AND_RETURN(ETL_ERROR(bad_format_string_exception)); + //} + } + } + + ETL_CONSTEXPR basic_format_string(const basic_format_string& other) = default; + ETL_CONSTEXPR14 basic_format_string& operator=(const basic_format_string& other) = default; + + ETL_CONSTEXPR string_view get() const + { + return _sv; + } + + private: + string_view _sv; + }; + + template + using format_string = basic_format_string...>; + + // supported types to format + using supported_format_types = etl::variant< + etl::monostate, + bool, + char, + int, + unsigned int, + long long int, + unsigned long long int, + float, + double, + long double, + const char*, + etl::string_view, + const void* + // basic_format_arg::handle, + >; + + template + class basic_format_parse_context + { + public: + + using iterator = string_view::const_iterator; + using const_iterator = string_view::const_iterator; + using char_type = CharT; + + basic_format_parse_context(etl::string_view fmt, size_t n_args = 0) + : range(fmt), num_args(n_args), current(0), automatic_mode(false), manual_mode(false) + { + } + + basic_format_parse_context& operator=(const basic_format_parse_context&) = delete; + + iterator begin() const noexcept + { + return range.begin(); + } + + iterator end() const noexcept + { + return range.end(); + } + + ETL_CONSTEXPR14 void advance_to(iterator pos) + { + range = etl::string_view(pos, range.end()); + } + + ETL_CONSTEXPR14 size_t next_arg_id() + { + // automatic number generation only allowed if not already in manual mode + ETL_ASSERT(manual_mode == false, ETL_ERROR(bad_format_string_exception)); + automatic_mode = true; + // TODO: compile time check + ETL_ASSERT(current < num_args, ETL_ERROR(bad_format_string_exception)/* not enough arguments for generated index */); + return current++; + } + + ETL_CONSTEXPR14 void check_arg_id(size_t id) + { + // manual index specification only allowed if not already in automatic mode + ETL_ASSERT(automatic_mode == false, ETL_ERROR(bad_format_string_exception)); + manual_mode = true; + ETL_ASSERT(id < num_args, ETL_ERROR(bad_format_string_exception)/* index out of range */); + } + + private: + etl::string_view range; + size_t num_args; + size_t current; + bool automatic_mode; + bool manual_mode; + + template + friend struct formatter; + }; + + using format_parse_context = basic_format_parse_context; + + template + class basic_format_arg + { + public: + + class handle + { + public: + void format(etl::basic_format_parse_context& /* parse_ctx */, + Context& /*format_ctx*/) + { + //typename Context::template formatter_type f; + //parse_ctx.advance_to(f.parse(parse_ctx)); + //format_ctx.advance_to(f.format(const_cast(static_cast(ref)), format_ctx)); + } + + private: + const void* obj; + typedef void(*function_type)(etl::basic_format_parse_context&, Context&, const void*); + function_type func; + }; + + basic_format_arg() + { + } + + basic_format_arg(const bool v) + : data(v) + { + } + + basic_format_arg(const int v) + : data(v) + { + } + + basic_format_arg(const unsigned int v) + : data(v) + { + } + + basic_format_arg(const long long int v) + : data(v) + { + } + + basic_format_arg(const unsigned long long int v) + : data(v) + { + } + + basic_format_arg(const char* v) + : data(v) + { + } + + basic_format_arg(char v) + : data(v) + { + } + + basic_format_arg(const float v) + : data(v) + { + } + + basic_format_arg(const double v) + : data(v) + { + } + + basic_format_arg(const long double v) + : data(v) + { + } + + basic_format_arg(const etl::string_view v) + : data(v) + { + } + + basic_format_arg(const basic_format_arg& other): data(other.data) + { + } + + basic_format_arg(const void* v) + : data(v) + { + } + + basic_format_arg& operator=(const basic_format_arg& other) + { + data = other.data; + return *this; + } + + explicit operator bool() const + { + return !etl::holds_alternative(data); + } + + template + R visit(Visitor&& vis) + { + return etl::visit(etl::forward(vis), data); + } + + private: + supported_format_types data; + }; + + template + class format_arg_store + { + public: + format_arg_store(Args&... args): _args{args...} {} + + basic_format_arg get(size_t i) const + { + return _args.get(i); + } + + etl::array_view> get() + { + return _args; + } + + private: + etl::array, sizeof...(Args)> _args; + }; + + template + class basic_format_args + { + public: + template + basic_format_args(format_arg_store& store): _args(store.get()) + { + } + + basic_format_args(const basic_format_args& other): _args(other._args) + { + } + + basic_format_args& operator=(const basic_format_args& other) + { + _args = other._args; + return *this; + } + + basic_format_arg get(size_t i) const + { + return _args[i]; + } + + // non-standard + size_t size() + { + return _args.size(); + } + + private: + etl::array_view> _args; + }; + + namespace private_format + { + using char_type = char; + + enum class spec_align_t + { + NONE, // default + START, + END, + CENTER + }; + + enum class spec_sign_t + { + MINUS, // default + PLUS, + SPACE + }; + + struct format_spec_t + { + etl::optional index{etl::nullopt_t()}; + spec_align_t align{spec_align_t::NONE}; // '<' / '>' / '^' / none (default) + char_type fill{' '}; // fill character (' ' is default) + spec_sign_t sign{spec_sign_t::MINUS}; // '+' / '-' (default) / ' ' + bool hash{false}; // # + bool zero{false}; // 0 + etl::optional width{etl::nullopt_t()}; // the arg index if width_nested_replacement == true + bool width_nested_replacement{false}; // {} + etl::optional precision{etl::nullopt_t()}; // the arg index if precision_nested_replacement == true + bool precision_nested_replacement{false}; // {} + bool locale_specific{false}; // 'L' + etl::optional type{etl::nullopt_t()}; // literal 's', 'b', 'd', ... + }; + } + + template + class basic_format_context + { + public: + + using iterator = OutputIt; + using char_type = CharT; + + basic_format_context(const basic_format_context& other): _it(other._it), _format_args(other._format_args) + { + } + + basic_format_context(OutputIt it, basic_format_args& fmt_args): _it(it), _format_args(fmt_args) + { + } + + basic_format_context& operator= (const basic_format_context&) = delete; + + basic_format_arg arg(size_t id) const + { + return _format_args.get(id); + } + + iterator out() + { + return _it; + } + + void advance_to(iterator it) + { + _it = it; + } + + private_format::format_spec_t format_spec; + + private: + iterator _it; + basic_format_args& _format_args; + }; + + template + using format_context = basic_format_context; + + template + using format_args = basic_format_args>; + + template + using format_arg = basic_format_arg>; + + template, class... Args> + format_arg_store make_format_args(Args&... args) + { + return format_arg_store(args...); + } + + namespace private_format + { + inline bool is_digit(const char c) + { + return c >= '0' && c <= '9'; + } + + inline void advance(format_parse_context& parse_ctx) + { + parse_ctx.advance_to(parse_ctx.begin() + 1); + } + + inline etl::optional parse_num(format_parse_context& parse_ctx) + { + etl::optional result; + auto fmt_it = parse_ctx.begin(); + while (fmt_it != parse_ctx.end()) + { + const char c = *fmt_it; + if (is_digit(c)) + { + size_t old_value = result.value_or(0); + size_t new_value = old_value * 10 + static_cast(c - '0'); + if (new_value < old_value) { + // Overflow detected + ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception)); + } + result = new_value; + } + else + { + break; + } + ++fmt_it; + } + if (result.has_value()) + { + parse_ctx.advance_to(fmt_it); + } + return result; + } + + inline etl::optional parse_any_of(format_parse_context& parse_ctx, etl::string_view chars) + { + etl::optional result; + auto fmt_it = parse_ctx.begin(); + if (fmt_it != parse_ctx.end()) + { + const char c = *fmt_it; + auto it = etl::find(chars.cbegin(), chars.cend(), c); + if (it != chars.cend()) + { + result = *it; + ++fmt_it; + parse_ctx.advance_to(fmt_it); + } + } + return result; + } + + inline bool parse_char(format_parse_context& parse_ctx, char c) + { + auto fmt_it = parse_ctx.begin(); + if (fmt_it != parse_ctx.end()) + { + char value = *fmt_it; + if (value == c) { + ++fmt_it; + parse_ctx.advance_to(fmt_it); + return true; + } + } + return false; + } + + inline bool parse_sequence(format_parse_context& parse_ctx, etl::string_view sequence) + { + auto fmt_it = parse_ctx.begin(); + if (etl::equal(sequence.cbegin(), sequence.cend(), fmt_it)) + { + fmt_it += sequence.size(); + parse_ctx.advance_to(fmt_it); + return true; + } + return false; + } + + inline bool is_align_character(char c) + { + return c == '<' || c == '>' || c == '^'; + } + + inline spec_align_t align_from_char(char c) + { + spec_align_t result = spec_align_t::NONE; + switch (c) + { + case '<': result = spec_align_t::START; break; + case '>': result = spec_align_t::END; break; + case '^': result = spec_align_t::CENTER; break; + default: + // invalid alignment specification + ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception)); + } + return result; + } + + inline spec_align_t parse_fill_and_align(format_parse_context& parse_ctx, char_type& fill) + { + spec_align_t result = spec_align_t::NONE; + fill = ' '; // default + + auto fmt_it = parse_ctx.begin(); + if (fmt_it != parse_ctx.end()) + { + const char c = *fmt_it; + ++fmt_it; + + if (is_align_character(c)) + { + result = align_from_char(c); + parse_ctx.advance_to(fmt_it); + } + else if (fmt_it != parse_ctx.end()) + { + const char c2 = *fmt_it; + ++fmt_it; + if (is_align_character(c2)) + { + result = align_from_char(c2); + ETL_ASSERT(c != '{' && c != '}', ETL_ERROR(bad_format_string_exception)); // no { or } allowed as fill character + fill = c; + parse_ctx.advance_to(fmt_it); + } + } + else + { + // no align and fill spec (valid) + } + } + return result; + } + + inline spec_sign_t sign_from_char(const char c) + { + spec_sign_t result = spec_sign_t::MINUS; + switch (c) + { + case '-': result = spec_sign_t::MINUS; break; + case '+': result = spec_sign_t::PLUS; break; + case ' ': result = spec_sign_t::SPACE; break; + default: + // invalid sign character c + ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception)); + } + return result; + } + + inline bool parse_nested_replacement(format_parse_context& parse_ctx, etl::optional& index) + { + bool start = parse_char(parse_ctx, '{'); + if (start) + { + auto num = parse_num(parse_ctx); + if (num) + { + // manual mode + index = num; + parse_ctx.check_arg_id(*index); + bool end = parse_char(parse_ctx, '}'); + if (end) + { + return true; + } + else + { + // bad nested replacement index spec + ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception)); + } + } + else + { + bool end = parse_char(parse_ctx, '}'); + if (end) + { + index = parse_ctx.next_arg_id(); + return true; + } + else + { + // bad nested replacement spec + ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception)); + } + } + } + return false; + } + + template + void parse_format_spec(format_parse_context& parse_ctx, format_context& fmt_context) + { + auto& format_spec = fmt_context.format_spec; + + format_spec = format_spec_t(); // reset format_spec to defaults + + format_spec.index = parse_num(parse_ctx); // optional + + bool colon = parse_char(parse_ctx, ':'); + if (colon) + { + format_spec.align = parse_fill_and_align(parse_ctx, format_spec.fill); + + etl::optional sign = parse_any_of(parse_ctx, "+- "); + if (sign) { + format_spec.sign = sign_from_char(*sign); + } + + format_spec.hash = parse_char(parse_ctx, '#'); + format_spec.zero = parse_char(parse_ctx, '0'); + + format_spec.width = parse_num(parse_ctx); + if (!format_spec.width) + { + // possibly with via nested replacement + format_spec.width_nested_replacement = parse_nested_replacement(parse_ctx, format_spec.width); + } + + if (parse_char(parse_ctx, '.')) + { + format_spec.precision = parse_num(parse_ctx); + if (!format_spec.precision) + { + // possibly with via nested replacement + format_spec.precision_nested_replacement = parse_nested_replacement(parse_ctx, format_spec.precision); + } + } + + format_spec.locale_specific = parse_char(parse_ctx, 'L'); + + format_spec.type = parse_any_of(parse_ctx, "s?bBcdoxXaAeEfFgGpP"); + } + } + } + + template + struct formatter + { + using char_type = CharT; + }; + + template<> + struct formatter + { + format_parse_context::iterator parse(format_parse_context& parse_ctx) + { + return parse_ctx.end(); + } + + template + typename format_context::iterator format(etl::monostate arg, format_context& fmt_ctx) + { + (void)arg; + return fmt_ctx.out(); + } + }; + + namespace private_format + { + // for 4321, return 1000 + template::value>> + UnsignedT get_highest_digit(UnsignedT value, size_t base = 10) + { + ETL_ASSERT(base > 1, ETL_ERROR(bad_format_string_exception)); + UnsignedT result = 1; + value /= base; + while (result <= value) + { + result *= base; + } + return result; + } + + template + T int_pow(T base, T exp) + { + T result = 1; + while (exp > 0) { + if (exp % 2 == 1) result *= base; + base *= base; + exp /= 2; + } + return result; + } + + template + void format_sign(OutputIt& it, T value, const format_spec_t& spec) + { + char c = '\0'; + if (value < 0) + { + c = '-'; + } + else + { + switch (spec.sign) + { + case spec_sign_t::MINUS: + // c already set above if negative + break; + case spec_sign_t::PLUS: + c = '+'; + break; + case spec_sign_t::SPACE: + c = ' '; + break; + default: + // invalid sign + ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception)); + } + } + + if (c != '\0') + { + *it = c; + ++it; + } + } + + template + void format_sequence(OutputIt& out_it, etl::string_view value) + { + auto it = value.cbegin(); + while (it != value.cend()) + { + *out_it = *it; + ++it; + ++out_it; + } + } + + template + void format_alternate_form(OutputIt& it, const format_spec_t& spec) + { + if (spec.hash && spec.type.has_value()) + { + switch (spec.type.value()) + { + case 'b': + format_sequence(it, "0b"); + break; + case 'B': + format_sequence(it, "0B"); + break; + case 'o': + format_sequence(it, "0"); + break; + case 'x': + format_sequence(it, "0x"); + break; + case 'X': + format_sequence(it, "0X"); + break; + // default: no prefix + } + } + } + + template + void format_plain_char(OutputIt& it, char_type c) + { + *it = c; + ++it; + } + + template + void format_escaped_char(OutputIt& it, char_type c) + { + switch (c) + { + case '\t': + format_sequence(it, "\\t"); + break; + case '\n': + format_sequence(it, "\\n"); + break; + case '\r': + format_sequence(it, "\\r"); + break; + case '"': + format_sequence(it, "\\\""); + break; + case '\'': + format_sequence(it, "\\'"); + break; + case '\\': + format_sequence(it, "\\\\"); + break; + default: + *it = c; + ++it; + } + } + + template + void fill(OutputIt& it, size_t size, char_type c) + { + while (size > 0) + { + *it = c; + ++it; + --size; + } + } + + template + inline size_t base_from_spec(const format_spec_t& spec) + { + size_t base = default_base; + if (spec.type.has_value()) + { + switch (spec.type.value()) + { + case 'a': + case 'A': + base = 16; + break; + case 'b': + case 'B': + base = 2; + break; + case 'o': + base = 8; + break; + case 'p': + case 'P': + case 'x': + case 'X': + base = 16; + break; + // default: no prefix + } + } + return base; + } + + inline bool is_uppercase(const char c) + { + return c >= 'A' && c <= 'Z'; + } + + template + void format_digit_char(OutputIt& it, T value, const format_spec_t& spec) + { + if (value <= 9) + { + *it = '0' + value; + } + else + { + if (spec.type.has_value() && is_uppercase(spec.type.value())) + { + *it = 'A' + (value - 10); + } + else + { + *it = 'a' + (value - 10); + } + } + ++it; + } + + inline void adjust_width_from_spec(const format_spec_t& spec, size_t& width) + { + if (spec.zero && spec.width.has_value()) + { + width = etl::max(width, spec.width.value()); + } + } + + inline void check_precision(const format_spec_t& spec) + { + if (spec.precision.has_value()) + { + // precision not allowed for integer numbers + ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception)); + } + } + + // used for both integers and float parts + // skip_last_zeros helps in case of printing after-the-decimal zeros which are + // redundant then + template + void format_plain_num(OutputIt& it, T value, const format_spec_t& spec, size_t width = 0) + { + using UnsignedT = typename etl::make_unsigned::type; + + UnsignedT unsigned_value = static_cast(value < 0 ? -value : value); + + size_t base = base_from_spec(spec); + UnsignedT highest_digit = get_highest_digit(unsigned_value, base); + if (width > 0) + { + UnsignedT align_highest_digit = int_pow(base, width - 1); + highest_digit = etl::max(align_highest_digit, highest_digit); + } + + // this loop is iterated at least once, to print a number + while (highest_digit > 0) + { + UnsignedT digit = unsigned_value / highest_digit; + unsigned_value %= highest_digit; + format_digit_char(it, digit, spec); + + if ETL_CONSTEXPR17 (skip_last_zeros) + { + if (unsigned_value == 0) + { + break; + } + } + + highest_digit /= base; + } + } + + // for integers + template + void format_num(OutputIt& it, T value, const format_spec_t& spec) + { + size_t width = 0; + format_sign(it, value, spec); + format_alternate_form(it, spec); + adjust_width_from_spec(spec, width); + check_precision(spec); + format_plain_num(it, value, spec, width); + } + + template + void format_floating_default(OutputIt& it, T value, const format_spec_t& spec) + { + const size_t fractional_decimals = 6; // default + + T integral; + T fractional = modf(value, &integral); + bool sign; + unsigned long long int fractional_int; + unsigned long long int integral_int; + if (integral < 0.0) + { + sign = true; + fractional_int = static_cast(-fractional * pow(10., fractional_decimals)); + integral_int = static_cast(-integral); + } + else + { + sign = false; + fractional_int = static_cast(fractional * pow(10., fractional_decimals)); + integral_int = static_cast(integral); + } + + private_format::format_sign(it, sign ? -1 : 0, spec); + private_format::format_plain_num(it, integral_int, spec); + private_format::format_sequence(it, "."); + private_format::format_plain_num(it, fractional_int, spec, fractional_decimals); + } + + // floating point in hex notation + template + void format_floating_a(OutputIt& it, T value, const format_spec_t& spec) + { + static const size_t fractional_decimals = 10; // default + static const size_t exponent_decimals = 1; + long long int exponent_int = 0; + + bool sign; + unsigned long long int fractional_int; + unsigned long long int integral_int; + + T integral; + T fractional = modf(value, &integral); + + while (value >= 0x10 || value <= -0x10) + { + ++exponent_int; + value /= 0x10; + fractional = modf(value, &integral); + } + + while ((value > 0.0000000000001 && value < 1) || (value < -0.0000000000001 && value > -1)) + { + --exponent_int; + value *= 0x10; + fractional = modf(value, &integral); + } + + if (integral < 0.0) + { + sign = true; + fractional_int = static_cast(-fractional * pow(static_cast(0x10), fractional_decimals)); + integral_int = static_cast(-integral); + } + else + { + sign = false; + fractional_int = static_cast(fractional * pow(static_cast(0x10), fractional_decimals)); + integral_int = static_cast(integral); + } + + private_format::format_sign(it, sign ? -1 : 0, spec); + private_format::format_plain_char(it, '0'); + char hex_letter = 'x'; + if (is_uppercase(spec.type.value())) + { + hex_letter = 'X'; + } + private_format::format_plain_char(it, hex_letter); + private_format::format_plain_num(it, integral_int, spec); + private_format::format_plain_char(it, '.'); + private_format::format_plain_num(it, fractional_int, spec, fractional_decimals); + char letter = 'p'; + if (is_uppercase(spec.type.value())) + { + letter = 'P'; + } + private_format::format_plain_char(it, letter); + private_format::format_plain_char(it, (exponent_int < 0) ? '-' : '+'); + private_format::format_plain_num(it, exponent_int, spec, exponent_decimals); + } + + template + void format_floating_e(OutputIt& it, T value, const format_spec_t& spec) + { + static const size_t fractional_decimals = 6; // default + static const size_t exponent_decimals = 2; + long long int exponent_int = 0; + + bool sign; + unsigned long long int fractional_int; + unsigned long long int integral_int; + + T integral; + T fractional = modf(value, &integral); + + while (value >= 10 || value <= -10) + { + ++exponent_int; + value /= 10; + fractional = modf(value, &integral); + } + + while ((value > 0.0000000000001 && value < 1) || (value < -0.0000000000001 && value > -1)) + { + --exponent_int; + value *= 10; + fractional = modf(value, &integral); + } + + if (integral < 0.0) + { + sign = true; + fractional_int = static_cast(-fractional * pow(10., fractional_decimals)); + integral_int = static_cast(-integral); + } + else + { + sign = false; + fractional_int = static_cast(fractional * pow(10., fractional_decimals)); + integral_int = static_cast(integral); + } + + private_format::format_sign(it, sign ? -1 : 0, spec); + private_format::format_plain_num(it, integral_int, spec); + private_format::format_sequence(it, "."); + private_format::format_plain_num(it, fractional_int, spec, fractional_decimals); + char letter = 'e'; + if (is_uppercase(spec.type.value())) + { + letter = 'E'; + } + private_format::format_plain_char(it, letter); + private_format::format_plain_char(it, (exponent_int < 0) ? '-' : '+'); + private_format::format_plain_num(it, exponent_int, spec, exponent_decimals); + } + + template + void format_floating_f(OutputIt& it, T value, const format_spec_t& spec) + { + const size_t fractional_decimals = 6; // default + + T integral; + T fractional = modf(value, &integral); + bool sign; + unsigned long long int fractional_int; + unsigned long long int integral_int; + if (integral < 0.0) + { + sign = true; + fractional_int = static_cast(-fractional * pow(10., fractional_decimals)); + integral_int = static_cast(-integral); + } + else + { + sign = false; + fractional_int = static_cast(fractional * pow(10., fractional_decimals)); + integral_int = static_cast(integral); + } + + private_format::format_sign(it, sign ? -1 : 0, spec); + private_format::format_plain_num(it, integral_int, spec); + private_format::format_sequence(it, "."); + private_format::format_plain_num(it, fractional_int, spec, fractional_decimals); + } + + class dummy_assign_to + { + public: + dummy_assign_to& operator=(char_type) + { + return *this; + } + }; + + template + class limit_assign_to + { + public: + limit_assign_to(OutputIt o, bool is_active) + : out(o) + , active(is_active) + { + } + + limit_assign_to& operator=(char_type c) + { + if (active) + { + *out = c; + } + return *this; + } + + private: + OutputIt out; + bool active; + }; + + template + class limit_iterator + { + public: + limit_iterator(OutputIt& it, size_t n) + : out(it) + , limit(n) + { + } + + limit_iterator(const limit_iterator& other) = default; + limit_iterator(limit_iterator&& other) = default; + limit_iterator& operator=(const limit_iterator& other) = default; + limit_iterator& operator=(limit_iterator&& other) = default; + + limit_assign_to operator*() + { + return limit_assign_to(out, (limit > 0)); + } + + limit_iterator& operator++() + { + if (limit > 0) + { + --limit; + ++out; + } + return *this; + } + + limit_iterator operator++(int) + { + limit_iterator temp = *this; + if (limit > 0) + { + --limit; + out++; + } + return temp; + } + + OutputIt get() + { + return out; + } + + private: + OutputIt out; + size_t limit; + }; + + class counter_iterator + { + public: + counter_iterator(): count(0) + { + } + + counter_iterator(const counter_iterator& other) = default; + counter_iterator& operator=(const counter_iterator& other) = default; + + dummy_assign_to operator*() + { + return dummy_assign_to(); + } + + counter_iterator& operator++() + { + ++count; + return *this; + } + + counter_iterator operator++(int) + { + counter_iterator temp = *this; + count++; + return temp; + } + + size_t value() + { + return count; + } + + private: + size_t count; + }; + + template + void format_floating_g(OutputIt& it, T value, const format_spec_t& spec) + { + private_format::counter_iterator counter_e, counter_f; + + format_floating_e(counter_e, value, spec); + format_floating_f(counter_f, value, spec); + + if (counter_e.value() < counter_f.value()) + { + format_floating_e(it, value, spec); + } + else + { + format_floating_f(it, value, spec); + } + } + + template + void format_floating(OutputIt& it, T value, const format_spec_t& spec) + { + if (isnan(value)) + { + if (spec.type.has_value() && (is_uppercase(spec.type.value()))) + { + format_sequence(it, "NAN"); + } + else + { + format_sequence(it, "nan"); + } + } + else if (isinf(value)) + { + if (spec.type.has_value() && (is_uppercase(spec.type.value()))) + { + format_sequence(it, "INF"); + } + else + { + format_sequence(it, "inf"); + } + } + else if (!spec.type.has_value()) + { + format_floating_default(it, value, spec); + } + else + { + switch (spec.type.value()) + { + case 'a': + case 'A': + format_floating_a(it, value, spec); + break; + case 'e': + case 'E': + format_floating_e(it, value, spec); + break; + case 'f': + case 'F': + format_floating_f(it, value, spec); + break; + case 'g': + case 'G': + format_floating_g(it, value, spec); + break; + default: + // unknown presentation type + ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception)); + } + } + } + + template + struct format_visitor + { + using output_iterator = OutputIt; + + format_visitor(format_parse_context& parse_context, format_context& f_ctx) + : parse_ctx(parse_context) + , fmt_ctx(f_ctx) + { + } + + // for all types in supported_format_types + template + void operator()(T value) + { + formatter f; + format_parse_context::iterator it = f.parse(parse_ctx); + parse_ctx.advance_to(it); + OutputIt fit = f.format(value, fmt_ctx); + fmt_ctx.advance_to(fit); + } + + format_parse_context& parse_ctx; + format_context& fmt_ctx; + }; + + template + void output(format_context& fmt_context, char c) + { + *fmt_context.out() = c; + OutputIt tmp = fmt_context.out(); + tmp++; + fmt_context.advance_to(tmp); + } + + template + typename format_context::iterator format_aligned_int(Int arg, format_context& fmt_ctx) + { + size_t prefix_size = 0; + size_t suffix_size = 0; + + if (fmt_ctx.format_spec.width) + { + // calculate size + private_format::counter_iterator counter; + private_format::format_num(counter, arg, fmt_ctx.format_spec); + + if (counter.value() < fmt_ctx.format_spec.width.value()) + { + size_t pad = fmt_ctx.format_spec.width.value() - counter.value(); + switch (fmt_ctx.format_spec.align) + { + case private_format::spec_align_t::START: + prefix_size = 0; + suffix_size = pad; + break; + case private_format::spec_align_t::CENTER: + prefix_size = pad / 2; + suffix_size = pad - prefix_size; + break; + case private_format::spec_align_t::NONE: // default + case private_format::spec_align_t::END: + prefix_size = pad; + suffix_size = 0; + break; + default: + // invalid alignment specification + ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception)); + } + } + } + + // actual output + OutputIt it = fmt_ctx.out(); + private_format::fill(it, prefix_size, fmt_ctx.format_spec.fill); + private_format::format_num(it, arg, fmt_ctx.format_spec); + private_format::fill(it, suffix_size, fmt_ctx.format_spec.fill); + return it; + } + + template + typename format_context::iterator format_aligned_floating(Float arg, format_context& fmt_ctx) + { + size_t prefix_size = 0; + size_t suffix_size = 0; + + if (fmt_ctx.format_spec.width) + { + // calculate size + private_format::counter_iterator counter; + private_format::format_floating(counter, arg, fmt_ctx.format_spec); + + if (counter.value() < fmt_ctx.format_spec.width.value()) + { + size_t pad = fmt_ctx.format_spec.width.value() - counter.value(); + switch (fmt_ctx.format_spec.align) + { + case private_format::spec_align_t::START: + prefix_size = 0; + suffix_size = pad; + break; + case private_format::spec_align_t::CENTER: + prefix_size = pad / 2; + suffix_size = pad - prefix_size; + break; + case private_format::spec_align_t::NONE: // default + case private_format::spec_align_t::END: + prefix_size = pad; + suffix_size = 0; + break; + default: + // invalid alignment specification + ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception)); + } + } + } + + // actual output + OutputIt it = fmt_ctx.out(); + private_format::fill(it, prefix_size, fmt_ctx.format_spec.fill); + private_format::format_floating(it, arg, fmt_ctx.format_spec); + private_format::fill(it, suffix_size, fmt_ctx.format_spec.fill); + return it; + } + + template + void format_string_view(OutputIt& it, etl::string_view arg, const format_spec_t& spec) + { + bool escaped = false; + if (spec.type.has_value()) + { + switch (spec.type.value()) + { + case 's': + // default output + break; + case '?': + // escaped string + escaped = true; + break; + default: + // invalid type for string + ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception)); + } + } + size_t limit = etl::numeric_limits::max(); + if (spec.precision.has_value()) + { + limit = spec.precision.value(); + } + + if (escaped) + { + format_plain_char(it, '"'); + } + etl::string_view::const_iterator arg_it = arg.begin(); + while (arg_it != arg.cend() && limit > 0) + { + if (escaped) + { + format_escaped_char(it, *arg_it); + } + else + { + format_plain_char(it, *arg_it); + } + ++arg_it; + --limit; + } + if (escaped) + { + format_plain_char(it, '"'); + } + } + + template + typename format_context::iterator format_aligned_string_view(etl::string_view arg, format_context& fmt_ctx) + { + size_t prefix_size = 0; + size_t suffix_size = 0; + + if (fmt_ctx.format_spec.width) + { + // calculate size + private_format::counter_iterator counter; + private_format::format_string_view(counter, arg, fmt_ctx.format_spec); + + if (counter.value() < fmt_ctx.format_spec.width.value()) + { + size_t pad = fmt_ctx.format_spec.width.value() - counter.value(); + switch (fmt_ctx.format_spec.align) + { + case private_format::spec_align_t::NONE: // default + case private_format::spec_align_t::START: + prefix_size = 0; + suffix_size = pad; + break; + case private_format::spec_align_t::CENTER: + prefix_size = pad / 2; + suffix_size = pad - prefix_size; + break; + case private_format::spec_align_t::END: + prefix_size = pad; + suffix_size = 0; + break; + default: + // invalid alignment specification + ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception)); + } + } + } + + // actual output + OutputIt it = fmt_ctx.out(); + private_format::fill(it, prefix_size, fmt_ctx.format_spec.fill); + private_format::format_string_view(it, arg, fmt_ctx.format_spec); + private_format::fill(it, suffix_size, fmt_ctx.format_spec.fill); + return it; + } + + template + void format_chars(OutputIt& it, const char* arg, const format_spec_t& spec) + { + bool escaped = false; + if (spec.type.has_value()) + { + switch (spec.type.value()) + { + case 's': + // default output + break; + case '?': + // escaped string + escaped = true; + break; + default: + // invalid type for string + ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception)); + } + } + size_t limit = etl::numeric_limits::max(); + if (spec.precision.has_value()) + { + limit = spec.precision.value(); + } + + if (escaped) + { + format_plain_char(it, '"'); + } + const char_type* arg_it = arg; + while (*arg_it != '\0' && limit > 0) + { + if (escaped) + { + format_escaped_char(it, *arg_it); + } + else + { + format_plain_char(it, *arg_it); + } + ++arg_it; + --limit; + } + if (escaped) + { + format_plain_char(it, '"'); + } + } + + template + typename format_context::iterator format_aligned_chars(const char* arg, format_context& fmt_ctx) + { + size_t prefix_size = 0; + size_t suffix_size = 0; + + if (fmt_ctx.format_spec.width) + { + // calculate size + private_format::counter_iterator counter; + private_format::format_chars(counter, arg, fmt_ctx.format_spec); + + if (counter.value() < fmt_ctx.format_spec.width.value()) + { + size_t pad = fmt_ctx.format_spec.width.value() - counter.value(); + switch (fmt_ctx.format_spec.align) + { + case private_format::spec_align_t::NONE: // default + case private_format::spec_align_t::START: + prefix_size = 0; + suffix_size = pad; + break; + case private_format::spec_align_t::CENTER: + prefix_size = pad / 2; + suffix_size = pad - prefix_size; + break; + case private_format::spec_align_t::END: + prefix_size = pad; + suffix_size = 0; + break; + default: + // invalid alignment specification + ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception)); + } + } + } + + // actual output + OutputIt it = fmt_ctx.out(); + private_format::fill(it, prefix_size, fmt_ctx.format_spec.fill); + private_format::format_chars(it, arg, fmt_ctx.format_spec); + private_format::fill(it, suffix_size, fmt_ctx.format_spec.fill); + return it; + } + + inline void check_char_spec(const format_spec_t& spec) + { + if ((!spec.type.has_value() || spec.type.value() == 'c' || spec.type.value() == '?') && + (spec.sign != spec_sign_t::MINUS || + spec.zero || + spec.hash || + spec.precision) + ) + { + ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception)); + } + } + + template + void format_char(OutputIt& it, char_type c, const format_spec_t& spec) + { + check_char_spec(spec); + if (spec.type.has_value()) + { + switch (spec.type.value()) + { + case 'c': + // default output + format_plain_char(it, c); + break; + case '?': + // escaped string + format_plain_char(it, '\''); + format_escaped_char(it, c); + format_plain_char(it, '\''); + break; + case 'b': + case 'B': + case 'd': + case 'o': + case 'x': + case 'X': + private_format::format_num(it, static_cast(static_cast(c)), spec); + break; + default: + // invalid type for string + ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception)); + } + } + else + { + format_plain_char(it, c); + } + } + + template + typename format_context::iterator format_aligned_char(char_type arg, format_context& fmt_ctx) + { + size_t prefix_size = 0; + size_t suffix_size = 0; + + if (fmt_ctx.format_spec.width) + { + // calculate size + private_format::counter_iterator counter; + private_format::format_char(counter, arg, fmt_ctx.format_spec); + + if (counter.value() < fmt_ctx.format_spec.width.value()) + { + size_t pad = fmt_ctx.format_spec.width.value() - counter.value(); + switch (fmt_ctx.format_spec.align) + { + case private_format::spec_align_t::NONE: // default + if (!fmt_ctx.format_spec.type.has_value() || fmt_ctx.format_spec.type.value() == 'c' || fmt_ctx.format_spec.type.value() == '?') + { + prefix_size = 0; + suffix_size = pad; + } + else + { + prefix_size = pad; + suffix_size = 0; + } + break; + case private_format::spec_align_t::START: + prefix_size = 0; + suffix_size = pad; + break; + case private_format::spec_align_t::CENTER: + prefix_size = pad / 2; + suffix_size = pad - prefix_size; + break; + case private_format::spec_align_t::END: + prefix_size = pad; + suffix_size = 0; + break; + default: + // invalid alignment specification + ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception)); + } + } + } + + // actual output + OutputIt it = fmt_ctx.out(); + private_format::fill(it, prefix_size, fmt_ctx.format_spec.fill); + private_format::format_char(it, arg, fmt_ctx.format_spec); + private_format::fill(it, suffix_size, fmt_ctx.format_spec.fill); + return it; + } + + template + void format_bool(OutputIt& it, bool value, const format_spec_t& spec) + { + if (spec.type.has_value()) + { + switch (spec.type.value()) + { + case 's': + // default output + format_sequence(it, value ? "true" : "false"); + break; + case 'b': + case 'B': + case 'd': + case 'o': + case 'x': + case 'X': + private_format::format_num(it, static_cast(static_cast(value)), spec); + break; + default: + // invalid type for string + ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception)); + } + } + else + { + format_sequence(it, value ? "true" : "false"); + } + } + + template + typename format_context::iterator format_aligned_bool(bool arg, format_context& fmt_ctx) + { + size_t prefix_size = 0; + size_t suffix_size = 0; + + if (fmt_ctx.format_spec.width) + { + // calculate size + private_format::counter_iterator counter; + private_format::format_bool(counter, arg, fmt_ctx.format_spec); + + if (counter.value() < fmt_ctx.format_spec.width.value()) + { + size_t pad = fmt_ctx.format_spec.width.value() - counter.value(); + switch (fmt_ctx.format_spec.align) + { + case private_format::spec_align_t::START: + prefix_size = 0; + suffix_size = pad; + break; + case private_format::spec_align_t::CENTER: + prefix_size = pad / 2; + suffix_size = pad - prefix_size; + break; + case private_format::spec_align_t::NONE: // default + case private_format::spec_align_t::END: + prefix_size = pad; + suffix_size = 0; + break; + default: + // invalid alignment specification + ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception)); + } + } + } + + // actual output + OutputIt it = fmt_ctx.out(); + private_format::fill(it, prefix_size, fmt_ctx.format_spec.fill); + private_format::format_bool(it, arg, fmt_ctx.format_spec); + private_format::fill(it, suffix_size, fmt_ctx.format_spec.fill); + return it; + } + + template + void format_pointer(OutputIt& it, const void* value, const format_spec_t& spec) + { + if (spec.type.has_value()) + { + switch (spec.type.value()) + { + case 'p': + case 'P': + format_sequence(it, spec.type.value() == 'p' ? "0x" : "0X"); + format_plain_num(it, reinterpret_cast(value), spec); + break; + default: + // invalid type for string + ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception)); + } + } + else + { + format_sequence(it, "0x"); + format_plain_num(it, reinterpret_cast(value), spec); + } + } + + template + typename format_context::iterator format_aligned_pointer(const void* arg, format_context& fmt_ctx) + { + size_t prefix_size = 0; + size_t suffix_size = 0; + + if (fmt_ctx.format_spec.width) + { + // calculate size + private_format::counter_iterator counter; + private_format::format_pointer(counter, arg, fmt_ctx.format_spec); + + if (counter.value() < fmt_ctx.format_spec.width.value()) + { + size_t pad = fmt_ctx.format_spec.width.value() - counter.value(); + switch (fmt_ctx.format_spec.align) + { + case private_format::spec_align_t::START: + prefix_size = 0; + suffix_size = pad; + break; + case private_format::spec_align_t::CENTER: + prefix_size = pad / 2; + suffix_size = pad - prefix_size; + break; + case private_format::spec_align_t::NONE: // default + case private_format::spec_align_t::END: + prefix_size = pad; + suffix_size = 0; + break; + default: + // invalid alignment specification + ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception)); + } + } + } + + // actual output + OutputIt it = fmt_ctx.out(); + private_format::fill(it, prefix_size, fmt_ctx.format_spec.fill); + private_format::format_pointer(it, arg, fmt_ctx.format_spec); + private_format::fill(it, suffix_size, fmt_ctx.format_spec.fill); + return it; + } + } // namespace private_format + + template<> + struct formatter + { + format_parse_context::iterator parse(format_parse_context& parse_ctx) + { + // unified parsing is done already in vformat_to() + return parse_ctx.begin(); + } + + template + typename format_context::iterator format(int arg, format_context& fmt_ctx) + { + if (fmt_ctx.format_spec.type.has_value() && fmt_ctx.format_spec.type.value() == 'c') + { + return private_format::format_aligned_char(static_cast(arg), fmt_ctx); + } + return private_format::format_aligned_int(arg, fmt_ctx); + } + }; + + template<> + struct formatter + { + format_parse_context::iterator parse(format_parse_context& parse_ctx) + { + // unified parsing is done already in vformat_to() + return parse_ctx.begin(); + } + + template + typename format_context::iterator format(unsigned int arg, format_context& fmt_ctx) + { + if (fmt_ctx.format_spec.type.has_value() && fmt_ctx.format_spec.type.value() == 'c') + { + return private_format::format_aligned_char(static_cast(arg), fmt_ctx); + } + return private_format::format_aligned_int(arg, fmt_ctx); + } + }; + + template<> + struct formatter + { + format_parse_context::iterator parse(format_parse_context& parse_ctx) + { + // unified parsing is done already in vformat_to() + return parse_ctx.begin(); + } + + template + typename format_context::iterator format(long long int arg, format_context& fmt_ctx) + { + if (fmt_ctx.format_spec.type.has_value() && fmt_ctx.format_spec.type.value() == 'c') + { + return private_format::format_aligned_char(static_cast(arg), fmt_ctx); + } + return private_format::format_aligned_int(arg, fmt_ctx); + } + }; + + template<> + struct formatter + { + format_parse_context::iterator parse(format_parse_context& parse_ctx) + { + // unified parsing is done already in vformat_to() + return parse_ctx.begin(); + } + + template + typename format_context::iterator format(unsigned long long int arg, format_context& fmt_ctx) + { + if (fmt_ctx.format_spec.type.has_value() && fmt_ctx.format_spec.type.value() == 'c') + { + return private_format::format_aligned_char(static_cast(arg), fmt_ctx); + } + return private_format::format_aligned_int(arg, fmt_ctx); + } + }; + + template<> + struct formatter + { + format_parse_context::iterator parse(format_parse_context& parse_ctx) + { + // unified parsing is done already in vformat_to() + return parse_ctx.begin(); + } + + template + typename format_context::iterator format(private_format::char_type arg, format_context& fmt_ctx) + { + return private_format::format_aligned_char(arg, fmt_ctx); + } + }; + + template<> + struct formatter + { + format_parse_context::iterator parse(format_parse_context& parse_ctx) + { + // unified parsing is done already in vformat_to() + return parse_ctx.begin(); + } + + template + typename format_context::iterator format(float arg, format_context& fmt_ctx) + { + return private_format::format_aligned_floating(arg, fmt_ctx); + } + }; + + template<> + struct formatter + { + format_parse_context::iterator parse(format_parse_context& parse_ctx) + { + // unified parsing is done already in vformat_to() + return parse_ctx.begin(); + } + + template + typename format_context::iterator format(double arg, format_context& fmt_ctx) + { + return private_format::format_aligned_floating(arg, fmt_ctx); + } + }; + + template<> + struct formatter + { + format_parse_context::iterator parse(format_parse_context& parse_ctx) + { + // unified parsing is done already in vformat_to() + return parse_ctx.begin(); + } + + template + typename format_context::iterator format(long double arg, format_context& fmt_ctx) + { + return private_format::format_aligned_floating(arg, fmt_ctx); + } + }; + + template<> + struct formatter + { + format_parse_context::iterator parse(format_parse_context& parse_ctx) + { + // unified parsing is done already in vformat_to() + return parse_ctx.begin(); + } + + template + typename format_context::iterator format(etl::string_view arg, format_context& fmt_ctx) + { + return private_format::format_aligned_string_view(arg, fmt_ctx); + } + }; + + // string formatter + template<> + struct formatter + { + format_parse_context::iterator parse(format_parse_context& parse_ctx) + { + // unified parsing is done already in vformat_to() + return parse_ctx.begin(); + } + + template + typename format_context::iterator format(const char* arg, format_context& fmt_ctx) + { + return private_format::format_aligned_chars(arg, fmt_ctx); + } + }; + + template<> + struct formatter + { + format_parse_context::iterator parse(format_parse_context& parse_ctx) + { + // unified parsing is done already in vformat_to() + return parse_ctx.begin(); + } + + template + typename format_context::iterator format(bool arg, format_context& fmt_ctx) + { + return private_format::format_aligned_bool(arg, fmt_ctx); + } + }; + + template<> + struct formatter + { + format_parse_context::iterator parse(format_parse_context& parse_ctx) + { + // unified parsing is done already in vformat_to() + return parse_ctx.begin(); + } + + template + typename format_context::iterator format(const void* arg, format_context& fmt_ctx) + { + return private_format::format_aligned_pointer(arg, fmt_ctx); + } + }; + + template + OutputIt vformat_to(OutputIt out, etl::string_view fmt, format_args args) + { + format_parse_context parse_context(fmt, args.size()); + format_context fmt_context(out, args); + private_format::format_visitor v(parse_context, fmt_context); + + while (parse_context.begin() != parse_context.end()) + { + const char c = *parse_context.begin(); + private_format::advance(parse_context); + if (c == '{') + { + + if (*parse_context.begin() == '{') + { + // escape sequence for literal '{' + private_format::output(fmt_context, c); + private_format::advance(parse_context); + } + else + { + private_format::parse_format_spec(parse_context, fmt_context); + etl::optional index = fmt_context.format_spec.index; + if (index.has_value()) + { + parse_context.check_arg_id(*index); + } + else + { + index = parse_context.next_arg_id(); + } + format_arg arg = args.get(*index); + arg.template visit(v); + + ETL_ASSERT(*parse_context.begin() == '}', ETL_ERROR(bad_format_string_exception)/*"Closing brace missing"*/); + if (parse_context.begin() != parse_context.end()) + { + private_format::advance(parse_context); + } + } + } + else if (c == '}') // only matches here if } without { is found + { + ETL_ASSERT(*parse_context.begin() == '}', ETL_ERROR(bad_format_string_exception)/*"2nd closing brace missing on escaped closing brace"*/); + // escape sequence for literal '}' + private_format::output(fmt_context, c); + private_format::advance(parse_context); + } + else + { + private_format::output(fmt_context, c); + } + }; + + // plain strings need it, back insert iterators don't: + //*fmt_context.out() = '\0'; + + return fmt_context.out(); + } + + template::type, OutputIt>::value>, + class... Args> + OutputIt format_to(OutputIt out, format_string fmt, Args&&... args) + { + auto the_args{make_format_args(args...)}; + return vformat_to(etl::move(out), fmt.get(), format_args(the_args)); + } + + template, class... Args> + OutputIt format_to_n(OutputIt out, size_t n, format_string fmt, Args&&... args) + { + auto the_args{make_format_args(args...)}; + return vformat_to(WrapperIt(out, n), + fmt.get(), + format_args(the_args)).get(); + } + + // non std in the following, specific to etl + template + etl::istring::iterator format_to(etl::istring& out, format_string fmt, Args&&... args) + { + etl::istring::iterator result = format_to_n(out.begin(), out.max_size(), fmt, etl::forward(args)...); + out.uninitialized_resize(result - out.begin()); + return result; + } + + template + size_t formatted_size(format_string fmt, Args&&... args) + { + private_format::counter_iterator it; + it = format_to(it, fmt, etl::forward(args)...); + return it.value(); + } +} + +#endif + +#endif diff --git a/include/etl/print.h b/include/etl/print.h new file mode 100644 index 00000000..511fab70 --- /dev/null +++ b/include/etl/print.h @@ -0,0 +1,117 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 BMW AG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_PRINT_INCLUDED +#define ETL_PRINT_INCLUDED + +#include "platform.h" + +#include "format.h" + +#if ETL_USING_CPP11 + +// to be implemented in a concrete project, typically printing to a serial console +// type int here is the convention from putchar(), actually storing char +extern "C" void etl_putchar(int c); + +namespace etl +{ + namespace private_print + { + using char_type = etl::private_format::char_type; + + // No-op iterator that forwards all assignments to etl_putchar + class print_iterator + { + public: + class print_to + { + public: + print_to& operator=(char_type c) + { + etl_putchar(static_cast(c)); + return *this; + } + }; + + print_iterator() + { + } + + print_iterator(const print_iterator&) + { + } + + print_iterator& operator=(const print_iterator&) + { + return *this; + } + + print_to operator*() + { + return print_to(); + } + + print_iterator& operator++() + { + return *this; + } + + print_iterator operator++(int) + { + return *this; + } + }; + } // namespace private_print + + template + void print(etl::format_string fmt, Args&&... args) + { + private_print::print_iterator it; + (void)format_to(it, etl::move(fmt), etl::forward(args)...); + } + + inline void println() + { + etl_putchar(static_cast('\n')); + } + + template + void println(etl::format_string fmt, Args&&... args) + { + private_print::print_iterator it; + (void)format_to(it, etl::move(fmt), etl::forward(args)...); + println(); + } +} // namespace etl + +#endif + +#endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7866cd5d..26333f79 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -184,6 +184,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 @@ -260,6 +261,7 @@ add_executable(etl_tests test_poly_span_fixed_extent.cpp test_pool.cpp test_pool_external_buffer.cpp + test_print.cpp test_priority_queue.cpp test_pseudo_moving_average.cpp test_quantize.cpp diff --git a/test/test_format.cpp b/test/test_format.cpp new file mode 100644 index 00000000..54f12823 --- /dev/null +++ b/test/test_format.cpp @@ -0,0 +1,490 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 BMW AG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "unit_test_framework.h" + +#include "etl/format.h" + +#include "etl/iterator.h" + +#if ETL_USING_CPP11 + +namespace +{ + using iterator = etl::back_insert_iterator; + + template + etl::istring& test_format(etl::istring& s, etl::format_string fmt, Args&&... args) + { + (void) etl::format_to(s, fmt, etl::forward(args)...); + return s; + } + + SUITE(test_format) + { + + //************************************************************************* + TEST(test_empty) + { + etl::string<100> s; + + const char* result = etl::format_to(s, ""); + CHECK_EQUAL(s.cbegin(), result); + CHECK_EQUAL("", s); + } + + //************************************************************************* + TEST(test_format) + { + etl::string<100> s; + + const char* result = etl::format_to(s, "abc"); + CHECK_EQUAL(s.cbegin() + 3, result); + CHECK_EQUAL("abc", s); + } + + //************************************************************************* + TEST(test_format_int) + { + etl::string<100> s; + + CHECK_EQUAL("1", test_format(s, "{}", 1)); + CHECK_EQUAL("123", test_format(s, "{}", 123)); + CHECK_EQUAL("4123", test_format(s, "{}", 4123)); + CHECK_EQUAL("1048962123", test_format(s, "{}", 1048962123)); + CHECK_EQUAL("1 2", test_format(s, "{} {}", 1, 2)); + CHECK_EQUAL("-123", test_format(s, "{}", -123)); + CHECK_EQUAL("-314748364", test_format(s, "{}", (int)-314748364)); + CHECK_EQUAL("2147483647", test_format(s, "{}", (int)2147483647)); + CHECK_EQUAL("-2147483648", test_format(s, "{}", (int)-2147483648)); + CHECK_EQUAL("0", test_format(s, "{}", 0)); + CHECK_EQUAL("-1", test_format(s, "{}", -1)); + } + + //************************************************************************* + TEST(test_format_unsigned_int) + { + etl::string<100> s; + + CHECK_EQUAL("0", test_format(s, "{}", static_cast(0U))); + CHECK_EQUAL("1", test_format(s, "{}", static_cast(1U))); + CHECK_EQUAL("12345678", test_format(s, "{}", static_cast(12345678U))); + CHECK_EQUAL("4123456780", test_format(s, "{}", static_cast(4123456780U))); + } + + //************************************************************************* + TEST(test_format_long_long_int) + { + etl::string<100> s; + + CHECK_EQUAL("-1", test_format(s, "{}", static_cast(-1LL))); + CHECK_EQUAL("0", test_format(s, "{}", static_cast(0LL))); + CHECK_EQUAL("1", test_format(s, "{}", static_cast(1LL))); + CHECK_EQUAL("-12345678", test_format(s, "{}", static_cast(-12345678LL))); + CHECK_EQUAL("-4123456780", test_format(s, "{}", static_cast(-4123456780LL))); + CHECK_EQUAL("-123456781234", test_format(s, "{}", static_cast(-123456781234LL))); + CHECK_EQUAL("-412345678012", test_format(s, "{}", static_cast(-412345678012LL))); + CHECK_EQUAL("12345678", test_format(s, "{}", static_cast(12345678LL))); + CHECK_EQUAL("4123456780", test_format(s, "{}", static_cast(4123456780LL))); + } + + //************************************************************************* + TEST(test_format_unsigned_long_long_int) + { + etl::string<100> s; + + CHECK_EQUAL("0", test_format(s, "{}", static_cast(0LL))); + CHECK_EQUAL("1", test_format(s, "{}", static_cast(1LL))); + CHECK_EQUAL("12345678", test_format(s, "{}", static_cast(12345678LL))); + CHECK_EQUAL("4123456780", test_format(s, "{}", static_cast(4123456780LL))); + CHECK_EQUAL("18446744073709551615", test_format(s, "{}", static_cast(18446744073709551615ULL))); + CHECK_EQUAL("1311768467463790320", test_format(s, "{}", static_cast(0x123456789ABCDEF0ULL))); + } + + //************************************************************************* + TEST(test_format_other_int) + { + etl::string<100> s; + + CHECK_EQUAL("34", test_format(s, "{}", static_cast(34))); + CHECK_EQUAL("-14", test_format(s, "{}", static_cast(-14))); + CHECK_EQUAL("6534", test_format(s, "{}", static_cast(6534))); + CHECK_EQUAL("-9414", test_format(s, "{}", static_cast(-9414))); + CHECK_EQUAL("236534", test_format(s, "{}", static_cast(236534))); + CHECK_EQUAL("-6759414", test_format(s, "{}", static_cast(-6759414))); + } + + //************************************************************************* + TEST(test_format_float) + { + etl::string<100> s; + + CHECK_EQUAL("1.0", test_format(s, "{}", 1.0f)); + CHECK_EQUAL("1.234567", test_format(s, "{}", 1.234567f)); + CHECK_EQUAL("1.234567", test_format(s, "{}", 1.2345678f)); + CHECK_EQUAL("1.125", test_format(s, "{}", 1.125f)); + } + + //************************************************************************* + TEST(test_format_double) + { + etl::string<100> s; + + CHECK_EQUAL("1.0", test_format(s, "{}", 1.0)); + CHECK_EQUAL("1.234564", test_format(s, "{}", 1.234564)); + CHECK_EQUAL("1.234567", test_format(s, "{}", 1.2345678)); + CHECK_EQUAL("1.5", test_format(s, "{}", 1.5)); + } + + //************************************************************************* + TEST(test_format_long_double) + { + etl::string<100> s; + + CHECK_EQUAL("1.0", test_format(s, "{}", 1.0l)); + auto& result = test_format(s, "{}", 1.234567l); + CHECK("1.234567" == result || "1.234566" == result); + CHECK_EQUAL("1.234567", test_format(s, "{}", 1.2345678l)); + CHECK_EQUAL("1.25", test_format(s, "{}", 1.25l)); + } + + //************************************************************************* + TEST(test_format_float_presentation) + { + etl::string<100> s; + + CHECK_EQUAL("1.000000e+00", test_format(s, "{:e}", 1.0f)); + CHECK_EQUAL("1.125000E+00", test_format(s, "{:E}", 1.125f)); + CHECK_EQUAL("-2.533324e-05", test_format(s, "{:e}", -0.00002533324f)); + CHECK_EQUAL("-2.500000e+11", test_format(s, "{:e}", -250000000000.0f)); + CHECK_EQUAL("1.000000", test_format(s, "{:f}", 1.0f)); + CHECK_EQUAL("1.125000", test_format(s, "{:F}", 1.125f)); + CHECK_EQUAL("1.000000", test_format(s, "{:g}", 1.0f)); + CHECK_EQUAL("1.125000", test_format(s, "{:G}", 1.125f)); + CHECK_EQUAL("1.000000e+10", test_format(s, "{:g}", 10000000000.0f)); + CHECK_EQUAL("1.000000E+10", test_format(s, "{:G}", 10000000000.0f)); + CHECK_EQUAL("nan", test_format(s, "{}", NAN)); + CHECK_EQUAL("nan", test_format(s, "{:e}", NAN)); + CHECK_EQUAL("NAN", test_format(s, "{:E}", NAN)); + CHECK_EQUAL("nan", test_format(s, "{:f}", NAN)); + CHECK_EQUAL("NAN", test_format(s, "{:F}", NAN)); + CHECK_EQUAL("nan", test_format(s, "{:g}", NAN)); + CHECK_EQUAL("NAN", test_format(s, "{:0.3G}", NAN)); + CHECK_EQUAL("inf", test_format(s, "{}", INFINITY)); + CHECK_EQUAL("inf", test_format(s, "{:e}", INFINITY)); + CHECK_EQUAL("INF", test_format(s, "{:E}", INFINITY)); + CHECK_EQUAL("inf", test_format(s, "{:f}", INFINITY)); + CHECK_EQUAL("INF", test_format(s, "{:F}", INFINITY)); + CHECK_EQUAL("inf", test_format(s, "{:g}", INFINITY)); + CHECK_EQUAL("INF", test_format(s, "{:0.3G}", INFINITY)); + CHECK_EQUAL("0x1.8p+0", test_format(s, "{:a}", 1.5f)); + CHECK_EQUAL("0X1.4CCCCCCCCCP+0", test_format(s, "{:A}", 1.3l)); + CHECK_EQUAL("0x2.49fp+4", test_format(s, "{:a}", 150000.0)); + CHECK_EQUAL("0x1.92a738p-5", test_format(s, "{:a}", 0.0000015f)); + CHECK_EQUAL("0x1.6345785d8ap+e", test_format(s, "{:a}", 100000000000000000.l)); + } + + //************************************************************************* + TEST(test_format_char_array) + { + etl::string<100> s; + + CHECK_EQUAL("s", test_format(s, "{}", "s")); + CHECK_EQUAL("abcd", test_format(s, "{}", "abcd")); + } + + //************************************************************************* + TEST(test_format_char) + { + etl::string<100> s; + + CHECK_EQUAL("a s b", test_format(s, "a {} b", 's')); + CHECK_EQUAL("a s b", test_format(s, "a {:c} b", 's')); + CHECK_EQUAL("a 's' b", test_format(s, "a {:?} b", 's')); + CHECK_EQUAL("a \t b", test_format(s, "a {} b", '\t')); + CHECK_EQUAL("a '\\t' b", test_format(s, "a {:?} b", '\t')); + CHECK_EQUAL("a '\\n' b", test_format(s, "a {:?} b", '\n')); + CHECK_EQUAL("a '\\r' b", test_format(s, "a {:?} b", '\r')); + CHECK_EQUAL("a '\\\"' b", test_format(s, "a {:?} b", '"')); + CHECK_EQUAL("a '\\'' b", test_format(s, "a {:?} b", '\'')); + CHECK_EQUAL("a '\\\\' b", test_format(s, "a {:?} b", '\\')); + CHECK_EQUAL("a '\\\\' b", test_format(s, "a {:?} b", '\\')); + CHECK_EQUAL("a 97 b", test_format(s, "a {:d} b", 'a')); + CHECK_EQUAL("a 61 b", test_format(s, "a {:X} b", 'a')); + CHECK_EQUAL("a 61 b", test_format(s, "a {:x} b", 'a')); + CHECK_EQUAL("a 0x61 b", test_format(s, "a {:#x} b", 'a')); + } + + //************************************************************************* + TEST(test_format_bool) + { + etl::string<100> s; + + CHECK_EQUAL("1false2true3", test_format(s, "1{}2{}3", false, true)); + CHECK_EQUAL("true", test_format(s, "{:s}", true)); + CHECK_EQUAL("1", test_format(s, "{:d}", true)); + CHECK_EQUAL("1", test_format(s, "{:X}", true)); + CHECK_EQUAL("01", test_format(s, "{:#o}", true)); + CHECK_EQUAL(" true", test_format(s, "{:10}", true)); + } + + //************************************************************************* + TEST(test_format_string_view) + { + etl::string<100> s; + etl::string_view sv("data1"); + + CHECK_EQUAL("data1", test_format(s, "{}", sv)); + CHECK_EQUAL("data1", test_format(s, "{:s}", sv)); + CHECK_THROW(test_format(s, "{:d}", sv), etl::bad_format_string_exception); + CHECK_EQUAL("data1 ", test_format(s, "{:10s}", sv)); + CHECK_EQUAL("data1 ", test_format(s, "{:<10s}", sv)); + CHECK_EQUAL(" data1", test_format(s, "{:>10s}", sv)); + CHECK_EQUAL(" data1 ", test_format(s, "{:^10s}", sv)); + CHECK_EQUAL("data1", test_format(s, "{:3}", sv)); + CHECK_EQUAL("dat", test_format(s, "{:.3s}", sv)); + CHECK_EQUAL("dat", test_format(s, "{:^.3s}", sv)); + CHECK_EQUAL(". dat !", test_format(s, ".{:^8.3s}!", sv)); + CHECK_EQUAL("^dat $", test_format(s, "^{:8.3s}$", sv)); + } + + //************************************************************************* + TEST(test_format_string_view_escaped) + { + etl::string<100> s; + etl::string_view sv("data1\n"); + + CHECK_EQUAL("\"data1\\n\"", test_format(s, "{:?}", sv)); + } + + //************************************************************************* + TEST(test_format_chars) + { + etl::string<100> s; + const char* chars = "data1"; + + CHECK_EQUAL("data1", test_format(s, "{}", chars)); + CHECK_EQUAL("data1", test_format(s, "{:s}", chars)); + CHECK_THROW(test_format(s, "{:d}", chars), etl::bad_format_string_exception); + CHECK_EQUAL("data1 ", test_format(s, "{:10s}", chars)); + CHECK_EQUAL("data1 ", test_format(s, "{:<10s}", chars)); + CHECK_EQUAL(" data1", test_format(s, "{:>10s}", chars)); + CHECK_EQUAL(" data1 ", test_format(s, "{:^10s}", chars)); + CHECK_EQUAL("data1", test_format(s, "{:3}", chars)); + CHECK_EQUAL("dat", test_format(s, "{:.3s}", chars)); + CHECK_EQUAL("dat", test_format(s, "{:^.3s}", chars)); + CHECK_EQUAL(". dat !", test_format(s, ".{:^8.3s}!", chars)); + CHECK_EQUAL("^dat $", test_format(s, "^{:8.3s}$", chars)); + } + + //************************************************************************* + TEST(test_format_chars_escaped) + { + etl::string<100> s; + const char* chars = "data2\n"; + + CHECK_EQUAL("\"data2\\n\"", test_format(s, "{:?}", chars)); + } + + //************************************************************************* + TEST(test_format_pointer) + { + etl::string<100> s; + + void* p = nullptr; + + CHECK_EQUAL("0x0", test_format(s, "{}", p)); + CHECK_EQUAL("0x0", test_format(s, "{:p}", p)); + CHECK_EQUAL("0X0", test_format(s, "{:P}", p)); + + if (sizeof(uintptr_t) == 8) + { + p = reinterpret_cast(0x123456789abcdef0ULL); + CHECK_EQUAL("0x123456789abcdef0", test_format(s, "{:p}", p)); + CHECK_EQUAL("0X123456789ABCDEF0", test_format(s, "{:P}", p)); + } + else if (sizeof(uintptr_t) == 4) + { + p = reinterpret_cast(0x1abcdef0ULL); + CHECK_EQUAL("0x1abcdef0", test_format(s, "{:p}", p)); + CHECK_EQUAL("0X1ABCDEF0", test_format(s, "{:P}", p)); + } + } + + //************************************************************************* + TEST(test_format_limit) + { + etl::string<10> s; + + CHECK_EQUAL("abcdefghij", test_format(s, "abcdefghijkl")); + CHECK_EQUAL("abcdefgh12", test_format(s, "abcdefgh{}", 123)); + } + + //************************************************************************* + TEST(test_format_escape) + { + etl::string<100> s; + + CHECK_EQUAL("abc{def", test_format(s, "abc{{def")); + CHECK_EQUAL("}abc", test_format(s, "}}abc")); + } + + //************************************************************************* + TEST(test_format_invalid) + { + etl::string<100> s; + + CHECK_THROW(test_format(s, "a{b}", 1), etl::bad_format_string_exception); // bad format index spec + // goal: rejected at compile time on C++20, error on <= C++17 + + CHECK_THROW(test_format(s, "a{b"), etl::bad_format_string_exception); // closing brace missing + // goal: rejected at compile time on C++20, error on <= C++17 + + CHECK_THROW(test_format(s, "a{b}"), etl::bad_format_string_exception); // arg missing + // goal: rejected at compile time on C++20, error on <= C++17 + + CHECK_THROW(test_format(s, "a}b"), etl::bad_format_string_exception); // bad format: only escaped }} allowed + // goal: rejected at compile time on C++20, error on <= C++17 + + CHECK_EQUAL("123", test_format(s, "{:}", 123)); // valid + CHECK_THROW(test_format(s, "{::}", 123), etl::bad_format_string_exception); // bad format spec + CHECK_THROW(test_format(s, "{1}", 123), etl::bad_format_string_exception); // bad index + } + + //************************************************************************* + TEST(test_format_indexed) + { + etl::string<100> s; + + CHECK_EQUAL("34 56", test_format(s, "{0} {1}", 34, 56)); + CHECK_EQUAL("56 34", test_format(s, "{1} {0}", 34, 56)); + CHECK_EQUAL("134 134", test_format(s, "{0} {0}", 134)); + CHECK_EQUAL("a b c d e f g h i j k l m n", test_format(s, "{0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12} {13}", 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n')); + } + + //************************************************************************* + TEST(test_formatted_size) + { + CHECK_EQUAL(0, etl::formatted_size("")); + CHECK_EQUAL(0, etl::formatted_size("{}", "")); + CHECK_EQUAL(5, etl::formatted_size("xyz{}", 12)); + CHECK_EQUAL(3, etl::formatted_size("{}", "abc")); + } + + //************************************************************************* + TEST(test_iterator) + { + etl::string<100> s; + + etl::istring::iterator result = etl::format_to(s.begin(), "{0} {1}", 34, 56); + s.uninitialized_resize(result - s.begin()); + CHECK_EQUAL("34 56", s); + + s.clear(); + etl::format_to(iterator(s), ""); + CHECK_EQUAL("", s); + + s.clear(); + etl::format_to(iterator(s), "{0} {1}", 65, 34); + CHECK_EQUAL("65 34", s); + + s = "abcdefghij"; + etl::format_to_n(s.begin(), 3, "xy{}", 123); + CHECK_EQUAL("xy1defghij", s); + } + + //************************************************************************* + TEST(test_format_spec_fill_and_align) + { + etl::string<100> s; + + CHECK_EQUAL("a 34", test_format(s, "a{:5}", 34)); + CHECK_EQUAL("a34", test_format(s, "a{:1}", 34)); + CHECK_EQUAL("a34", test_format(s, "a{:2}", 34)); + CHECK_EQUAL(" 34", test_format(s, "{:>4}", 34)); + CHECK_EQUAL(" 34 ", test_format(s, "{:^4}", 34)); + CHECK_EQUAL(" 34 ", test_format(s, "{:^5}", 34)); + CHECK_EQUAL(" -65 ", test_format(s, "{:^5}", -65)); + CHECK_EQUAL("34 ", test_format(s, "{:<4}", 34)); + CHECK_THROW(test_format(s, "a{:*5}", 34), etl::bad_format_string_exception); + CHECK_EQUAL("a*34**", test_format(s, "a{:*^5}", 34)); + CHECK_EQUAL("a*34**", test_format(s, "a{:*^5}", static_cast(34))); + CHECK_EQUAL("a***-341234567890****", test_format(s, "a{:*^20}", static_cast(-341234567890))); + CHECK_EQUAL("a****341234567890****", test_format(s, "a{:*^20}", static_cast(341234567890))); + CHECK_EQUAL(" x ", test_format(s, "{: ^20}", 'x')); + CHECK_EQUAL("x ", test_format(s, "{:20}", 'x')); + CHECK_EQUAL(" x", test_format(s, "{:>20}", 'x')); + CHECK_EQUAL("x ", test_format(s, "{:<20}", 'x')); + } + + //************************************************************************* + TEST(test_format_spec_sign) + { + etl::string<100> s; + + CHECK_EQUAL("34", test_format(s, "{:-}", 34)); + CHECK_EQUAL("-34", test_format(s, "{:-}", -34)); + CHECK_EQUAL("-34", test_format(s, "{:+}", -34)); + CHECK_EQUAL("+34", test_format(s, "{:+}", 34)); + CHECK_EQUAL("+0", test_format(s, "{:+}", 0)); + CHECK_EQUAL("0", test_format(s, "{:-}", 0)); + CHECK_EQUAL("210", test_format(s, "{:-}", 210)); + CHECK_EQUAL("-210", test_format(s, "{:-}", -210)); + CHECK_EQUAL(" 0", test_format(s, "{: }", 0)); + CHECK_EQUAL(" 546", test_format(s, "{: }", 546)); + CHECK_EQUAL("-546", test_format(s, "{: }", -546)); + } + + //************************************************************************* + TEST(test_format_int_presentation) + { + etl::string<100> s; + + CHECK_EQUAL("134", test_format(s, "{:d}", 134)); + CHECK_EQUAL("3f4", test_format(s, "{:x}", 0x3f4)); + CHECK_EQUAL("123456789abcdef0", test_format(s, "{:x}", 0x123456789abcdef0ULL)); + CHECK_EQUAL("0x3f4", test_format(s, "{:#x}", 0x3f4)); + CHECK_EQUAL("3F4", test_format(s, "{:X}", 0x3f4)); + CHECK_EQUAL("0X3F4", test_format(s, "{:#X}", 0x3f4)); + CHECK_EQUAL("34", test_format(s, "{:o}", 034)); + CHECK_EQUAL("034", test_format(s, "{:#o}", 034)); + CHECK_EQUAL("1010", test_format(s, "{:b}", 0b1010)); + CHECK_EQUAL("0b1010", test_format(s, "{:#b}", 0b1010)); + CHECK_EQUAL("1010", test_format(s, "{:B}", 0b1010)); + CHECK_EQUAL("0B1010", test_format(s, "{:#B}", 0b1010)); + CHECK_EQUAL("-0B1010", test_format(s, "{:#B}", -0b1010)); + CHECK_EQUAL("C", test_format(s, "{:c}", 67)); + CHECK_EQUAL("00067", test_format(s, "{:05d}", 67)); + CHECK_EQUAL("+00067", test_format(s, "{:+05d}", 67)); + CHECK_EQUAL("+0X00EF1", test_format(s, "{:+#05X}", 0xEF1)); + CHECK_THROW(test_format(s, "{:+#05.5X}", 0xEF1), etl::bad_format_string_exception); + } + } +} + +#endif \ No newline at end of file diff --git a/test/test_print.cpp b/test/test_print.cpp new file mode 100644 index 00000000..08573975 --- /dev/null +++ b/test/test_print.cpp @@ -0,0 +1,82 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 BMW AG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "unit_test_framework.h" + +#include "etl/print.h" + +#if ETL_USING_CPP11 + +namespace { + using iterator = etl::back_insert_iterator; + + etl::string<100> output; +} + +// to be implemented in a concrete project, typically printing to a serial console +extern "C" void etl_putchar(int c) +{ + iterator output_it(output); + *output_it = static_cast(c); +} + +namespace +{ + SUITE(test_format) + { + //************************************************************************* + TEST(test_print) + { + output.clear(); + etl::print("Hello Print!"); + CHECK_EQUAL("Hello Print!", output); + + output.clear(); + etl::print("{}", "Hello format!"); + CHECK_EQUAL("Hello format!", output); + + output.clear(); + etl::print("Hello {}!", 321); + CHECK_EQUAL("Hello 321!", output); + } + + //************************************************************************* + TEST(test_println) + { + output.clear(); + etl::println("Hello Println!"); + CHECK_EQUAL("Hello Println!\n", output); + + output.clear(); + etl::println(); + CHECK_EQUAL("\n", output); + } + } +} + +#endif \ No newline at end of file From d98c3ac9039c88575f877c019536eb0d1a899ba4 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 18 Dec 2025 08:59:42 +0000 Subject: [PATCH 053/298] Fixed issues with unsigned to signed conversion. Added format.h to VS2022 project. Added format.h to syntax check CMakeLists.txt --- include/etl/format.h | 13 +++++-------- test/syntax_check/CMakeLists.txt | 1 + test/syntax_check/format.h.t.cpp | 29 +++++++++++++++++++++++++++++ test/test_format.cpp | 4 ++-- test/vs2022/etl.vcxproj | 22 ++++++++++++++++++++++ test/vs2022/etl.vcxproj.filters | 9 +++++++++ 6 files changed, 68 insertions(+), 10 deletions(-) create mode 100644 test/syntax_check/format.h.t.cpp diff --git a/include/etl/format.h b/include/etl/format.h index e65df98b..d090457d 100644 --- a/include/etl/format.h +++ b/include/etl/format.h @@ -914,17 +914,17 @@ namespace etl { if (value <= 9) { - *it = '0' + value; + *it = static_cast('0' + static_cast::type>(value)); } else { if (spec.type.has_value() && is_uppercase(spec.type.value())) { - *it = 'A' + (value - 10); + *it = static_cast('A' + static_cast::type>(value - 10)); } else { - *it = 'a' + (value - 10); + *it = static_cast('a' + static_cast::type>(value - 10)); } } ++it; @@ -955,7 +955,7 @@ namespace etl { using UnsignedT = typename etl::make_unsigned::type; - UnsignedT unsigned_value = static_cast(value < 0 ? -value : value); + UnsignedT unsigned_value = etl::absolute_unsigned(value); size_t base = base_from_spec(spec); UnsignedT highest_digit = get_highest_digit(unsigned_value, base); @@ -2195,10 +2195,7 @@ namespace etl { private_format::output(fmt_context, c); } - }; - - // plain strings need it, back insert iterators don't: - //*fmt_context.out() = '\0'; + } return fmt_context.out(); } diff --git a/test/syntax_check/CMakeLists.txt b/test/syntax_check/CMakeLists.txt index 6cedf381..8df498b4 100644 --- a/test/syntax_check/CMakeLists.txt +++ b/test/syntax_check/CMakeLists.txt @@ -199,6 +199,7 @@ target_sources(tests PRIVATE flat_multiset.h.t.cpp flat_set.h.t.cpp fnv_1.h.t.cpp + format.h.t.cpp format_spec.h.t.cpp forward_list.h.t.cpp frame_check_sequence.h.t.cpp diff --git a/test/syntax_check/format.h.t.cpp b/test/syntax_check/format.h.t.cpp new file mode 100644 index 00000000..3943f7e4 --- /dev/null +++ b/test/syntax_check/format.h.t.cpp @@ -0,0 +1,29 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include diff --git a/test/test_format.cpp b/test/test_format.cpp index 54f12823..b04cefcc 100644 --- a/test/test_format.cpp +++ b/test/test_format.cpp @@ -80,8 +80,8 @@ namespace CHECK_EQUAL("1 2", test_format(s, "{} {}", 1, 2)); CHECK_EQUAL("-123", test_format(s, "{}", -123)); CHECK_EQUAL("-314748364", test_format(s, "{}", (int)-314748364)); - CHECK_EQUAL("2147483647", test_format(s, "{}", (int)2147483647)); - CHECK_EQUAL("-2147483648", test_format(s, "{}", (int)-2147483648)); + CHECK_EQUAL("2147483647", test_format(s, "{}", INT32_MAX)); + CHECK_EQUAL("-2147483648", test_format(s, "{}", INT32_MIN)); CHECK_EQUAL("0", test_format(s, "{}", 0)); CHECK_EQUAL("-1", test_format(s, "{}", -1)); } diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index da763fab..a79e639b 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -3465,6 +3465,7 @@ + @@ -6772,6 +6773,26 @@ true true + + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true true @@ -10321,6 +10342,7 @@ + diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index 1af8495a..6b03cb0b 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -1527,6 +1527,9 @@ ETL\Maths\CRC + + ETL\Utilities + @@ -3737,6 +3740,12 @@ Tests\Callbacks & Delegates + + Tests\Syntax Checks\Source + + + Tests\Strings + From 84f037b61645c549386580b42a4c2f614b5f02be Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 20 Dec 2025 12:51:01 +0000 Subject: [PATCH 054/298] Enhanced test and syntax check scripts to add non-scrolling command line header --- test/run-syntax-checks.sh | 40 +++++++++++++++++++++++++++++ test/run-tests.sh | 54 ++++++++++++++++++++++++++++++++++----- 2 files changed, 88 insertions(+), 6 deletions(-) diff --git a/test/run-syntax-checks.sh b/test/run-syntax-checks.sh index 18a65523..9991a54e 100644 --- a/test/run-syntax-checks.sh +++ b/test/run-syntax-checks.sh @@ -5,11 +5,32 @@ echo -e configuration_name="Configuration Name Not Set" +# Define colours FailColour='\033[38;2;255;128;128m' PassColour='\033[38;2;128;255;128m' TitleColour='\033[38;2;107;210;255m' HelpColour='\033[38;2;250;180;250m' NoColour='\033[0m' +CommandColour='\033[38;2;255;255;128m' + +# Save cursor position +tput sc + +# Clear screen +tput clear + +# Write fixed header on line 1 +tput cup 0 0 +echo $CommandColour "run-syntax-checks.sh" $1 $2 $3 $4 $5 $NoColour + +# Define scrolling region from line 2 to bottom +tput csr 2 $(($(tput lines) - 1)) + +# Restore cursor position +tput rc + +# Move cursor to start of scrollable area +tput cup 1 0 ParseGitBranch() { @@ -81,6 +102,25 @@ ChecksCompleted() echo "$NoColour" } +cleanup() +{ + # Reset scroll region to full screen + tput csr 0 $(($(tput lines) - 1)) + # Move cursor to a safe line (bottom of terminal) + tput cup $(($(tput lines) - 1)) 0 +} + +ctrl_c() +{ + # Reset scroll region to full screen + tput csr 0 $(($(tput lines) - 1)) + # Move cursor to a safe line (bottom of terminal) + tput cup $(($(tput lines) - 1)) 0 +} + +trap ctrl_c INT +trap cleanup EXIT + cd syntax_check || exit 1 echo "" > log.txt diff --git a/test/run-tests.sh b/test/run-tests.sh index e914114b..8f756794 100755 --- a/test/run-tests.sh +++ b/test/run-tests.sh @@ -4,16 +4,37 @@ shopt -s xpg_echo clear -export ASAN_OPTIONS=symbol_line=1 -export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-14/bin//llvm-symbolizer - -configuration_name="Configuration Name Not Set" - +# Define colours FailColour='\033[38;2;255;128;128m' PassColour='\033[38;2;128;255;128m' TitleColour='\033[38;2;107;210;255m' HelpColour='\033[38;2;250;180;250m' NoColour='\033[0m' +CommandColour='\033[38;2;255;255;128m' + +# Save cursor position +tput sc + +# Clear screen +tput clear + +# Write fixed header on line 1 +tput cup 0 0 +echo $CommandColour "run-tests.sh" $1 $2 $3 $4 $5 $NoColour + +# Define scrolling region from line 2 to bottom +tput csr 2 $(($(tput lines) - 1)) + +# Restore cursor position +tput rc + +# Move cursor to start of scrollable area +tput cup 1 0 + +export ASAN_OPTIONS=symbol_line=1 +export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-14/bin//llvm-symbolizer + +configuration_name="Configuration Name Not Set" ParseGitBranch() { @@ -179,10 +200,31 @@ fi etl_version_raw=$(cat ../version.txt) etl_version=$(echo $etl_version_raw | sed -e 's/\r//g') # Remove trailing \r +cleanup() +{ + # Reset scroll region to full screen + tput csr 0 $(($(tput lines) - 1)) + # Move cursor to a safe line (bottom of terminal) + tput cup $(($(tput lines) - 1)) 0 +} + +ctrl_c() +{ + # Reset scroll region to full screen + tput csr 0 $(($(tput lines) - 1)) + # Move cursor to a safe line (bottom of terminal) + tput cup $(($(tput lines) - 1)) 0 +} + +trap ctrl_c INT +trap cleanup EXIT + +cd syntax_check || exit 1 +echo "" > log.txt + #****************************************************************************** # Get the compiler versions #****************************************************************************** - while read i ; do CC=`echo $i | cut -d, -f1 | sed -e 's/ *$//'` MSG=`echo $i | cut -d, -f2 | sed -e 's/ *$//'` From 6b3e776eb52abecbcba02ec0ce332f5769add7d5 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 22 Dec 2025 21:02:17 +0000 Subject: [PATCH 055/298] Fixed filters on VS2022 project --- test/vs2022/etl.vcxproj.filters | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index 6b03cb0b..4f1f3320 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -1530,6 +1530,12 @@ ETL\Utilities + + UnitTest++\Header Files + + + UnitTest++\Header Files + @@ -3746,6 +3752,15 @@ Tests\Strings + + Tests\Syntax Checks\Source + + + Tests\Types + + + Tests\Callbacks & Delegates + From 922cfde45379515a7f5c0087c95e3aa57d74eea6 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 22 Dec 2025 21:02:54 +0000 Subject: [PATCH 056/298] Reverted scrolling changes on test script --- test/run-tests.sh | 54 ++++++----------------------------------------- 1 file changed, 6 insertions(+), 48 deletions(-) diff --git a/test/run-tests.sh b/test/run-tests.sh index 8f756794..e914114b 100755 --- a/test/run-tests.sh +++ b/test/run-tests.sh @@ -4,37 +4,16 @@ shopt -s xpg_echo clear -# Define colours +export ASAN_OPTIONS=symbol_line=1 +export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-14/bin//llvm-symbolizer + +configuration_name="Configuration Name Not Set" + FailColour='\033[38;2;255;128;128m' PassColour='\033[38;2;128;255;128m' TitleColour='\033[38;2;107;210;255m' HelpColour='\033[38;2;250;180;250m' NoColour='\033[0m' -CommandColour='\033[38;2;255;255;128m' - -# Save cursor position -tput sc - -# Clear screen -tput clear - -# Write fixed header on line 1 -tput cup 0 0 -echo $CommandColour "run-tests.sh" $1 $2 $3 $4 $5 $NoColour - -# Define scrolling region from line 2 to bottom -tput csr 2 $(($(tput lines) - 1)) - -# Restore cursor position -tput rc - -# Move cursor to start of scrollable area -tput cup 1 0 - -export ASAN_OPTIONS=symbol_line=1 -export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-14/bin//llvm-symbolizer - -configuration_name="Configuration Name Not Set" ParseGitBranch() { @@ -200,31 +179,10 @@ fi etl_version_raw=$(cat ../version.txt) etl_version=$(echo $etl_version_raw | sed -e 's/\r//g') # Remove trailing \r -cleanup() -{ - # Reset scroll region to full screen - tput csr 0 $(($(tput lines) - 1)) - # Move cursor to a safe line (bottom of terminal) - tput cup $(($(tput lines) - 1)) 0 -} - -ctrl_c() -{ - # Reset scroll region to full screen - tput csr 0 $(($(tput lines) - 1)) - # Move cursor to a safe line (bottom of terminal) - tput cup $(($(tput lines) - 1)) 0 -} - -trap ctrl_c INT -trap cleanup EXIT - -cd syntax_check || exit 1 -echo "" > log.txt - #****************************************************************************** # Get the compiler versions #****************************************************************************** + while read i ; do CC=`echo $i | cut -d, -f1 | sed -e 's/ *$//'` MSG=`echo $i | cut -d, -f2 | sed -e 's/ *$//'` From c8fa20620ebb219614df42d100f83150f97753df Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 23 Dec 2025 07:03:46 +0000 Subject: [PATCH 057/298] Fixed C++11 issue with constexpr in exception.h --- include/etl/exception.h | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/include/etl/exception.h b/include/etl/exception.h index c73fef1c..6caebe14 100644 --- a/include/etl/exception.h +++ b/include/etl/exception.h @@ -34,8 +34,7 @@ SOFTWARE. #include "platform.h" #if ETL_USING_STD_EXCEPTION -#include - + #include #define ETL_EXCEPTION_CONSTEXPR #else #define ETL_EXCEPTION_CONSTEXPR ETL_CONSTEXPR @@ -65,7 +64,7 @@ namespace etl /// Constructor. //************************************************************************* #if defined(ETL_VERBOSE_ERRORS) - ETL_CONSTEXPR + ETL_EXCEPTION_CONSTEXPR exception(string_type reason_, string_type file_, numeric_type line_) : reason_text(reason_), file_text(file_), @@ -73,12 +72,12 @@ namespace etl { } #elif defined(ETL_MINIMAL_ERRORS) - ETL_CONSTEXPR + ETL_EXCEPTION_CONSTEXPR exception(string_type /*reason_*/, string_type /*file_*/, numeric_type /*line_*/) { } #else - ETL_CONSTEXPR + ETL_EXCEPTION_CONSTEXPR exception(string_type reason_, string_type /*file_*/, numeric_type /*line_*/) : reason_text(reason_) { @@ -107,7 +106,7 @@ namespace etl /// Gets the file for the exception. /// \return const char* to the file. //*************************************************************************** - ETL_CONSTEXPR + ETL_EXCEPTION_CONSTEXPR string_type file_name() const { #if defined(ETL_VERBOSE_ERRORS) @@ -121,7 +120,7 @@ namespace etl /// Gets the line for the exception. /// \return int as line number. //*************************************************************************** - ETL_CONSTEXPR + ETL_EXCEPTION_CONSTEXPR numeric_type line_number() const { #if defined(ETL_VERBOSE_ERRORS) From c798bd337bbcc177d06ed93cd2a83e2870acc550 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 23 Dec 2025 07:04:31 +0000 Subject: [PATCH 058/298] Revert script to full scrolling terminal style --- test/run-syntax-checks.sh | 40 --------------------------------------- 1 file changed, 40 deletions(-) diff --git a/test/run-syntax-checks.sh b/test/run-syntax-checks.sh index 9991a54e..18a65523 100644 --- a/test/run-syntax-checks.sh +++ b/test/run-syntax-checks.sh @@ -5,32 +5,11 @@ echo -e configuration_name="Configuration Name Not Set" -# Define colours FailColour='\033[38;2;255;128;128m' PassColour='\033[38;2;128;255;128m' TitleColour='\033[38;2;107;210;255m' HelpColour='\033[38;2;250;180;250m' NoColour='\033[0m' -CommandColour='\033[38;2;255;255;128m' - -# Save cursor position -tput sc - -# Clear screen -tput clear - -# Write fixed header on line 1 -tput cup 0 0 -echo $CommandColour "run-syntax-checks.sh" $1 $2 $3 $4 $5 $NoColour - -# Define scrolling region from line 2 to bottom -tput csr 2 $(($(tput lines) - 1)) - -# Restore cursor position -tput rc - -# Move cursor to start of scrollable area -tput cup 1 0 ParseGitBranch() { @@ -102,25 +81,6 @@ ChecksCompleted() echo "$NoColour" } -cleanup() -{ - # Reset scroll region to full screen - tput csr 0 $(($(tput lines) - 1)) - # Move cursor to a safe line (bottom of terminal) - tput cup $(($(tput lines) - 1)) 0 -} - -ctrl_c() -{ - # Reset scroll region to full screen - tput csr 0 $(($(tput lines) - 1)) - # Move cursor to a safe line (bottom of terminal) - tput cup $(($(tput lines) - 1)) 0 -} - -trap ctrl_c INT -trap cleanup EXIT - cd syntax_check || exit 1 echo "" > log.txt From 96e322993388e869b2699fb2339951fc0100e63a Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 23 Dec 2025 07:05:23 +0000 Subject: [PATCH 059/298] Fixed issue with use of binary constants with C++11 in etl::format tests --- test/test_format.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/test_format.cpp b/test/test_format.cpp index b04cefcc..31bdecce 100644 --- a/test/test_format.cpp +++ b/test/test_format.cpp @@ -473,11 +473,13 @@ namespace CHECK_EQUAL("0X3F4", test_format(s, "{:#X}", 0x3f4)); CHECK_EQUAL("34", test_format(s, "{:o}", 034)); CHECK_EQUAL("034", test_format(s, "{:#o}", 034)); +#if ETL_USING_CPP14 CHECK_EQUAL("1010", test_format(s, "{:b}", 0b1010)); CHECK_EQUAL("0b1010", test_format(s, "{:#b}", 0b1010)); CHECK_EQUAL("1010", test_format(s, "{:B}", 0b1010)); CHECK_EQUAL("0B1010", test_format(s, "{:#B}", 0b1010)); CHECK_EQUAL("-0B1010", test_format(s, "{:#B}", -0b1010)); +#endif CHECK_EQUAL("C", test_format(s, "{:c}", 67)); CHECK_EQUAL("00067", test_format(s, "{:05d}", 67)); CHECK_EQUAL("+00067", test_format(s, "{:+05d}", 67)); From 342e43e28befbfad9e565641c72e0301cb868010 Mon Sep 17 00:00:00 2001 From: mike919192 <91038685+mike919192@users.noreply.github.com> Date: Tue, 23 Dec 2025 02:09:37 -0500 Subject: [PATCH 060/298] Fix discrepency with STL in max element and minmax element (#1245) --- include/etl/algorithm.h | 4 ++-- test/test_algorithm.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/etl/algorithm.h b/include/etl/algorithm.h index 08ebfeda..88b8f7b6 100644 --- a/include/etl/algorithm.h +++ b/include/etl/algorithm.h @@ -1528,7 +1528,7 @@ namespace etl while (begin != end) { - if (!compare(*begin, *maximum)) + if (compare(*maximum, *begin)) { maximum = begin; } @@ -1582,7 +1582,7 @@ namespace etl minimum = begin; } - if (compare(*maximum, *begin)) + if (!compare(*begin, *maximum)) { maximum = begin; } diff --git a/test/test_algorithm.cpp b/test/test_algorithm.cpp index b7573bb0..3fcfa1c4 100644 --- a/test/test_algorithm.cpp +++ b/test/test_algorithm.cpp @@ -53,7 +53,7 @@ namespace std::mt19937 urng(rng()); using Vector = std::vector; - Vector data = { 2, 1, 4, 3, 6, 5, 8, 7, 10, 9 }; + Vector data = { 2, 1, 1, 4, 3, 6, 5, 8, 7, 10, 10, 9 }; using VectorM = std::vector; From 339f5abf0fea8de08414ae43895afe3faa29dd4d Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 23 Dec 2025 07:10:10 +0000 Subject: [PATCH 061/298] Updated ignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 068e7602..ced27dae 100644 --- a/.gitignore +++ b/.gitignore @@ -411,3 +411,4 @@ examples/UniquePtrWithPool/UniquePtrWithPool test/vs2022/Debug Clang C++20 - Optimised -O2 include/etl/header_file_list.txt temp +test/syntax_check/build-make From 819d813a12b3cd2b85ab189ff7f98791263d1927 Mon Sep 17 00:00:00 2001 From: mike919192 <91038685+mike919192@users.noreply.github.com> Date: Tue, 23 Dec 2025 02:11:07 -0500 Subject: [PATCH 062/298] Fix no check macros (#1244) --- include/etl/error_handler.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/etl/error_handler.h b/include/etl/error_handler.h index 425f68ef..be2af4d1 100644 --- a/include/etl/error_handler.h +++ b/include/etl/error_handler.h @@ -305,9 +305,9 @@ namespace etl #define ETL_ASSERT_OR_RETURN(b, e) static_cast(sizeof(b)) // Does nothing. #define ETL_ASSERT_OR_RETURN_VALUE(b, e, v) static_cast(sizeof(b)) // Does nothing. - #define ETL_ASSERT_FAIL(e) static_cast(sizeof(b)) // Does nothing. - #define ETL_ASSERT_FAIL_AND_RETURN(e) static_cast(sizeof(b)) // Does nothing. - #define ETL_ASSERT_FAIL_AND_RETURN_VALUE(e, v) static_cast(sizeof(b)) // Does nothing. + #define ETL_ASSERT_FAIL(e) ETL_DO_NOTHING // Does nothing. + #define ETL_ASSERT_FAIL_AND_RETURN(e) ETL_DO_NOTHING // Does nothing. + #define ETL_ASSERT_FAIL_AND_RETURN_VALUE(e, v) ETL_DO_NOTHING // Does nothing. #elif defined(ETL_USE_ASSERT_FUNCTION) #define ETL_ASSERT(b, e) do {if (!(b)) ETL_UNLIKELY {etl::private_error_handler::assert_handler<0>::assert_function_ptr((e));}} while(false) // If the condition fails, calls the assert function #define ETL_ASSERT_OR_RETURN(b, e) do {if (!(b)) ETL_UNLIKELY {etl::private_error_handler::assert_handler<0>::assert_function_ptr((e)); return;}} while(false) // If the condition fails, calls the assert function and return From 94d960748d1c6ec05c2947a44e3d40a9d9bb935b Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 23 Dec 2025 08:28:47 +0000 Subject: [PATCH 063/298] Fixed incompatibilities with C++03 --- include/etl/expected.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/etl/expected.h b/include/etl/expected.h index 948df290..722c411e 100644 --- a/include/etl/expected.h +++ b/include/etl/expected.h @@ -51,7 +51,7 @@ namespace etl struct is_expected : etl::false_type {}; template - struct is_expected> : etl::true_type {}; + struct is_expected > : etl::true_type {}; //*************************************************************************** /// Base exception for et::expected @@ -853,6 +853,7 @@ namespace etl typedef etl::variant storage_type; storage_type storage; +#if ETL_USING_CPP11 template ::value>::type> auto transform_impl(F&& f, TExp&& exp) const -> expected { @@ -918,6 +919,7 @@ namespace etl return expected(unexpected(etl::invoke(etl::forward(f), etl::forward(etl::get(exp.storage))))); } } +#endif }; //***************************************************************************** @@ -1226,6 +1228,7 @@ namespace etl etl::variant storage; +#if ETL_USING_CPP11 template ::value>::type> auto transform_impl(F&& f, TExp&& exp) const -> expected { @@ -1291,6 +1294,7 @@ namespace etl return expected(unexpected(etl::invoke(etl::forward(f), etl::forward(etl::get(exp.storage))))); } } +#endif }; } From 46a937fc3430c8fe990fd2cc83e9dc57a0d4bb0b 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 064/298] implement .begin() and .end() for etl::optional (#1246) Co-authored-by: nikdelgado --- include/etl/optional.h | 38 +++++++++++++++++++ test/test_optional.cpp | 86 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 123 insertions(+), 1 deletion(-) 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..12e17934 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); + } + }; } 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 065/298] 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); + } } } From 16389b3eea21bb7e8e07b9f1ff0dfe4088a939bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1nyi=20B=C3=A9la?= <91312503+ivanyib@users.noreply.github.com> Date: Thu, 1 Jan 2026 10:56:25 +0100 Subject: [PATCH 066/298] Indirect vector checks (#1239) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Check in indirect_vector::emplace_back if the vector is full, when push pop checks are requested * Add extra checks to indirect_vector * Fix emplace in indirect_vector not taking const_iterator * Fix usage of ipool::create in indirect_vector, so that there are no intermitten objects created --------- Co-authored-by: Béla Iványi --- include/etl/indirect_vector.h | 94 +++++++---- test/test_indirect_vector.cpp | 93 +++++++++++ test/test_indirect_vector_external_buffer.cpp | 149 ++++++++++++++++++ 3 files changed, 308 insertions(+), 28 deletions(-) diff --git a/include/etl/indirect_vector.h b/include/etl/indirect_vector.h index 36d6c695..c0d41438 100644 --- a/include/etl/indirect_vector.h +++ b/include/etl/indirect_vector.h @@ -292,6 +292,11 @@ namespace etl return lhs.lookup_itr < rhs.lookup_itr; } + friend bool operator <= (const iterator& lhs, const iterator& rhs) + { + return lhs.lookup_itr <= rhs.lookup_itr; + } + private: iterator(indirect_iterator itr_) @@ -424,6 +429,11 @@ namespace etl return lhs.lookup_itr < rhs.lookup_itr; } + friend bool operator <= (const const_iterator& lhs, const const_iterator& rhs) + { + return lhs.lookup_itr <= rhs.lookup_itr; + } + private: typedef typename etl::ivector::const_iterator lookup_itr_t; @@ -757,7 +767,7 @@ namespace etl //********************************************************************* void push_back(const_reference value) { - ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(size() != capacity(), ETL_ERROR(vector_full)); + ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(!full(), ETL_ERROR(vector_full)); T* p = storage.create(value); lookup.push_back(p); @@ -771,7 +781,7 @@ namespace etl //********************************************************************* void push_back(rvalue_reference value) { - ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(size() != capacity(), ETL_ERROR(vector_full)); + ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(!full(), ETL_ERROR(vector_full)); T* p = storage.create(etl::move(value)); lookup.push_back(p); @@ -787,6 +797,8 @@ namespace etl template reference emplace_back(Args && ... args) { + ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(vector_full)); + T* p = storage.create(etl::forward(args)...); lookup.push_back(p); return back(); @@ -799,7 +811,9 @@ namespace etl //********************************************************************* reference emplace_back() { - T* p = storage.create(T()); + ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(vector_full)); + + T* p = storage.create(); lookup.push_back(p); return back(); } @@ -812,7 +826,9 @@ namespace etl template reference emplace_back(const T1& value1) { - T* p = storage.create(T(value1)); + ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(vector_full)); + + T* p = storage.create(value1); lookup.push_back(p); return back(); } @@ -825,7 +841,9 @@ namespace etl template reference emplace_back(const T1& value1, const T2& value2) { - T* p = storage.create(T(value1, value2)); + ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(vector_full)); + + T* p = storage.create(value1, value2); lookup.push_back(p); return back(); } @@ -838,7 +856,9 @@ namespace etl template reference emplace_back(const T1& value1, const T2& value2, const T3& value3) { - T* p = storage.create(T(value1, value2, value3)); + ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(vector_full)); + + T* p = storage.create(value1, value2, value3); lookup.push_back(p); return back(); } @@ -851,7 +871,9 @@ namespace etl template reference emplace_back(const T1& value1, const T2& value2, const T3& value3, const T4& value4) { - T* p = storage.create(T(value1, value2, value3, value4)); + ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(vector_full)); + + T* p = storage.create(value1, value2, value3, value4); lookup.push_back(p); return back(); } @@ -862,7 +884,7 @@ namespace etl //************************************************************************* void pop_back() { - ETL_ASSERT(!empty(), ETL_ERROR(vector_empty)); + ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(!empty(), ETL_ERROR(vector_empty)); reference object = back(); storage.destroy(etl::addressof(object)); @@ -878,8 +900,9 @@ namespace etl iterator insert(const_iterator position, const_reference value) { ETL_ASSERT(size() != capacity(), ETL_ERROR(vector_full)); + ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(vector_out_of_bounds)); - T* p = storage.create(T(value)); + T* p = storage.create(value); position = iterator(lookup.insert(position.lookup_itr, p)); return to_iterator(position); @@ -895,8 +918,9 @@ namespace etl iterator insert(const_iterator position, rvalue_reference value) { ETL_ASSERT(size() != capacity(), ETL_ERROR(vector_full)); + ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(vector_out_of_bounds)); - T* p = storage.create(T(etl::move(value))); + T* p = storage.create(etl::move(value)); position = iterator(lookup.insert(position.lookup_itr, p)); return to_iterator(position); @@ -908,68 +932,74 @@ namespace etl //************************************************************************* #if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_VECTOR_FORCE_CPP03_IMPLEMENTATION) template - iterator emplace(iterator position, Args && ... args) + iterator emplace(const_iterator position, Args && ... args) { ETL_ASSERT(!full(), ETL_ERROR(vector_full)); + ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(vector_out_of_bounds)); - T* p = storage.create(T(etl::forward(args)...)); + T* p = storage.create(etl::forward(args)...); position = iterator(lookup.insert(position.lookup_itr, p)); - return position; + return to_iterator(position); } #else - iterator emplace(iterator position) + iterator emplace(const_iterator position) { ETL_ASSERT(!full(), ETL_ERROR(vector_full)); + ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(vector_out_of_bounds)); - T* p = storage.create(T()); + T* p = storage.create(); position = iterator(lookup.insert(position.lookup_itr, p)); - return position; + return to_iterator(position); } template - iterator emplace(iterator position, const T1& value1) + iterator emplace(const_iterator position, const T1& value1) { ETL_ASSERT(!full(), ETL_ERROR(vector_full)); + ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(vector_out_of_bounds)); - T* p = storage.create(T(value1)); + T* p = storage.create(value1); position = iterator(lookup.insert(position.lookup_itr, p)); - return position; + return to_iterator(position); } template - iterator emplace(iterator position, const T1& value1, const T2& value2) + iterator emplace(const_iterator position, const T1& value1, const T2& value2) { ETL_ASSERT(!full(), ETL_ERROR(vector_full)); + ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(vector_out_of_bounds)); - T* p = storage.create(T(value1, value2)); + T* p = storage.create(value1, value2); position = iterator(lookup.insert(position.lookup_itr, p)); - return position; + return to_iterator(position); } template - iterator emplace(iterator position, const T1& value1, const T2& value2, const T3& value3) + iterator emplace(const_iterator position, const T1& value1, const T2& value2, const T3& value3) { ETL_ASSERT(!full(), ETL_ERROR(vector_full)); + ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(vector_out_of_bounds)); - T* p = storage.create(T(value1, value2, value3)); + T* p = storage.create(value1, value2, value3); position = iterator(lookup.insert(position.lookup_itr, p)); - return position; + return to_iterator(position); } template - iterator emplace(iterator position, const T1& value1, const T2& value2, const T3& value3, const T4& value4) + iterator emplace(const_iterator position, const T1& value1, const T2& value2, const T3& value3, const T4& value4) { ETL_ASSERT(!full(), ETL_ERROR(vector_full)); + ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(vector_out_of_bounds)); - T* p = storage.create(T(value1, value2, value3, value4)); + T* p = storage.create(value1, value2, value3, value4); position = iterator(lookup.insert(position.lookup_itr, p)); - return position; + return to_iterator(position); } #endif @@ -983,6 +1013,7 @@ namespace etl iterator insert(const_iterator position, size_t n, parameter_t value) { ETL_ASSERT((size() + n) <= capacity(), ETL_ERROR(vector_full)); + ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(vector_out_of_bounds)); iterator position_ = to_iterator(position); @@ -1012,6 +1043,7 @@ namespace etl size_t count = size_t(etl::distance(first, last)); ETL_ASSERT((size() + count) <= capacity(), ETL_ERROR(vector_full)); + ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(vector_out_of_bounds)); // Make space for the new lookup pointers. typename etl::ivector::iterator lookup_itr = to_iterator(position).lookup_itr; @@ -1034,6 +1066,8 @@ namespace etl //********************************************************************* iterator erase(iterator i_element) { + ETL_ASSERT_CHECK_EXTRA(cbegin() <= i_element && i_element < cend(), ETL_ERROR(vector_out_of_bounds)); + storage.destroy(etl::addressof(*i_element)); return iterator(lookup.erase(i_element.lookup_itr)); @@ -1046,6 +1080,8 @@ namespace etl //********************************************************************* iterator erase(const_iterator i_element) { + ETL_ASSERT_CHECK_EXTRA(cbegin() <= i_element && i_element < cend(), ETL_ERROR(vector_out_of_bounds)); + storage.destroy(etl::addressof(*i_element)); return iterator(lookup.erase(i_element.lookup_itr)); @@ -1061,6 +1097,8 @@ namespace etl //********************************************************************* iterator erase(const_iterator first, const_iterator last) { + ETL_ASSERT_CHECK_EXTRA(cbegin() <= first && first <= last && last <= cend(), ETL_ERROR(vector_out_of_bounds)); + iterator element = to_iterator(first); while (element != last) diff --git a/test/test_indirect_vector.cpp b/test/test_indirect_vector.cpp index cd639a6b..26b61ac8 100644 --- a/test/test_indirect_vector.cpp +++ b/test/test_indirect_vector.cpp @@ -536,6 +536,8 @@ namespace { CHECK_EQUAL(data[i], compare_data[i]); } + + CHECK_THROW(data[data.size()], etl::vector_out_of_bounds); } //************************************************************************* @@ -549,6 +551,8 @@ namespace { CHECK_EQUAL(data[i], compare_data[i]); } + + CHECK_THROW(data[data.size()], etl::vector_out_of_bounds); } //************************************************************************* @@ -586,6 +590,9 @@ namespace DataNDC data(initial_data.begin(), initial_data.end()); CHECK(data.front() == compare_data.front()); + + DataNDC emptyData; + CHECK_THROW(emptyData.front(), etl::vector_out_of_bounds); } //************************************************************************* @@ -595,6 +602,9 @@ namespace const DataNDC data(initial_data.begin(), initial_data.end()); CHECK(data.front() == compare_data.front()); + + const DataNDC emptyData; + CHECK_THROW(emptyData.front(), etl::vector_out_of_bounds); } //************************************************************************* @@ -604,6 +614,9 @@ namespace DataNDC data(initial_data.begin(), initial_data.end()); CHECK(data.back() == compare_data.back()); + + DataNDC emptyData; + CHECK_THROW(emptyData.back(), etl::vector_out_of_bounds); } //************************************************************************* @@ -613,6 +626,9 @@ namespace const DataNDC data(initial_data.begin(), initial_data.end()); CHECK(data.back() == compare_data.back()); + + const DataNDC emptyData; + CHECK_THROW(emptyData.back(), etl::vector_out_of_bounds); } //************************************************************************* @@ -759,6 +775,21 @@ namespace CHECK_EQUAL(back, data.back()); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_back_excess) + { + DataNDC data; + + for (size_t i = 0UL; i < SIZE; ++i) + { + std::string value(" "); + value[0] = char('A' + i); + data.emplace_back(value); + } + + CHECK_THROW(data.emplace_back("Z"), etl::vector_full); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_push_back_unique_ptr) { @@ -996,6 +1027,18 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value_outofbounds) + { + const size_t INITIAL_SIZE = 5; + const NDC INITIAL_VALUE("1"); + + DataNDC data; + DataNDC data2; + data.assign(initial_data.begin(), initial_data.begin() + INITIAL_SIZE); + CHECK_THROW(data.insert(data2.cbegin(), INITIAL_VALUE), etl::vector_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_emplace_position_default_value) { @@ -1048,6 +1091,18 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_position_value_outofbounds) + { + const size_t INITIAL_SIZE = 5; + const std::string INITIAL_VALUE("1"); + + DataNDC data; + DataNDC data2; + data.assign(initial_data.begin(), initial_data.begin() + INITIAL_SIZE); + CHECK_THROW(data.emplace(data2.begin(), INITIAL_VALUE), etl::vector_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_value_excess) { @@ -1097,6 +1152,17 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) + { + const NDC INITIAL_VALUE("1"); + + DataNDC data; + DataNDC data2; + + CHECK_THROW(data.insert(data2.end(), 1, INITIAL_VALUE), etl::vector_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_n_value_excess) { @@ -1151,6 +1217,15 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_outofbounds) + { + DataNDC data; + DataNDC data2; + + CHECK_THROW(data.insert(data2.end(), insert_data.begin(), insert_data.end()), etl::vector_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_range_excess) { @@ -1195,6 +1270,15 @@ namespace CHECK(is_equal); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_outofbounds) + { + DataNDC data(initial_data.begin(), initial_data.end()); + + CHECK_THROW(data.erase(data.end()), etl::vector_out_of_bounds); + CHECK_THROW(data.erase(data.cend()), etl::vector_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_range) { @@ -1214,6 +1298,15 @@ namespace CHECK(is_equal); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range_outofbounds) + { + DataNDC data(initial_data.begin(), initial_data.end()); + DataNDC data2(initial_data.begin(), initial_data.end()); + + CHECK_THROW(data.erase(data2.begin(), data2.end()), etl::vector_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_clear) { diff --git a/test/test_indirect_vector_external_buffer.cpp b/test/test_indirect_vector_external_buffer.cpp index 4ce54e75..3f94bc71 100644 --- a/test/test_indirect_vector_external_buffer.cpp +++ b/test/test_indirect_vector_external_buffer.cpp @@ -646,6 +646,8 @@ namespace { CHECK_EQUAL(data[i], compare_data[i]); } + + CHECK_THROW(data[data.size()], etl::vector_out_of_bounds); } //************************************************************************* @@ -662,6 +664,8 @@ namespace { CHECK_EQUAL(data[i], compare_data[i]); } + + CHECK_THROW(data[data.size()], etl::vector_out_of_bounds); } //************************************************************************* @@ -708,6 +712,12 @@ namespace DataNDC data(initial_data.begin(), initial_data.end(), lookup, pool); CHECK(data.front() == compare_data.front()); + + LookupNDC lookup2; + PoolNDC pool2; + + DataNDC data2(lookup2, pool2); + CHECK_THROW(data2.front(), etl::vector_out_of_bounds); } //************************************************************************* @@ -720,6 +730,12 @@ namespace const DataNDC data(initial_data.begin(), initial_data.end(), lookup, pool); CHECK(data.front() == compare_data.front()); + + LookupNDC lookup2; + PoolNDC pool2; + + const DataNDC data2(lookup2, pool2); + CHECK_THROW(data2.front(), etl::vector_out_of_bounds); } //************************************************************************* @@ -732,6 +748,12 @@ namespace DataNDC data(initial_data.begin(), initial_data.end(), lookup, pool); CHECK(data.back() == compare_data.back()); + + LookupNDC lookup2; + PoolNDC pool2; + + DataNDC data2(lookup2, pool2); + CHECK_THROW(data2.back(), etl::vector_out_of_bounds); } //************************************************************************* @@ -744,6 +766,12 @@ namespace const DataNDC data(initial_data.begin(), initial_data.end(), lookup, pool); CHECK(data.back() == compare_data.back()); + + LookupNDC lookup2; + PoolNDC pool2; + + const DataNDC data2(lookup2, pool2); + CHECK_THROW(data2.back(), etl::vector_out_of_bounds); } //************************************************************************* @@ -875,6 +903,24 @@ namespace CHECK(is_equal); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_back_excess) + { + LookupNDC lookup; + PoolNDC pool; + + DataNDC data(lookup, pool); + + for (size_t i = 0UL; i < SIZE; ++i) + { + std::string value(" "); + value[0] = char('A' + i); + data.emplace_back(value); + } + + CHECK_THROW(data.emplace_back("Z"), etl::vector_full); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_push_back_unique_ptr) { @@ -1028,6 +1074,26 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + const NDC INITIAL_VALUE("1"); + + LookupNDC lookup; + PoolNDC pool; + + DataNDC data(lookup, pool); + + LookupNDC lookup2; + PoolNDC pool2; + + DataNDC data2(lookup2, pool2); + + data.assign(initial_data.begin(), initial_data.begin() + INITIAL_SIZE); + CHECK_THROW(data.insert(data2.cbegin(), INITIAL_VALUE), etl::vector_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_emplace_position_value) { @@ -1058,6 +1124,25 @@ namespace } } + TEST_FIXTURE(SetupFixture, test_emplace_position_value_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + const std::string INITIAL_VALUE("1"); + + LookupNDC lookup; + PoolNDC pool; + + DataNDC data(lookup, pool); + + LookupNDC lookup2; + PoolNDC pool2; + + DataNDC data2(lookup2, pool2); + + data.assign(initial_data.begin(), initial_data.begin() + INITIAL_SIZE); + CHECK_THROW(data.emplace(data2.begin(), INITIAL_VALUE), etl::vector_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_value_excess) { @@ -1113,6 +1198,24 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) + { + const NDC INITIAL_VALUE("1"); + + LookupNDC lookup; + PoolNDC pool; + + DataNDC data(lookup, pool); + + LookupNDC lookup2; + PoolNDC pool2; + + DataNDC data2(lookup2, pool2); + + CHECK_THROW(data.insert(data2.end(), 1, INITIAL_VALUE), etl::vector_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_n_value_excess) { @@ -1173,6 +1276,24 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_outofbounds) + { + const NDC INITIAL_VALUE("1"); + + LookupNDC lookup; + PoolNDC pool; + + DataNDC data(lookup, pool); + + LookupNDC lookup2; + PoolNDC pool2; + + DataNDC data2(lookup2, pool2); + + CHECK_THROW(data.insert(data2.end(), insert_data.begin(), insert_data.end()), etl::vector_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_range_excess) { @@ -1223,6 +1344,18 @@ namespace CHECK(is_equal); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_outofbounds) + { + LookupNDC lookup; + PoolNDC pool; + + DataNDC data(initial_data.begin(), initial_data.end(), lookup, pool); + + CHECK_THROW(data.erase(data.end()), etl::vector_out_of_bounds); + CHECK_THROW(data.erase(data.cend()), etl::vector_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_range) { @@ -1245,6 +1378,22 @@ namespace CHECK(is_equal); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range_outofbounds) + { + LookupNDC lookup; + PoolNDC pool; + + DataNDC data(initial_data.begin(), initial_data.end(), lookup, pool); + + LookupNDC lookup2; + PoolNDC pool2; + + DataNDC data2(initial_data.begin(), initial_data.end(), lookup2, pool2); + + CHECK_THROW(data.erase(data2.begin(), data2.end()), etl::vector_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_clear) { From 0c3dafa09e4213fe52c2c8d7f0d43b984012036f Mon Sep 17 00:00:00 2001 From: littepoint <38397123+littepointR@users.noreply.github.com> Date: Sun, 4 Jan 2026 18:38:09 +0800 Subject: [PATCH 067/298] feat(mutex): Add ThreadX mutex support (#1252) * feat(mutex): Add ThreadX mutex support * fix(mutex): Fix ThreadX mutex naming and destructor issues Correct the header guard macro naming error from ETL_MUTEX_THREAD to ETL_MUTEX_THREADX Add mutex destructor to properly release resources Modify mutex creation name identifier to "etl mutex" --------- Co-authored-by: littepoint <1053049738@qq.com> --- include/etl/mutex.h | 5 +- include/etl/mutex/mutex_threadx.h | 81 +++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 include/etl/mutex/mutex_threadx.h diff --git a/include/etl/mutex.h b/include/etl/mutex.h index 105c377b..0d8873dd 100644 --- a/include/etl/mutex.h +++ b/include/etl/mutex.h @@ -37,6 +37,9 @@ SOFTWARE. #elif defined(ETL_TARGET_OS_FREERTOS) #include "mutex/mutex_freertos.h" #define ETL_HAS_MUTEX 1 +#elif defined(ETL_TARGET_OS_THREADX) + #include "mutex/mutex_threadx.h" + #define ETL_HAS_MUTEX 1 #elif ETL_USING_STL && ETL_USING_CPP11 #include "mutex/mutex_std.h" #define ETL_HAS_MUTEX 1 @@ -62,7 +65,7 @@ namespace etl //*************************************************************************** /// lock_guard - /// A mutex wrapper that provides an RAII mechanism for owning a mutex for + /// A mutex wrapper that provides an RAII mechanism for owning a mutex for /// the duration of a scoped block. //*************************************************************************** template diff --git a/include/etl/mutex/mutex_threadx.h b/include/etl/mutex/mutex_threadx.h new file mode 100644 index 00000000..074987e9 --- /dev/null +++ b/include/etl/mutex/mutex_threadx.h @@ -0,0 +1,81 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2020 Phil Wise phil@phil-wise.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_MUTEX_THREADX_INCLUDED +#define ETL_MUTEX_THREADX_INCLUDED + +#include "../platform.h" + +#include "tx_api.h" + +namespace etl +{ + //*************************************************************************** + ///\ingroup mutex + ///\brief This mutex class is implemented using ThreadX's mutexes + //*************************************************************************** + class mutex + { + public: + + mutex() + { + tx_mutex_create(&mutex_handle, "etl mutex", TX_INHERIT); + } + + ~mutex() + { + tx_mutex_delete(&mutex_handle); + } + + void lock() + { + tx_mutex_get(&mutex_handle, TX_WAIT_FOREVER); + } + + bool try_lock() + { + return tx_mutex_get(&mutex_handle, TX_NO_WAIT) == TX_SUCCESS; + } + + void unlock() + { + tx_mutex_put(&mutex_handle); + } + + private: + // Non-copyable + mutex(const mutex&) ETL_DELETE; + mutex& operator=(const mutex&) ETL_DELETE; + + // mutex handle + TX_MUTEX mutex_handle; + }; +} + +#endif From 5b99aa50b34f0f15fde01e7ecd7c9b29a2813eb1 Mon Sep 17 00:00:00 2001 From: Bo Rydberg <2945606+bolry@users.noreply.github.com> Date: Thu, 8 Jan 2026 21:12:43 +0100 Subject: [PATCH 068/298] Fix syntax errors in base64 test (#1255) Co-authored-by: John Wellbelove From f8ee5f450b40f4dee560546af345738d87b24aca Mon Sep 17 00:00:00 2001 From: Bo Rydberg <2945606+bolry@users.noreply.github.com> Date: Thu, 8 Jan 2026 22:58:27 +0100 Subject: [PATCH 069/298] Make code base with tests compile under gcc-14 (#1254) * Make code base with tests compile under gcc-14 * Update buffer_descriptors.h Following the same style as non-tests headers have. E.g., include/etl/intrusive_list.h & include/etl/intrusive_forward_list.h --------- Co-authored-by: John Wellbelove --- include/etl/buffer_descriptors.h | 2 + test/test_base64_RFC2152_decoder.cpp | 43 +++++++++-------- test/test_base64_RFC3501_decoder.cpp | 47 ++++++++++--------- ...64_RFC4648_URL_decoder_with_no_padding.cpp | 44 ++++++++--------- ...ase64_RFC4648_URL_decoder_with_padding.cpp | 43 ++++++++--------- ...base64_RFC4648_decoder_with_no_padding.cpp | 46 +++++++++--------- ...st_base64_RFC4648_decoder_with_padding.cpp | 44 ++++++++--------- test/test_circular_iterator.cpp | 2 + test/test_map.cpp | 8 ++-- 9 files changed, 142 insertions(+), 137 deletions(-) diff --git a/include/etl/buffer_descriptors.h b/include/etl/buffer_descriptors.h index 02ff32a9..836769fc 100644 --- a/include/etl/buffer_descriptors.h +++ b/include/etl/buffer_descriptors.h @@ -99,7 +99,9 @@ namespace etl pointer data() const { assert(pdesc_item != ETL_NULLPTR); +#include "private/diagnostic_null_dereference_push.h" return pdesc_item->pbuffer; +#include "private/diagnostic_pop.h" } //********************************* diff --git a/test/test_base64_RFC2152_decoder.cpp b/test/test_base64_RFC2152_decoder.cpp index af6e1a87..d25f0ddf 100644 --- a/test/test_base64_RFC2152_decoder.cpp +++ b/test/test_base64_RFC2152_decoder.cpp @@ -379,15 +379,14 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; b64.decode_final(encoded[i].data(), encoded[i].size()); - #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -403,7 +402,7 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -411,7 +410,7 @@ namespace b64.decode_final(encoded[i].data(), encoded[i].size()); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -427,7 +426,7 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -452,7 +451,7 @@ namespace CHECK_TRUE(received_final_block); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -468,7 +467,7 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -493,7 +492,7 @@ namespace CHECK_TRUE(received_final_block); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -509,7 +508,7 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -517,7 +516,7 @@ namespace b64.decode_final(encoded[i].begin(), encoded[i].end()); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -533,7 +532,7 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -541,7 +540,7 @@ namespace b64.decode_final(encoded[i].begin(), encoded[i].end()); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -557,7 +556,7 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -582,7 +581,7 @@ namespace CHECK_TRUE(received_final_block); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -598,7 +597,7 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -639,7 +638,7 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -657,7 +656,7 @@ namespace CHECK_TRUE(received_final_block); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -673,7 +672,7 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -691,7 +690,7 @@ namespace CHECK_TRUE(received_final_block); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -707,7 +706,7 @@ namespace { codec_full_buffer b64; - for (size_t i = 4; i < 256; ++i) + for (size_t i = 4; i < input_data.size(); ++i) { b64.restart(); @@ -729,7 +728,7 @@ namespace b64.flush(); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(b64.begin(), b64.end()); #include "etl/private/diagnostic_pop.h" diff --git a/test/test_base64_RFC3501_decoder.cpp b/test/test_base64_RFC3501_decoder.cpp index 0e750518..e48af347 100644 --- a/test/test_base64_RFC3501_decoder.cpp +++ b/test/test_base64_RFC3501_decoder.cpp @@ -376,7 +376,7 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -384,7 +384,7 @@ namespace b64.decode_final(encoded[i].data(), encoded[i].size()); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -400,7 +400,7 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -408,7 +408,7 @@ namespace b64.decode_final(encoded[i].data(), encoded[i].size()); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -424,7 +424,7 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -449,7 +449,7 @@ namespace CHECK_TRUE(received_final_block); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -465,7 +465,7 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -490,7 +490,7 @@ namespace CHECK_TRUE(received_final_block); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -506,7 +506,7 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -514,7 +514,7 @@ namespace b64.decode_final(encoded[i].begin(), encoded[i].end()); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -530,15 +530,15 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; b64.decode_final(encoded[i].begin(), encoded[i].end()); - + #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -554,7 +554,7 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -579,7 +579,7 @@ namespace CHECK_TRUE(received_final_block); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -595,7 +595,7 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -618,9 +618,9 @@ namespace CHECK_FALSE(received_final_block); b64.flush(); CHECK_TRUE(received_final_block); - + #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -636,7 +636,7 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -654,7 +654,7 @@ namespace CHECK_TRUE(received_final_block); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -670,7 +670,7 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -704,7 +704,7 @@ namespace { codec_full_buffer b64; - for (size_t i = 4; i < 256; ++i) + for (size_t i = 4; i < input_data.size(); ++i) { b64.restart(); @@ -725,8 +725,9 @@ namespace b64.flush(); + #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(b64.begin(), b64.end()); #include "etl/private/diagnostic_pop.h" diff --git a/test/test_base64_RFC4648_URL_decoder_with_no_padding.cpp b/test/test_base64_RFC4648_URL_decoder_with_no_padding.cpp index b2d3c01b..ad16041f 100644 --- a/test/test_base64_RFC4648_URL_decoder_with_no_padding.cpp +++ b/test/test_base64_RFC4648_URL_decoder_with_no_padding.cpp @@ -376,7 +376,7 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -384,7 +384,7 @@ namespace b64.decode_final(encoded[i].data(), encoded[i].size()); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -400,7 +400,7 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -408,7 +408,7 @@ namespace b64.decode_final(encoded[i].data(), encoded[i].size()); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -424,7 +424,7 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -449,7 +449,7 @@ namespace CHECK_TRUE(received_final_block); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -465,7 +465,7 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -490,7 +490,7 @@ namespace CHECK_TRUE(received_final_block); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -506,7 +506,7 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -514,7 +514,7 @@ namespace b64.decode_final(encoded[i].begin(), encoded[i].end()); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -530,7 +530,7 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -538,7 +538,7 @@ namespace b64.decode_final(encoded[i].begin(), encoded[i].end()); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -554,7 +554,7 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -579,7 +579,7 @@ namespace CHECK_TRUE(received_final_block); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -595,7 +595,7 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -620,7 +620,7 @@ namespace CHECK_TRUE(received_final_block); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -636,7 +636,7 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -654,7 +654,7 @@ namespace CHECK_TRUE(received_final_block); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -670,7 +670,7 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -688,7 +688,7 @@ namespace CHECK_TRUE(received_final_block); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -704,7 +704,7 @@ namespace { codec_full_buffer b64; - for (size_t i = 4; i < 256; ++i) + for (size_t i = 4; i < input_data.size(); ++i) { b64.restart(); @@ -726,7 +726,7 @@ namespace b64.flush(); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(b64.begin(), b64.end()); #include "etl/private/diagnostic_pop.h" diff --git a/test/test_base64_RFC4648_URL_decoder_with_padding.cpp b/test/test_base64_RFC4648_URL_decoder_with_padding.cpp index 77c990a3..5266d3c9 100644 --- a/test/test_base64_RFC4648_URL_decoder_with_padding.cpp +++ b/test/test_base64_RFC4648_URL_decoder_with_padding.cpp @@ -376,7 +376,7 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -384,7 +384,7 @@ namespace b64.decode_final(encoded[i].data(), encoded[i].size()); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -400,7 +400,7 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -408,7 +408,7 @@ namespace b64.decode_final(encoded[i].data(), encoded[i].size()); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -424,7 +424,7 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -447,9 +447,9 @@ namespace CHECK_FALSE(received_final_block); b64.flush(); CHECK_TRUE(received_final_block); - + #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -465,7 +465,7 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -490,7 +490,7 @@ namespace CHECK_TRUE(received_final_block); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -506,7 +506,7 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -514,7 +514,7 @@ namespace b64.decode_final(encoded[i].begin(), encoded[i].end()); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -530,7 +530,7 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -554,7 +554,7 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -579,7 +579,7 @@ namespace CHECK_TRUE(received_final_block); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -595,7 +595,7 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -620,7 +620,7 @@ namespace CHECK_TRUE(received_final_block); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -636,7 +636,7 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -653,6 +653,7 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); #include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); @@ -670,7 +671,7 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -688,7 +689,7 @@ namespace CHECK_TRUE(received_final_block); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -704,7 +705,7 @@ namespace { codec_full_buffer b64; - for (size_t i = 4; i < 256; ++i) + for (size_t i = 4; i < input_data.size(); ++i) { b64.restart(); @@ -726,7 +727,7 @@ namespace b64.flush(); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(b64.begin(), b64.end()); #include "etl/private/diagnostic_pop.h" diff --git a/test/test_base64_RFC4648_decoder_with_no_padding.cpp b/test/test_base64_RFC4648_decoder_with_no_padding.cpp index a87852f3..9c33aafa 100644 --- a/test/test_base64_RFC4648_decoder_with_no_padding.cpp +++ b/test/test_base64_RFC4648_decoder_with_no_padding.cpp @@ -376,15 +376,15 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; b64.decode_final(encoded[i].data(), encoded[i].size()); - + #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -400,7 +400,7 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -408,7 +408,7 @@ namespace b64.decode_final(encoded[i].data(), encoded[i].size()); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -424,7 +424,7 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -449,7 +449,7 @@ namespace CHECK_TRUE(received_final_block); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -465,7 +465,7 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -490,7 +490,7 @@ namespace CHECK_TRUE(received_final_block); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -506,7 +506,7 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -514,7 +514,7 @@ namespace b64.decode_final(encoded[i].begin(), encoded[i].end()); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -530,7 +530,7 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -538,7 +538,7 @@ namespace b64.decode_final(encoded[i].begin(), encoded[i].end()); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -554,7 +554,7 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -579,7 +579,7 @@ namespace CHECK_TRUE(received_final_block); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -595,7 +595,7 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -620,7 +620,7 @@ namespace CHECK_TRUE(received_final_block); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -636,7 +636,7 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -654,7 +654,7 @@ namespace CHECK_TRUE(received_final_block); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -670,7 +670,7 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -688,7 +688,7 @@ namespace CHECK_TRUE(received_final_block); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -704,7 +704,7 @@ namespace { codec_full_buffer b64; - for (size_t i = 4; i < 256; ++i) + for (size_t i = 4; i < input_data.size(); ++i) { b64.restart(); @@ -726,7 +726,7 @@ namespace b64.flush(); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(b64.begin(), b64.end()); #include "etl/private/diagnostic_pop.h" diff --git a/test/test_base64_RFC4648_decoder_with_padding.cpp b/test/test_base64_RFC4648_decoder_with_padding.cpp index 41e0a2ff..a16570d4 100644 --- a/test/test_base64_RFC4648_decoder_with_padding.cpp +++ b/test/test_base64_RFC4648_decoder_with_padding.cpp @@ -376,7 +376,7 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -384,7 +384,7 @@ namespace b64.decode_final(encoded[i].data(), encoded[i].size()); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -400,7 +400,7 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -408,7 +408,7 @@ namespace b64.decode_final(encoded[i].data(), encoded[i].size()); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -424,7 +424,7 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -447,9 +447,9 @@ namespace CHECK_FALSE(received_final_block); b64.flush(); CHECK_TRUE(received_final_block); - + #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -465,7 +465,7 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -490,7 +490,7 @@ namespace CHECK_TRUE(received_final_block); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -506,7 +506,7 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -514,7 +514,7 @@ namespace b64.decode_final(encoded[i].begin(), encoded[i].end()); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -530,7 +530,7 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -538,7 +538,7 @@ namespace b64.decode_final(encoded[i].begin(), encoded[i].end()); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -554,7 +554,7 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -579,7 +579,7 @@ namespace CHECK_TRUE(received_final_block); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -595,7 +595,7 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -620,7 +620,7 @@ namespace CHECK_TRUE(received_final_block); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -636,7 +636,7 @@ namespace { codec b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -670,7 +670,7 @@ namespace { codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i != input_data.size(); ++i) { decoded_output.clear(); received_final_block = false; @@ -688,7 +688,7 @@ namespace CHECK_TRUE(received_final_block); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(decoded_output); #include "etl/private/diagnostic_pop.h" @@ -704,7 +704,7 @@ namespace { codec_full_buffer b64; - for (size_t i = 4; i < 256; ++i) + for (size_t i = 4; i < input_data.size(); ++i) { b64.restart(); @@ -726,7 +726,7 @@ namespace b64.flush(); #include "etl/private/diagnostic_null_dereference_push.h" - std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); std::vector actual(b64.begin(), b64.end()); #include "etl/private/diagnostic_pop.h" diff --git a/test/test_circular_iterator.cpp b/test/test_circular_iterator.cpp index 167af271..6b66cbe0 100644 --- a/test/test_circular_iterator.cpp +++ b/test/test_circular_iterator.cpp @@ -28,7 +28,9 @@ SOFTWARE. #include "unit_test_framework.h" #include +#include "etl/private/diagnostic_null_dereference_push.h" #include +#include "etl/private/diagnostic_pop.h" #include #include "etl/iterator.h" diff --git a/test/test_map.cpp b/test/test_map.cpp index b5ca6447..251e8408 100644 --- a/test/test_map.cpp +++ b/test/test_map.cpp @@ -1148,7 +1148,7 @@ namespace Data data(initial_data.begin(), initial_data.end()); Data::iterator it = data.find("3"); - CHECK(3 == it->second); + CHECK(data.end() != it && 3 == it->second); it = data.find("A"); CHECK(data.end() == it); @@ -1165,7 +1165,7 @@ namespace EMap data(initial_data.begin(), initial_data.end()); EMap::iterator it = data.find(Key("3")); - CHECK(3 == it->second); + CHECK(data.end() != it && 3 == it->second); it = data.find(Key("A")); CHECK(data.end() == it); @@ -1180,7 +1180,7 @@ namespace const Data data(initial_data.begin(), initial_data.end()); Data::const_iterator it = data.find("3"); - CHECK(3 == it->second); + CHECK(data.end() != it && 3 == it->second); it = data.find("A"); CHECK(data.end() == it); @@ -1197,7 +1197,7 @@ namespace const EMap data(initial_data.begin(), initial_data.end()); EMap::const_iterator it = data.find(Key("3")); - CHECK(3 == it->second); + CHECK(data.end() != it && 3 == it->second); it = data.find(Key("A")); CHECK(data.end() == it); From 09555434f66532e2f1e32c4e5c9a85a7a277ce03 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 8 Jan 2026 23:05:46 +0100 Subject: [PATCH 070/298] Fixed multiple definition of 'expected' --- test/test_base64_RFC4648_URL_decoder_with_padding.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/test/test_base64_RFC4648_URL_decoder_with_padding.cpp b/test/test_base64_RFC4648_URL_decoder_with_padding.cpp index 5266d3c9..f98fd948 100644 --- a/test/test_base64_RFC4648_URL_decoder_with_padding.cpp +++ b/test/test_base64_RFC4648_URL_decoder_with_padding.cpp @@ -653,7 +653,6 @@ namespace b64.flush(); CHECK_TRUE(received_final_block); - std::vector expected(input_data.begin(), std::next(input_data.begin(), i)); #include "etl/private/diagnostic_null_dereference_push.h" std::vector expected(input_data.begin(), input_data.begin() + i); std::vector actual(decoded_output); From 6d6ecc9fb5f35c28e0caad63d121e5077d8599b7 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 10 Jan 2026 09:46:50 +0100 Subject: [PATCH 071/298] Add etl::inplace_function (#1251) * Imported inplace_function and invoke functionality from original branch * Fixed spelling mistake * Update test/CMakeLists.txt Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update test/test_inplace_function.cpp Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Moved member type function_ptr to private section * Updated comments in inplace_function.h * Updated action workflows to be triggered on a pull-request based on development branch * Added suggested changes from PR reviews --------- Co-authored-by: John Wellbelove Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: John Wellbelove --- .github/workflows/clang-c++11.yml | 2 +- .github/workflows/clang-c++14.yml | 2 +- .github/workflows/clang-c++17.yml | 2 +- .github/workflows/clang-c++20.yml | 2 +- .github/workflows/clang-c++23.yml | 3 +- .github/workflows/clang-syntax-checks.yml | 2 +- .github/workflows/gcc-c++11.yml | 2 +- .github/workflows/gcc-c++14.yml | 2 +- .github/workflows/gcc-c++17.yml | 2 +- .github/workflows/gcc-c++20.yml | 2 +- .github/workflows/gcc-c++23.yml | 3 +- .github/workflows/gcc-syntax-checks.yml | 2 +- .github/workflows/msvc.yml | 2 +- include/etl/file_error_numbers.h | 1 + include/etl/inplace_function.h | 1529 +++++++++++++++++ include/etl/invoke.h | 58 +- test/CMakeLists.txt | 6 +- test/syntax_check/CMakeLists.txt | 2 + test/syntax_check/inplace_function.h.t.cpp | 29 + test/syntax_check/invoke.h.t.cpp | 29 + test/test_inplace_function.cpp | 1780 ++++++++++++++++++++ test/test_invoke.cpp | 532 ++++-- test/test_is_invocable.cpp | 1011 +++++++++++ test/vs2022/etl.vcxproj | 3 + test/vs2022/etl.vcxproj.filters | 11 +- 25 files changed, 4886 insertions(+), 133 deletions(-) create mode 100644 include/etl/inplace_function.h create mode 100644 test/syntax_check/inplace_function.h.t.cpp create mode 100644 test/syntax_check/invoke.h.t.cpp create mode 100644 test/test_inplace_function.cpp create mode 100644 test/test_is_invocable.cpp diff --git a/.github/workflows/clang-c++11.yml b/.github/workflows/clang-c++11.yml index 610b4529..1d6976eb 100644 --- a/.github/workflows/clang-c++11.yml +++ b/.github/workflows/clang-c++11.yml @@ -3,7 +3,7 @@ on: push: branches: [ master, development, pull-request/* ] pull_request: - branches: [ master, pull-request/* ] + branches: [ master, development, pull-request/* ] types: [opened, synchronize, reopened] jobs: diff --git a/.github/workflows/clang-c++14.yml b/.github/workflows/clang-c++14.yml index 233eabff..dd6c2aad 100644 --- a/.github/workflows/clang-c++14.yml +++ b/.github/workflows/clang-c++14.yml @@ -3,7 +3,7 @@ on: push: branches: [ master, development, pull-request/* ] pull_request: - branches: [ master, pull-request/* ] + branches: [ master, development, pull-request/* ] types: [opened, synchronize, reopened] jobs: diff --git a/.github/workflows/clang-c++17.yml b/.github/workflows/clang-c++17.yml index 2c659fc6..bc54989d 100644 --- a/.github/workflows/clang-c++17.yml +++ b/.github/workflows/clang-c++17.yml @@ -3,7 +3,7 @@ on: push: branches: [ master, development, pull-request/* ] pull_request: - branches: [ master, pull-request/* ] + branches: [ master, development, pull-request/* ] types: [opened, synchronize, reopened] jobs: diff --git a/.github/workflows/clang-c++20.yml b/.github/workflows/clang-c++20.yml index d170a982..bfd88665 100644 --- a/.github/workflows/clang-c++20.yml +++ b/.github/workflows/clang-c++20.yml @@ -3,7 +3,7 @@ on: push: branches: [ master, development, pull-request/* ] pull_request: - branches: [ master, pull-request/* ] + branches: [ master, development, pull-request/* ] types: [opened, synchronize, reopened] jobs: diff --git a/.github/workflows/clang-c++23.yml b/.github/workflows/clang-c++23.yml index b6b6cd84..3e1f5a67 100644 --- a/.github/workflows/clang-c++23.yml +++ b/.github/workflows/clang-c++23.yml @@ -3,7 +3,8 @@ on: push: branches: [ master, development, pull-request/* ] pull_request: - branches: [ master, pull-request/* ] + branches: [ master, development, pull-request/* ] + types: [opened, synchronize, reopened] jobs: diff --git a/.github/workflows/clang-syntax-checks.yml b/.github/workflows/clang-syntax-checks.yml index 0b32ecb2..700b2087 100644 --- a/.github/workflows/clang-syntax-checks.yml +++ b/.github/workflows/clang-syntax-checks.yml @@ -3,7 +3,7 @@ on: push: branches: [ master, development, pull-request/* ] pull_request: - branches: [ master, pull-request/* ] + branches: [ master, development, pull-request/* ] types: [opened, synchronize, reopened] jobs: diff --git a/.github/workflows/gcc-c++11.yml b/.github/workflows/gcc-c++11.yml index 100d179c..938402c1 100644 --- a/.github/workflows/gcc-c++11.yml +++ b/.github/workflows/gcc-c++11.yml @@ -3,7 +3,7 @@ on: push: branches: [ master, development, pull-request/* ] pull_request: - branches: [ master, pull-request/* ] + branches: [ master, development, pull-request/* ] types: [opened, synchronize, reopened] jobs: diff --git a/.github/workflows/gcc-c++14.yml b/.github/workflows/gcc-c++14.yml index 881f4607..59a06efc 100644 --- a/.github/workflows/gcc-c++14.yml +++ b/.github/workflows/gcc-c++14.yml @@ -3,7 +3,7 @@ on: push: branches: [ master, development, pull-request/* ] pull_request: - branches: [ master, pull-request/* ] + branches: [ master, development, pull-request/* ] types: [opened, synchronize, reopened] jobs: diff --git a/.github/workflows/gcc-c++17.yml b/.github/workflows/gcc-c++17.yml index 931c9a6d..90f6ced5 100644 --- a/.github/workflows/gcc-c++17.yml +++ b/.github/workflows/gcc-c++17.yml @@ -3,7 +3,7 @@ on: push: branches: [ master, development, pull-request/* ] pull_request: - branches: [ master, pull-request/* ] + branches: [ master, development, pull-request/* ] types: [opened, synchronize, reopened] jobs: diff --git a/.github/workflows/gcc-c++20.yml b/.github/workflows/gcc-c++20.yml index 9240046a..62833fbf 100644 --- a/.github/workflows/gcc-c++20.yml +++ b/.github/workflows/gcc-c++20.yml @@ -3,7 +3,7 @@ on: push: branches: [ master, development, pull-request/* ] pull_request: - branches: [ master, pull-request/* ] + branches: [ master, development, pull-request/* ] types: [opened, synchronize, reopened] jobs: diff --git a/.github/workflows/gcc-c++23.yml b/.github/workflows/gcc-c++23.yml index 93881f84..4b2efa3d 100644 --- a/.github/workflows/gcc-c++23.yml +++ b/.github/workflows/gcc-c++23.yml @@ -3,7 +3,8 @@ on: push: branches: [ master, development, pull-request/* ] pull_request: - branches: [ master, pull-request/* ] + branches: [ master, development, pull-request/* ] + types: [opened, synchronize, reopened] jobs: diff --git a/.github/workflows/gcc-syntax-checks.yml b/.github/workflows/gcc-syntax-checks.yml index 6db13f7b..5f3753b1 100644 --- a/.github/workflows/gcc-syntax-checks.yml +++ b/.github/workflows/gcc-syntax-checks.yml @@ -3,7 +3,7 @@ on: push: branches: [ master, development, pull-request/* ] pull_request: - branches: [ master, pull-request/* ] + branches: [ master, development, pull-request/* ] types: [opened, synchronize, reopened] jobs: diff --git a/.github/workflows/msvc.yml b/.github/workflows/msvc.yml index 08180a9e..9f28f025 100644 --- a/.github/workflows/msvc.yml +++ b/.github/workflows/msvc.yml @@ -3,7 +3,7 @@ on: push: branches: [ master, development, pull-request/* ] pull_request: - branches: [ master, pull-request/* ] + branches: [ master, development, pull-request/* ] types: [opened, synchronize, reopened] jobs: diff --git a/include/etl/file_error_numbers.h b/include/etl/file_error_numbers.h index b3e08814..47af25c0 100644 --- a/include/etl/file_error_numbers.h +++ b/include/etl/file_error_numbers.h @@ -110,4 +110,5 @@ SOFTWARE. #define ETL_NOT_NULL_FILE_ID "77" #define ETL_SIGNAL_FILE_ID "78" #define ETL_FORMAT_FILE_ID "79" +#define ETL_INPLACE_FUNCTION_FILE_ID "80" #endif diff --git a/include/etl/inplace_function.h b/include/etl/inplace_function.h new file mode 100644 index 00000000..a027f342 --- /dev/null +++ b/include/etl/inplace_function.h @@ -0,0 +1,1529 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_INPLACE_FUNCTION_INCLUDED +#define ETL_INPLACE_FUNCTION_INCLUDED + +#include "platform.h" + +#if ETL_USING_CPP11 + +#include "utility.h" +#include "optional.h" +#include "placement_new.h" +#include "type_traits.h" +#include "function_traits.h" +#include "error_handler.h" +#include "exception.h" +#include "invoke.h" +#include "file_error_numbers.h" + +#if !defined(ETL_DEFAULT_INPLACE_FUNCTION_SIZE) + #define ETL_DEFAULT_INPLACE_FUNCTION_SIZE 32 +#endif + +#if !defined(ETL_DEFAULT_INPLACE_FUNCTION_ALIGNMENT) + #define ETL_DEFAULT_INPLACE_FUNCTION_ALIGNMENT alignof(void*) +#endif + +namespace etl +{ + //************************************************************************* + /// Exception base for inplace_function + //************************************************************************* + class inplace_function_exception : public etl::exception + { + public: + + inplace_function_exception(string_type reason_, string_type file_name_, numeric_type line_number_) + : exception(reason_, file_name_, line_number_) + { + } + }; + + //************************************************************************* + /// Inplace function uninitialized exception. + //************************************************************************* + class inplace_function_uninitialized : public inplace_function_exception + { + public: + + inplace_function_uninitialized(string_type file_name_, numeric_type line_number_) + : inplace_function_exception(ETL_ERROR_TEXT("inplace_function:uninitialized", ETL_INPLACE_FUNCTION_FILE_ID"A"), file_name_, line_number_) + { + } + }; + + namespace private_inplace_function + { + //************************************************************************* + /// The vtable for inplace_function + //************************************************************************* + template + struct inplace_function_vtable + { + using invoke_type = TReturn(*)(void*, TArgs...); + using destroy_type = void(*)(void*); + using move_type = void(*)(void*, void*); + using copy_type = void(*)(const void*, void*); + + invoke_type invoke = nullptr; + destroy_type destroy = nullptr; + move_type move = nullptr; + copy_type copy = nullptr; + + //***************************************** + // Constructor + //***************************************** + ETL_CONSTEXPR inplace_function_vtable(invoke_type i, + destroy_type d, + move_type m, + copy_type c) + : invoke(i) + , destroy(d) + , move(m) + , copy(c) {} + + //***************************************** + // Payload records for member bindings + //***************************************** + // Non-const member function + //***************************************** + template + struct member_target + { + TReturn (TObject::* member)(TArgs...); + TObject obj; + }; + + //***************************************** + // Const member function + //***************************************** + template + struct const_member_target + { + TReturn(TObject::* member)(TArgs...) const; + TObject obj; + }; + + //***************************************** + // Storage helpers + //***************************************** + // Copy construct + //***************************************** + template + static void copy_construct(const void* src, void* dst) + { + ::new (dst) T(*static_cast(src)); + } + + //***************************************** + // Move construct + //***************************************** + template + static void move_construct(void* src, void* dst) + { + ::new (dst) T(etl::move(*static_cast(src))); + + if (DestroySrc) + { + static_cast(src)->~T(); + } + } + + //***************************************** + // Stub functions + //***************************************** + // Destroy function + //***************************************** + template + static void destroy_stub(void* p) + { + static_cast(p)->~T(); + } + + //***************************************** + // Free function - Returning value + //***************************************** + template ::value, int> = 0> + static R stub_function_ptr(void* p, TArgs... a) + { + return (*static_cast(p))(etl::forward(a)...); + } + + //***************************************** + // Free function - returning void + //***************************************** + template ::value, int> = 0> + static void stub_function_ptr(void* p, TArgs... a) + { + (*static_cast(p))(etl::forward(a)...); + } + + //***************************************** + // Member target - Returning value + //***************************************** + template ::value, int> = 0> + static R stub_member(void* p, TArgs... a) + { + auto* s = static_cast(p); + return (s->obj.*(s->member))(etl::forward(a)...); + } + + //***************************************** + // Member target - returning void + //***************************************** + template ::value, int> = 0> + static void stub_member(void* p, TArgs... a) + { + auto* s = static_cast(p); + (s->obj.*(s->member))(etl::forward(a)...); + } + + //***************************************** + // Functor / lambda stored in payload - returning value + //***************************************** + template ::value, int> = 0> + static R stub_functor(void* p, TArgs... a) + { + return (*static_cast(p))(etl::forward(a)...); + } + + //***************************************** + // Functor / lambda stored in payload - returning void + //***************************************** + template ::value, int> = 0> + static void stub_functor(void* p, TArgs... a) + { + (*static_cast(p))(etl::forward(a)...); + } + + //***************************************** + // Const functor / lambda stored in payload - returning value + //***************************************** + template ::value, int> = 0> + static R stub_const_functor(void* p, TArgs... a) + { + return (*static_cast(p))(etl::forward(a)...); + } + + //***************************************** + // Const functor / lambda stored in payload - returning void + //***************************************** + template ::value, int> = 0> + static void stub_const_functor(void* p, TArgs... a) + { + (*static_cast(p))(etl::forward(a)...); + } + + //***************************************** + // Compile-time bound free function - returning value + //***************************************** + template ::value, int> = 0> + static R stub_ct_function(void*, TArgs... a) + { + return Function(etl::forward(a)...); + } + + //***************************************** + // Compile-time bound free function - returning void + //***************************************** + template ::value, int> = 0> + static void stub_ct_function(void*, TArgs... a) + { + Function(etl::forward(a)...); + } + + //***************************************** + // Compile-time bound member + object - returning value + //***************************************** + template ::value, int> = 0> + static R stub_ct_member(void*, TArgs... a) + { + return (Object->*Method)(etl::forward(a)...); + } + + //***************************************** + // Compile-time bound member + object - returning void + //***************************************** + template ::value, int> = 0> + static void stub_ct_member(void*, TArgs... a) + { + (Object->*Method)(etl::forward(a)...); + } + + //***************************************** + // Compile-time bound const member + object - returning value + //***************************************** + template ::value, int> = 0> + static R stub_ct_const_member(void*, TArgs... a) + { + return (Object->*Method)(etl::forward(a)...); + } + + //***************************************** + // Compile-time bound const member + object - returning void + //***************************************** + template ::value, int> = 0> + static void stub_ct_const_member(void*, TArgs... a) + { + (Object->*Method)(etl::forward(a)...); + } + + //***************************************** + // Compile-time bound operator() + object - returning value + //***************************************** + template ::value, int> = 0> + static R stub_ct_operator(void*, TArgs... a) + { + return (*Object)(etl::forward(a)...); + } + + //***************************************** + // Compile-time bound operator() + object - returning void + //***************************************** + template ::value, int> = 0> + static void stub_ct_operator(void*, TArgs... a) + { + (*Object)(etl::forward(a)...); + } + + //***************************************** + // vtable factories + //***************************************** + // Free function pointer + //***************************************** + static const inplace_function_vtable* for_function_ptr() + { + using function_type = TReturn(*)(TArgs...); + static const inplace_function_vtable vtable(&inplace_function_vtable::template stub_function_ptr, + nullptr, + &inplace_function_vtable::template move_construct, + &inplace_function_vtable::template copy_construct); + return &vtable; + } + + //***************************************** + // Member function pointer + //***************************************** + template + static const inplace_function_vtable* for_member() + { + using target_t = member_target; + constexpr bool destroy_src_on_move = !etl::is_trivially_destructible::value; + + constexpr destroy_type destroy_ptr = etl::is_trivially_destructible::value ? nullptr + : &inplace_function_vtable::template destroy_stub; + + static const inplace_function_vtable vtable(&inplace_function_vtable::template stub_member, + destroy_ptr, + &inplace_function_vtable::template move_construct, + &inplace_function_vtable::template copy_construct); + return &vtable; + } + + //***************************************** + // Const member function pointer + //***************************************** + template + static const inplace_function_vtable* for_const_member() + { + using target_t = const_member_target; + constexpr bool destroy_src_on_move = !etl::is_trivially_destructible::value; + + constexpr destroy_type destroy_ptr = etl::is_trivially_destructible::value ? nullptr + : &inplace_function_vtable::template destroy_stub; + + static const inplace_function_vtable vtable(&inplace_function_vtable::template stub_member, + destroy_ptr, + &inplace_function_vtable::template move_construct, + &inplace_function_vtable::template copy_construct); + return &vtable; + } + + //***************************************** + // Functor / lambda + //***************************************** + template + static const inplace_function_vtable* for_functor() + { + constexpr bool destroy_src_on_move = !etl::is_trivially_destructible::value; + + constexpr destroy_type destroy_ptr = etl::is_trivially_destructible::value ? nullptr + : &inplace_function_vtable::template destroy_stub; + + static const inplace_function_vtable vtable(&inplace_function_vtable::template stub_functor, + destroy_ptr, + &inplace_function_vtable::template move_construct, + &inplace_function_vtable::template copy_construct); + return &vtable; + } + + //***************************************** + // Const functor / lambda + //***************************************** + template + static const inplace_function_vtable* for_const_functor() + { + constexpr bool destroy_src_on_move = !etl::is_trivially_destructible::value; + + constexpr destroy_type destroy_ptr = etl::is_trivially_destructible::value ? nullptr + : &inplace_function_vtable::template destroy_stub; + + static const inplace_function_vtable vtable(&inplace_function_vtable::template stub_const_functor, + destroy_ptr, + &inplace_function_vtable::template move_construct, + &inplace_function_vtable::template copy_construct); + return &vtable; + } + + //***************************************** + // Compile-time bound free function + //***************************************** + template + static const inplace_function_vtable* for_compile_time_function() + { + static const inplace_function_vtable vtable(&inplace_function_vtable::template stub_ct_function, + nullptr, + nullptr, + nullptr); + return &vtable; + } + + //***************************************** + // Compile-time bound member function + object + //***************************************** + template + static const inplace_function_vtable* for_compile_time_member() + { + static const inplace_function_vtable vtable(&inplace_function_vtable::template stub_ct_member, + nullptr, + nullptr, + nullptr); + return &vtable; + } + + //***************************************** + // Compile-time bound const member function + object + //***************************************** + template + static const inplace_function_vtable* for_compile_time_const_member() + { + static const inplace_function_vtable vtable(&inplace_function_vtable::template stub_ct_const_member, + nullptr, + nullptr, + nullptr); + return &vtable; + } + + //***************************************** + // Compile-time bound operator() + object + //***************************************** + template + static const inplace_function_vtable* for_compile_time_operator() + { + static const inplace_function_vtable vtable(&inplace_function_vtable::template stub_ct_operator, + nullptr, + nullptr, + nullptr); + return &vtable; + } + }; + } + + //************************************************************************* + /// inplace_function + //************************************************************************* + template + class inplace_function; + + //************************************************************************* + // Is not an etl::inplace_function + //************************************************************************* + template + struct is_inplace_function : etl::false_type {}; + + //************************************************************************* + // Is an etl::inplace_function + //************************************************************************* + template + struct is_inplace_function> : etl::true_type {}; + + //************************************************************************* + /// inplace_function + /// A function wrapper with in-place storage for the callable object. + /// \tparam TReturn The return type of the function signature. + /// \tparam TArgs The argument types of the function signature. + /// \tparam Object_Size The size of the in-place storage for the callable object. + /// \tparam Object_Alignment The alignment of the in-place storage for the callable object. + //************************************************************************* + template + class inplace_function + { + private: + + using this_type = inplace_function; + using storage_type = etl::uninitialized_buffer; + using vtable_type = private_inplace_function::inplace_function_vtable; + using function_ptr = TReturn(*)(TArgs...); + + public: + + using function_type = TReturn(TArgs...); + using return_type = TReturn; + using argument_types = etl::type_list; + + //************************************************************************* + /// Default constructor + //************************************************************************* + inplace_function() noexcept = default; + + //************************************************************************* + /// Copy constructor + ///\param other The other inplace_function to copy from. + //************************************************************************* + inplace_function(const inplace_function& other) + { + clone_from(other); + } + + //************************************************************************* + /// Copy constructor for different object buffer sizes + /// Static asserts if the destination buffer is too small. + /// Static assert if the destination alignment is too small. + /// \param other The other inplace_function to copy from. + ///************************************************************************* + template + inplace_function(const etl::inplace_function& other) + { + static_assert(Object_Size >= Other_Object_Size, "etl::inplace_function: Destination object size too small"); + static_assert(Object_Alignment >= Other_Object_Alignment, "etl::inplace_function: Destination object alignment too small"); + + clone_from(other); + } + + //************************************************************************* + /// Move constructor + /// \param other The other inplace_function to move from. + //************************************************************************* + inplace_function(inplace_function&& other) noexcept + { + move_from(other); + } + + //************************************************************************* + /// Move constructor for different object buffer + /// Static asserts if the destination buffer is too small. + /// Static assert if the destination alignment is too small. + /// \param other The other inplace_function to move from. + //************************************************************************* + template + inplace_function(etl::inplace_function&& other) noexcept + { + static_assert(Object_Size >= Other_Object_Size, "etl::inplace_function: Destination object size too small"); + static_assert(Object_Alignment >= Other_Object_Alignment, "etl::inplace_function: Destination object alignment too small"); + + move_from(other); + } + + //************************************************************************* + /// Destructor + //************************************************************************* + ~inplace_function() noexcept + { + clear(); + } + + //************************************************************************* + /// Construct from function pointer. + /// \param f The function pointer. + //************************************************************************* + inplace_function(function_ptr f) + { + set(f); + } + + //************************************************************************* + /// Construct from object + non-const member function (runtime). + /// \tparam TObject The object type. + /// \param method The member function pointer. + /// \param obj The object. + //************************************************************************* + template + inplace_function(TReturn (TObject::*method)(TArgs...), TObjectArg&& obj) + { + set(method, etl::forward(obj)); + } + + //************************************************************************* + /// Construct from object + const member function (runtime). + /// \tparam TObject The object type. + /// \param method The member function pointer. + /// \param obj The object. + //************************************************************************* + template + inplace_function(TReturn (TObject::*method)(TArgs...) const, TObjectArg&& obj) + { + set(method, etl::forward(obj)); + } + + //************************************************************************* + /// Construct from lambda/functor (runtime). + /// \tparam TLambda The lambda/functor type. + /// \param lambda The lambda/functor. + //************************************************************************* + template ::type, + typename = etl::enable_if_t::value && !is_inplace_function::value, void>> + inplace_function(TLambda& lambda) + { + set(lambda); + } + + //************************************************************************* + /// Construct from const lambda/functor (runtime). + /// \tparam TLambda The lambda/functor type. + /// \param lambda The lambda/functor. + //************************************************************************* + template ::type, + typename = etl::enable_if_t::value && !is_inplace_function::value, void>> + inplace_function(const TLambda& lambda) + { + set(lambda); + } + + //************************************************************************* + /// Create from function pointer (runtime). + /// \param f The function pointer. + //************************************************************************* + void set(function_ptr f) + { + // Validate that 'f' is invocable with (TArgs...) and returns TReturn + static_assert(etl::is_invocable_r::value, + "etl::inplace_function: function pointer is not compatible with the inplace_function signature"); + + static_assert(Object_Size >= sizeof(function_ptr), "etl::inplace_function: storage size too small"); + static_assert(Object_Alignment >= alignof(function_ptr), "etl::inplace_function: storage alignment too small"); + + clear(); + + // Construct the object in the storage. + ::new (storage_ptr()) function_ptr(f); + + vtable = vtable_type::for_function_ptr(); + } + + //************************************************************************* + /// Create from object + member function (runtime). + /// \tparam TObject The object type. + /// \param method The member function pointer. + /// \param obj The object. + //************************************************************************* + template + void set(TReturn(TObject::* method)(TArgs...), TObjectArg&& obj) + { + using D = etl::decay_t; + static_assert(etl::is_invocable_r::value, + "etl::inplace_function: bound member function is not compatible with the inplace_function signature"); + + using target_t = typename vtable_type::template member_target; + + static_assert(Object_Size >= sizeof(target_t), "etl::inplace_function: storage size too small"); + static_assert(Object_Alignment >= alignof(target_t), "etl::inplace_function: storage alignment too small"); + + clear(); + ::new (storage_ptr()) target_t{ method, etl::forward(obj) }; + vtable = vtable_type::template for_member(); + } + + //************************************************************************* + /// Create from object + const member function (runtime). + /// \tparam TObject The object type. + /// \param method The member function pointer. + /// \param obj The object. + //************************************************************************* + template + void set(TReturn(TObject::* method)(TArgs...) const, TObjectArg&& obj) + { + using D = etl::decay_t; + static_assert(etl::is_invocable_r::value, + "etl::inplace_function: bound member function is not compatible with the inplace_function signature"); + + using target_t = typename vtable_type::template const_member_target; + + static_assert(Object_Size >= sizeof(target_t), "etl::inplace_function: storage size too small"); + static_assert(Object_Alignment >= alignof(target_t), "etl::inplace_function: storage alignment too small"); + + clear(); + ::new (storage_ptr()) target_t{ method, etl::forward(obj) }; + vtable = vtable_type::template for_const_member(); + } + + //************************************************************************* + /// Create from lambda/functor (runtime). + /// \tparam TLambda The lambda/functor type. + /// \param lambda The lambda/functor. + //************************************************************************* + template ::type, + typename = etl::enable_if_t::value && !is_inplace_function::value, void>> + void set(TLambda& lambda) + { + // Validate that 'method' is invocable with (TObject&, TArgs...) and returns TReturn + static_assert(etl::is_invocable_r::value, + "etl::inplace_function: bound lambda/functor is not compatible with the inplace_function signature"); + + static_assert(Object_Size >= sizeof(T), "etl::inplace_function: Object size too small"); + static_assert(Object_Alignment >= alignof(T), "etl::inplace_function: Object alignment too small"); + + clear(); + + // Construct the object in the storage. + ::new (storage_ptr()) T(lambda); + + + vtable = vtable_type::template for_functor(); + } + + //************************************************************************* + /// Create from const lambda/functor (runtime). + /// \tparam TLambda The lambda/functor type. + /// \param lambda The lambda/functor. + //************************************************************************* + template ::type, + typename = etl::enable_if_t::value && !is_inplace_function::value, void>> + void set(const TLambda& lambda) + { + static_assert(etl::is_invocable_r::value, + "etl::inplace_function: bound lambda/functor is not compatible with the inplace_function signature"); + + static_assert(Object_Size >= sizeof(T), "etl::inplace_function: Object size too small"); + static_assert(Object_Alignment >= alignof(T), "etl::inplace_function: Object alignment too small"); + + clear(); + + // Construct the object in the storage. + ::new (storage_ptr()) T(lambda); + + vtable = vtable_type::template for_const_functor(); + } + + //************************************************************************* + /// Set from a compile-time bound free function. + /// Function must have external linkage. + /// Usage: ipf.template set<&FreeFn>(); + /// \tparam Function The function pointer. + //************************************************************************* + template + void set() + { + static_assert(etl::is_invocable_r::value, + "etl::inplace_function: function pointer is not compatible with the inplace_function signature"); + + clear(); + vtable = vtable_type::template for_compile_time_function(); + } + + //************************************************************************* + /// Set from a compile-time bound non-const member + instance reference. + /// Instance must have external linkage when used as an NTTP. + /// \tparam TObject The object type. + /// \tparam Method The member function pointer. + /// \tparam Instance The instance reference. + //************************************************************************* + template + void set() + { + static_assert(etl::is_invocable_r::value, + "etl::inplace_function: bound member function is not compatible with the inplace_function signature"); + + clear(); + vtable = vtable_type::template for_compile_time_member(); + } + + //************************************************************************* + /// Set from a compile-time bound const member + instance reference. + /// Instance must have external linkage when used as an NTTP. + /// \tparam TObject The object type. + /// \tparam Method The member function pointer. + /// \tparam Instance The instance reference. + //************************************************************************* + template + void set() + { + static_assert(etl::is_invocable_r::value, + "etl::inplace_function: bound member function is not compatible with the inplace_function signature"); + + clear(); + vtable = vtable_type::template for_compile_time_const_member(); + } + + //************************************************************************* + /// operator() + instance reference (compile-time, non-const) + /// \tparam TObject The object type. + /// \tparam Instance The instance reference. + //************************************************************************* + template , + typename = etl::enable_if_t::value && + etl::has_call_operator::value && + !etl::function_traits::is_const>> + void set() + { + static_assert(etl::is_invocable_r::value, + "etl::inplace_function: bound lambda/functor is not compatible with the inplace_function signature"); + + clear(); + vtable = vtable_type::template for_compile_time_operator(); + } + + //************************************************************************* + /// operator() + instance reference (compile-time, const) + /// \tparam TObject The object type. + /// \tparam Instance The instance reference. + //************************************************************************* + template , + typename = etl::enable_if_t::value && + etl::has_call_operator::value && + etl::function_traits::is_const>> + void set() + { + static_assert(etl::is_invocable_r::value, + "etl::inplace_function: bound lambda/functor is not compatible with the inplace_function signature"); + + clear(); + vtable = vtable_type::template for_compile_time_operator(); + } + + //************************************************************************* + /// Free function (external linkage) + /// \tparam Function The function pointer. + /// \return The constructed inplace_function. + //************************************************************************* + template + static this_type create() + { + return this_type(vtable_type::template for_compile_time_function()); + } + + //************************************************************************* + /// Non-const member + instance reference (compile time) + /// \tparam TObject The object type. + /// \tparam Method The member function pointer. + /// \tparam Instance The instance reference. + /// \return The constructed inplace_function. + //************************************************************************* + template + static this_type create() + { + return this_type(vtable_type::template for_compile_time_member()); + } + + //************************************************************************* + /// Const member + instance reference (compile time) + /// \tparam TObject The object type. + /// \tparam Method The member function pointer. + /// \tparam Instance The instance reference. + /// \return The constructed inplace_function. + //************************************************************************* + template + static this_type create() + { + return this_type(vtable_type::template for_compile_time_const_member()); + } + + //************************************************************************* + /// operator() + instance reference (compile time, non-const) + /// \tparam TObject The object type. + /// \tparam Instance The instance reference. + /// \return The constructed inplace_function. + //************************************************************************* + template + static this_type create() + { + return this_type(vtable_type::template for_compile_time_operator()); + } + + //************************************************************************* + /// Assignment operator + /// \param rhs The other inplace_function to copy from. + /// \return The current inplace_function. + //************************************************************************* + inplace_function& operator =(const inplace_function& rhs) + { + if (this != &rhs) + { + clear(); + clone_from(rhs); + } + + return *this; + } + + //************************************************************************* + /// Move assignment operator + /// \param rhs The other inplace_function to move from. + /// \return The current inplace_function. + //************************************************************************* + inplace_function& operator =(inplace_function&& rhs) noexcept + { + if (this != &rhs) + { + clear(); + move_from(rhs); + } + + return *this; + } + + //************************************************************************* + /// Assignment from nullptr + /// Clears the inplace_function. + /// \param nullptr_t Null pointer + /// \return The current inplace_function. + //************************************************************************* + inplace_function& operator =(etl::nullptr_t) noexcept + { + clear(); + + return *this; + } + + //************************************************************************* + /// Assignment from function pointer + /// \param f The function pointer. + /// \return The current inplace_function. + //************************************************************************* + inplace_function& operator =(function_ptr f) + { + set(f); + + return *this; + } + + //************************************************************************* + /// Assignment from lambda/functor (runtime). + /// Enabled only for class types that are not etl::inplace_function. + /// \tparam TLambda The lambda/functor type. + /// \param lambda The lambda/functor. + /// \return The current inplace_function. + //************************************************************************* + template ::type, + typename = etl::enable_if_t::value && !is_inplace_function::value, void>> + inplace_function& operator =(TLambda&& lambda) + { + set(etl::forward(lambda)); + + return *this; + } + + //************************************************************************* + /// Swap with another inplace_function + /// \param other The other inplace_function. + //************************************************************************* + void swap(inplace_function& other) noexcept + { + if (this == &other) + { + return; + } + + do_swap(vtable, storage_ptr(), + other.vtable, other.storage_ptr()); + } + + //************************************************************************* + /// Checks if the inplace_function is valid (has a target). + /// \return true if the inplace_function is valid, false if not. + //************************************************************************* + ETL_NODISCARD + bool is_valid() const noexcept + { + return (vtable != nullptr); + } + + //************************************************************************* + /// Boolean conversion operator. + /// Checks if the inplace_function is valid (has a target). + /// \return true if the inplace_function is valid, false if not. + //************************************************************************* + ETL_NODISCARD + explicit operator bool() const noexcept + { + return is_valid(); + } + + //************************************************************************* + /// Execute the inplace_function. + /// Triggers inplace_function_uninitialized assertion if not valid. + /// \param args The arguments to pass to the inplace_function. + /// \return The result of the invocation. + //************************************************************************* + TReturn operator()(TArgs... args) const + { + ETL_ASSERT(is_valid(), ETL_ERROR(inplace_function_uninitialized)); + + return vtable->invoke(storage_ptr(), etl::forward(args)...); + } + + //************************************************************************* + /// Execute the inplace_function, if valid. + /// 'void' return. + /// \param args The arguments to pass to the inplace_function. + /// \return true if executed, false if not valid. + //************************************************************************* + template + typename etl::enable_if_t::value, bool> + call_if(TArgs... args) const + { + if (is_valid()) + { + vtable->invoke(storage_ptr(), etl::forward(args)...); + return true; + } + else + { + return false; + } + } + + //************************************************************************* + /// Execute the inplace_function if valid. + /// Non 'void' return. + /// \param args The arguments to pass to the inplace_function. + /// \return etl::optional with result if executed, empty etl::optional if not valid. + //************************************************************************* + template + typename etl::enable_if_t::value, etl::optional> + call_if(TArgs... args) const + { + etl::optional result; + + if (is_valid()) + { + result = vtable->invoke(storage_ptr(), etl::forward(args)...); + } + + return result; + } + + //************************************************************************* + /// Execute the inplace_function if valid or call alternative. + /// Run time alternative. + /// \tparam TAlternative The alternative callable. + /// \param alternative The alternative callable. + /// \param args The arguments to pass to the inplace_function or alternative. + /// \return The result of the invocation. + //************************************************************************* + template + TReturn call_or(TAlternative&& alternative, TArgs... args) const + { + if (is_valid()) + { + return vtable->invoke(storage_ptr(), etl::forward(args)...); + } + else + { + return etl::forward(alternative)(etl::forward(args)...); + } + } + + //************************************************************************* + /// Execute the inplace_function if valid or call alternative. + /// Compile time alternative. + /// \tparam Alternative The alternative callable. + /// \param args The arguments to pass to the inplace_function or alternative. + /// \return The result of the invocation. + //************************************************************************* + template + TReturn call_or(TArgs... args) const + { + if (is_valid()) + { + return vtable->invoke(storage_ptr(), etl::forward(args)...); + } + else + { + return (Alternative)(etl::forward(args)...); + } + } + + //************************************************************************* + /// Clears the inplace_function + /// Destroys any stored callable object. + //************************************************************************* + void clear() noexcept + { + if (is_valid()) + { + if (vtable->destroy) + { + vtable->destroy(storage_ptr()); + } + + vtable = nullptr; + } + } + + //************************************************************************* + /// Get the storage size + /// \return The storage size. + //************************************************************************* + ETL_NODISCARD + static constexpr size_t size() noexcept + { + return Object_Size; + } + + //************************************************************************* + /// Get the storage alignment + /// \return The storage alignment. + //************************************************************************* + ETL_NODISCARD + static constexpr size_t alignment() noexcept + { + return Object_Alignment; + } + + private: + + // Allow cross-size access to internals + template + friend class inplace_function; + + //************************************************************************* + // Direct-initialization constructor for CT-bound vtables (no payload). + //************************************************************************* + explicit inplace_function(const vtable_type* vt) noexcept + : vtable(vt) + , storage() + {} + + //************************************************************************* + // clone_from + //************************************************************************* + template + void clone_from(const etl::inplace_function& other) + { + vtable = other.vtable; + + if (vtable && vtable->copy) + { + vtable->copy(&other.storage, &storage); + } + } + + //************************************************************************* + // move_from + //************************************************************************* + template + void move_from(etl::inplace_function& other) + { + vtable = other.vtable; + + if (vtable && vtable->move) + { + vtable->move(&other.storage, &storage); + } + + other.vtable = nullptr; + } + + //************************************************************************* + // Internal swap implementation + //************************************************************************* + static void do_swap(const vtable_type*& vt_a, void* storage_a, + const vtable_type*& vt_b, void* storage_b) noexcept + { + const bool a_valid = (vt_a != nullptr); + const bool b_valid = (vt_b != nullptr); + + if (!a_valid && !b_valid) + { + return; + } + + if (!a_valid) + { + // Only 'b' is valid + if (vt_b->move) + { + vt_b->move(storage_b, storage_a); + } + else if (vt_b->copy) + { + vt_b->copy(storage_b, storage_a); + } + vt_a = vt_b; + vt_b = nullptr; + return; + } + + // Only 'a' is valid + if (!b_valid) + { + if (vt_a->move) + { + vt_a->move(storage_a, storage_b); + } + else if (vt_a->copy) + { + vt_a->copy(storage_a, storage_b); + } + vt_b = vt_a; + vt_a = nullptr; + return; + } + + // Both valid. + // If both have no payload (compile-time bound: no move/copy) just swap vtable pointers. + if (!vt_a->move && !vt_a->copy && + !vt_b->move && !vt_b->copy) + { + const vtable_type* tmp = vt_a; + vt_a = vt_b; + vt_b = tmp; + return; + } + + // General case + alignas(Object_Alignment) unsigned char temp[Object_Size]; + + // a -> temp + if (vt_a->move) + { + vt_a->move(storage_a, temp); + } + else if (vt_a->copy) + { + vt_a->copy(storage_a, temp); + } + + // b -> a + if (vt_b->move) + { + vt_b->move(storage_b, storage_a); + } + else if (vt_b->copy) + { + vt_b->copy(storage_b, storage_a); + } + + // temp -> b + if (vt_a->move) + { + vt_a->move(temp, storage_b); + } + else if (vt_a->copy) + { + vt_a->copy(temp, storage_b); + } + + // Swap vtable pointers + const vtable_type* tmp = vt_a; + vt_a = vt_b; + vt_b = tmp; + } + + //************************************************************************* + // Get pointer to storage as a void* + //************************************************************************* + void* storage_ptr() const noexcept + { + return const_cast(static_cast(&storage)); + } + + const vtable_type* vtable = nullptr; + storage_type storage; + }; + + //************************************************************************* + /// Declare an inplace_function from a single type. + /// \tparam TSignature The function signature. + /// \tparam TStorage The storage type. + //************************************************************************* + template + using inplace_function_for = etl::inplace_function), + alignof(etl::decay_t)>; + + //************************************************************************* + /// Declare an inplace_function from multiple candidates. Picks the largest size/alignment. + /// \tparam TSignature The function signature. + /// \tparam T... The stored candidates types. + //************************************************************************* + template + using inplace_function_for_any = etl::inplace_function, etl::decay_t...>::size, + etl::largest, etl::decay_t...>::alignment>; + + //************************************************************************* + /// Helper to build an inplace_function from a free function pointer. + /// Usage: auto ipf = etl::make_inplace_function(); + /// \param function The function pointer. + /// \return The constructed inplace_function. + //************************************************************************* + template + ETL_NODISCARD + etl::inplace_function + make_inplace_function(TReturn(*function)(TArgs...)) + { + using function_ptr = TReturn(*)(TArgs...); + + return etl::inplace_function_for(function); + } + + //************************************************************************* + /// Helper to build an inplace_function bound to a non-const member function. + /// Usage: auto ipf = etl::make_inplace_function(obj, &Type::Method); + /// \param method The member function pointer. + /// \param obj The object. + /// \return The constructed inplace_function. + //************************************************************************* + template ::template member_target> + ETL_NODISCARD + etl::inplace_function + make_inplace_function(TReturn (TObject::*method)(TArgs...), TObject& obj) + { + return etl::inplace_function_for(method, obj); + } + + //************************************************************************* + /// Helper to build an inplace_function bound to a const member function. + /// Usage: auto ipf = etl::make_inplace_function(obj, &Type::Method) // obj is const + /// \param method The member function pointer. + /// \param obj The object. + /// \return The constructed inplace_function. + //************************************************************************* + template ::template const_member_target> + ETL_NODISCARD + etl::inplace_function + make_inplace_function(TReturn (TObject::*method)(TArgs...) const, const TObject& obj) + { + return etl::inplace_function_for(method, obj); + } + + //************************************************************************* + /// Helper to build an inplace_function from a lambda/functor (non-generic, non-overloaded). + /// Deduces R(Args...) from &T::operator(). + /// Prefer this when operator() is not overloaded/templated. + /// \param lambda The lambda/functor. + /// \return The constructed inplace_function. + //************************************************************************* + template ::type, + typename = typename etl::enable_if_t::value && !is_inplace_function::value, void>, + typename TSignature = typename etl::function_traits::function_type> + ETL_NODISCARD + etl::inplace_function + make_inplace_function(TLambda&& lambda) + { + return etl::inplace_function_for(etl::forward(lambda)); + } + + //************************************************************************* + /// Storage-deducing maker (non-class only) to avoid colliding with functor maker + /// \param function The function-like object. + /// \return The constructed inplace_function. + //************************************************************************* + template ::type, + typename = typename etl::enable_if_t::value, int>> + ETL_NODISCARD + inplace_function_for make_inplace_function(TType&& function) + { + // If T is a function type, use a function pointer for storage sizing. + using storage_t = typename etl::conditional::value, + typename etl::add_pointer::type, + T>::type; + + return inplace_function_for(etl::forward(function)); + } + +#if ETL_USING_CPP17 + //************************************************************************* + /// Make an inplace_function from a function at compile time. + /// Only participates for free function pointers (not member function pointers). + /// \tparam Function The function pointer. + /// \return The constructed inplace_function. + //************************************************************************* + template ::value && etl::is_function>::value>> + ETL_NODISCARD + auto make_inplace_function() + { + using function_type = typename etl::function_traits::function_type; + + return etl::inplace_function::template create(); + } + + //************************************************************************* + /// Make an inplace_function from a member function at compile time. + /// \tparam TObject The object type. + /// \tparam Method The member function pointer. + /// \tparam Instance The instance reference. + /// \return The constructed inplace_function. + //************************************************************************* + template ::value>, + typename = etl::enable_if_t::is_const>> + ETL_NODISCARD + auto make_inplace_function() + { + using function_type = typename etl::function_traits::function_type; + + return etl::inplace_function::template create(); + } + + //************************************************************************* + /// Make an inplace_function from a const member function at compile time. + /// \tparam TObject The object type. + /// \tparam Method The member function pointer. + /// \tparam Instance The instance reference. + /// \return The constructed inplace_function. + //************************************************************************* + template ::value>, + typename = etl::enable_if_t::is_const>> + ETL_NODISCARD + auto make_inplace_function() + { + using function_type = typename etl::function_traits::function_type; + + return etl::inplace_function::template create(); + } + + //************************************************************************* + /// Make an inplace_function from operator() at compile time. + /// \tparam TObject The object type. + /// \tparam Instance The instance reference. + /// \return The constructed inplace_function. + //************************************************************************* + template , + typename = etl::enable_if_t::value && etl::has_call_operator::value>> + ETL_NODISCARD + auto make_inplace_function() + { + using function_type = typename etl::function_traits::function_type; + + return etl::inplace_function::template create(); + } +#endif + + //************************************************************************* + /// Swap two inplace_functions. + /// \param lhs The first inplace_function. + /// \param rhs The second inplace_function. + //************************************************************************* + template + void swap(etl::inplace_function& lhs, etl::inplace_function& rhs) noexcept + { + lhs.swap(rhs); + } + + //************************************************************************* + /// Check inplace_function for equality with nullptr. + /// \param lhs The inplace_function. + /// \param rhs The nullptr. + /// \returns true if equal. + //************************************************************************* + template + ETL_NODISCARD + bool operator ==(const etl::inplace_function& lhs, etl::nullptr_t) + { + return !lhs.is_valid(); + } + + //************************************************************************* + /// Check inplace_function for equality with nullptr. + /// \param lhs The nullptr. + /// \param rhs The inplace_function. + /// \returns true if equal. + //************************************************************************* + template + ETL_NODISCARD + bool operator ==(etl::nullptr_t, const etl::inplace_function& rhs) + { + return !rhs.is_valid(); + } + + //************************************************************************* + /// Check inplace_function for inequality with nullptr. + /// \param lhs The inplace_function. + /// \param rhs The nullptr. + /// \returns true if not equal. + //************************************************************************* + template + ETL_NODISCARD + bool operator !=(const etl::inplace_function& lhs, etl::nullptr_t) + { + return lhs.is_valid(); + } + + //************************************************************************* + /// Check inplace_function for inequality with nullptr. + /// \param lhs The nullptr. + /// \param rhs The inplace_function. + /// \returns true if not equal. + //************************************************************************* + template + ETL_NODISCARD + bool operator !=(etl::nullptr_t, const etl::inplace_function& rhs) + { + return rhs.is_valid(); + } +} + +#endif +#endif \ No newline at end of file diff --git a/include/etl/invoke.h b/include/etl/invoke.h index efd0dc07..be9bbbfb 100644 --- a/include/etl/invoke.h +++ b/include/etl/invoke.h @@ -36,7 +36,6 @@ SOFTWARE. #include "function_traits.h" #include "type_traits.h" #include "utility.h" -#include "type_list.h" #if ETL_USING_CPP11 @@ -173,6 +172,37 @@ namespace etl static ETL_CONSTANT bool value = type::value; }; + //******************************************* + // Result type of a valid invocation. + template + struct invoke_result_impl + { + template + static auto test(int) -> decltype(etl::invoke(etl::declval(), etl::declval()...)); + + template + static void test(...); + + using type = decltype(test(0)); + }; + + //******************************************* + // Result type of a valid invocation. + template + struct invoke_result_impl> + { + template + static auto test(int) -> decltype(etl::invoke(etl::declval(), etl::declval()...)); + + template + static void test(...); + + using type = decltype(test(0)); + }; + + template + using invoke_result_impl_t = typename invoke_result_impl::type; + //******************************************* // Map raw function type to pointer. template @@ -195,7 +225,31 @@ namespace etl etl::void_t(), etl::declval()...))>, TArgs...> { - using type = decltype(etl::invoke(etl::declval(), etl::declval()...)); + private: + + using FC = private_invoke::effective_callable_t; + + public: + + using type = etl::conditional_t::value, + private_invoke::invoke_result_impl_t, + void>; + }; + + //**************************************************************************** + /// invoke_result> + template + struct invoke_result> + { + private: + + using FC = private_invoke::effective_callable_t; + + public: + + using type = etl::conditional_t::value, + private_invoke::invoke_result_impl_t, + void>; }; //******************************************* diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 26333f79..899ae047 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -201,6 +201,7 @@ add_executable(etl_tests 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 @@ -209,9 +210,10 @@ add_executable(etl_tests test_intrusive_queue.cpp test_intrusive_stack.cpp test_invert.cpp - test_io_port.cpp - test_iterator.cpp test_invoke.cpp + test_io_port.cpp + test_is_invocable.cpp + test_iterator.cpp test_jenkins.cpp test_largest.cpp test_limiter.cpp diff --git a/test/syntax_check/CMakeLists.txt b/test/syntax_check/CMakeLists.txt index 8df498b4..0e2627df 100644 --- a/test/syntax_check/CMakeLists.txt +++ b/test/syntax_check/CMakeLists.txt @@ -217,6 +217,7 @@ target_sources(tests PRIVATE imemory_block_allocator.h.t.cpp indirect_vector.h.t.cpp initializer_list.h.t.cpp + inplace_function.h.t.cpp instance_count.h.t.cpp integral_limits.h.t.cpp intrusive_forward_list.h.t.cpp @@ -225,6 +226,7 @@ target_sources(tests PRIVATE intrusive_queue.h.t.cpp intrusive_stack.h.t.cpp invert.h.t.cpp + invoke.h.t.cpp io_port.h.t.cpp ipool.h.t.cpp ireference_counted_message_pool.h.t.cpp diff --git a/test/syntax_check/inplace_function.h.t.cpp b/test/syntax_check/inplace_function.h.t.cpp new file mode 100644 index 00000000..af3ac7d4 --- /dev/null +++ b/test/syntax_check/inplace_function.h.t.cpp @@ -0,0 +1,29 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include diff --git a/test/syntax_check/invoke.h.t.cpp b/test/syntax_check/invoke.h.t.cpp new file mode 100644 index 00000000..40ed37b2 --- /dev/null +++ b/test/syntax_check/invoke.h.t.cpp @@ -0,0 +1,29 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include diff --git a/test/test_inplace_function.cpp b/test/test_inplace_function.cpp new file mode 100644 index 00000000..27fd5407 --- /dev/null +++ b/test/test_inplace_function.cpp @@ -0,0 +1,1780 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "unit_test_framework.h" + +#include "etl/inplace_function.h" +#include "etl/vector.h" + +#include +#include +#include +#include +#include + +// Enable exactly one of these at a time to see the corresponding static_assert fire. +//#define ETL_NEGATIVE_TEST_INPLACE_FUNCTION_BAD_RETURN +//#define ETL_NEGATIVE_TEST_INPLACE_FUNCTION_RVALUE_PARAM_MISMATCH_NONCONST +//#define ETL_NEGATIVE_TEST_INPLACE_FUNCTION_RVALUE_PARAM_MISMATCH_CONST + +namespace +{ + //***************************************************************************** + enum class FunctionCalled : int + { + Not_Called, + Free_Void_Called, + Free_Int_Called, + Free_Reference_Called, + Free_Moveableonly_Called, + Normal_Called, + Normal_Returning_Void_Called, + Alternative_Called, + Member_Void_Called, + Member_Void_Const_Called, + Member_Int_Called, + Member_Int_Const_Called, + Member_Reference_Called, + Member_Reference_Const_Called, + Member_Moveableonly_Called, + Member_Static_Called, + Operator_Called, + Operator_Const_Called, + Lambda_Called + }; + + FunctionCalled function_called = FunctionCalled::Not_Called; + + //***************************************************************************** + const int VALUE1 = 1; + const int VALUE2 = 2; + bool parameter_correct = false; + + //***************************************************************************** + // Object data structure. + //***************************************************************************** + struct Data + { + int ipf; + }; + + //***************************************************************************** + // Object moveable only data structure. + //***************************************************************************** + struct MoveableOnlyData + { + MoveableOnlyData() = default; + ~MoveableOnlyData() = default; + MoveableOnlyData(const MoveableOnlyData&) = delete; + MoveableOnlyData& operator=(const MoveableOnlyData&) = delete; + MoveableOnlyData(MoveableOnlyData&&) = default; + MoveableOnlyData& operator=(MoveableOnlyData&&) = default; + int ipf; + }; + + //***************************************************************************** + // The free function taking no parameters. + //***************************************************************************** + static void free_void() + { + function_called = FunctionCalled::Free_Void_Called; + } + + //***************************************************************************** + // The free function taking an int parameter. + //***************************************************************************** + void free_int(int i, int j) + { + function_called = FunctionCalled::Free_Int_Called; + parameter_correct = (i == VALUE1) && (j == VALUE2); + } + + //***************************************************************************** + // The free function taking a Data reference parameter. + //***************************************************************************** + void free_reference(const Data& data, int j) + { + function_called = FunctionCalled::Free_Reference_Called; + parameter_correct = (data.ipf == VALUE1) && (j == VALUE2); + } + + //***************************************************************************** + // The free function taking a moveable only parameter. + //***************************************************************************** + void free_moveableonly(MoveableOnlyData&& data) + { + function_called = FunctionCalled::Free_Moveableonly_Called; + parameter_correct = (data.ipf == VALUE1); + } + + //***************************************************************************** + // The normal function. + //***************************************************************************** + int normal(int i, int j) + { + function_called = FunctionCalled::Normal_Called; + parameter_correct = (i == VALUE1) && (j == VALUE2); + + return i + j; + } + + //***************************************************************************** + // The normal function returning void. + //***************************************************************************** + void normal_returning_void(int i, int j) + { + function_called = FunctionCalled::Normal_Returning_Void_Called; + parameter_correct = (i == VALUE1) && (j == VALUE2); + } + + //***************************************************************************** + // The alternative function. + //***************************************************************************** + int alternative(int i, int j) + { + function_called = FunctionCalled::Alternative_Called; + parameter_correct = (i == VALUE1) && (j == VALUE2); + + return i + j + 1; + } + + //***************************************************************************** + // The throwing function. + //***************************************************************************** + void throwing_void() + { + throw std::runtime_error("throwing function"); + } + + int throwing_normal(int, int) + { + throw std::runtime_error("throwing function with two parameters"); + } + + //******************************************* + // Functor with non-const operator() + struct Functor + { + void operator()() + { + function_called = FunctionCalled::Operator_Called; + } + }; + + //******************************************* + // Functor with const operator() + struct FunctorConst + { + void operator()() const + { + function_called = FunctionCalled::Operator_Const_Called; + } + }; + + //******************************************* + int times_2(int a) + { + return a * 2; + } + + //******************************************* + // Free int return. + int free_int_return(int i, int j) + { + return i + j; + } + +#if ETL_USING_CPP17 + static auto global_lambda = [](int i, int j) + { + function_called = FunctionCalled::Lambda_Called; + parameter_correct = (i == VALUE1) && (j == VALUE2); + }; +#endif + + //******************************************* + // Functor with that is destructible and movable + //******************************************* + struct DestructibleMovableObject + { + DestructibleMovableObject() + : call_count(0) + { + destructor_called = false; + copy_constructor_called = false; + move_constructor_called = false; + function_operator_called = false; + } + + ~DestructibleMovableObject() + { + destructor_called = true; + } + + DestructibleMovableObject(const DestructibleMovableObject& other) + : call_count(other.call_count) + { + copy_constructor_called = true; + } + + DestructibleMovableObject(DestructibleMovableObject&& other) + : call_count(other.call_count) + { + move_constructor_called = true; + } + + void operator()(int, int) + { + function_operator_called = true; + ++call_count; + } + + static bool destructor_called; + static bool copy_constructor_called; + static bool move_constructor_called; + static bool function_operator_called; + + int call_count; + }; + + bool DestructibleMovableObject::destructor_called = false; + bool DestructibleMovableObject::copy_constructor_called = false; + bool DestructibleMovableObject::move_constructor_called = false; + bool DestructibleMovableObject::function_operator_called = false; + + //******************************************* + // Sized functor + template + struct FunctorSized + { + FunctorSized() + : data() + { + } + + int operator()() + { + function_called = FunctionCalled::Operator_Called; + + return Size; + } + + int size() const + { + return Size; + } + + char data[Size]; + }; +} + +//***************************************************************************** +// The test class with member functions. +//***************************************************************************** +class Object +{ +public: + + //******************************************* + constexpr Object() + : call_count(0) + { + } + + //******************************************* + // void + void member_void() + { + function_called = FunctionCalled::Member_Void_Called; + } + + void member_void_const() const + { + function_called = FunctionCalled::Member_Void_Const_Called; + } + + //******************************************* + // int + int member_int(int i, int j) + { + function_called = FunctionCalled::Member_Int_Called; + parameter_correct = (i == VALUE1) && (j == VALUE2); + + ++call_count; + + return i + j + 1; + } + + int member_int_const(int i, int j) const + { + function_called = FunctionCalled::Member_Int_Const_Called; + parameter_correct = (i == VALUE1) && (j == VALUE2); + + ++call_count; + + return i + j + 1; + } + + //******************************************* + // reference + void member_reference(const Data& data, int j) + { + function_called = FunctionCalled::Member_Reference_Called; + parameter_correct = (data.ipf == VALUE1) && (j == VALUE2); + } + + void member_reference_const(const Data& data, int j) const + { + function_called = FunctionCalled::Member_Reference_Const_Called; + parameter_correct = (data.ipf == VALUE1) && (j == VALUE2); + + ++call_count; + } + + //******************************************* + // moveable only data + void member_moveableonly(MoveableOnlyData&& data) + { + function_called = FunctionCalled::Member_Moveableonly_Called; + parameter_correct = (data.ipf == VALUE1); + + ++call_count; + } + + //******************************************* + // static + static void member_static(const Data& data, int j) + { + function_called = FunctionCalled::Member_Static_Called; + parameter_correct = (data.ipf == VALUE1) && (j == VALUE2); + } + + //******************************************* + // operator() + void operator()() + { + function_called = FunctionCalled::Operator_Called; + + ++call_count; + } + + //******************************************* + // operator() const + void operator()() const + { + function_called = FunctionCalled::Operator_Const_Called; + + ++call_count; + } + + mutable int call_count; +}; + +Object object_static; +constexpr const Object const_object_static; + +Functor functor_static; +const FunctorConst const_functor_static; + +namespace +{ + //***************************************************************************** + // Initialises the test results. + //***************************************************************************** + struct SetupFixture + { + SetupFixture() + { + function_called = FunctionCalled::Not_Called; + parameter_correct = false; + } + }; + + SUITE(test_inplace_function) + { + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_inplace_function_types) + { + using InplaceFunction = etl::inplace_function; + + // Check the return type. + CHECK_TRUE((std::is_same::value)); + + // Check the argument types. + CHECK_TRUE((std::is_same>::value)); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_inplace_function_size_and_alignment) + { + using InplaceFunction84 = etl::inplace_function; + using InplaceFunction168 = etl::inplace_function; + + // Check the sizes. + CHECK_EQUAL(8, InplaceFunction84::size()); + CHECK_EQUAL(16, InplaceFunction168::size()); + + // Check the alignments. + CHECK_EQUAL(4, InplaceFunction84::alignment()); + CHECK_EQUAL(8, InplaceFunction168::alignment()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_is_valid_false) + { + etl::inplace_function ipf; + + CHECK(!ipf.is_valid()); + CHECK(!ipf); + + CHECK_THROW(ipf(), etl::inplace_function_uninitialized); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_is_valid_true) + { + auto lambda = [] {}; + + etl::inplace_function ipf(lambda); + + CHECK(ipf.is_valid()); + CHECK(ipf); + CHECK_NO_THROW(ipf()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_is_valid_after_clear) + { + auto lambda = [] {}; + + etl::inplace_function ipf(lambda); + + CHECK_TRUE(ipf.is_valid()); + ipf.clear(); + CHECK_FALSE(ipf.is_valid()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_free_void_run_time) + { + etl::inplace_function ipf(free_void); + + ipf(); + + CHECK(function_called == FunctionCalled::Free_Void_Called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_free_void_compile_time) + { + auto ipf = etl::inplace_function::create(); + + ipf(); + + CHECK(function_called == FunctionCalled::Free_Void_Called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_make_free_void_run_time) + { + auto ipf = etl::make_inplace_function(free_void); + + ipf(); + + CHECK(function_called == FunctionCalled::Free_Void_Called); + } + +#if ETL_USING_CPP17 + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_make_free_void_compile_time) + { + auto ipf = etl::make_inplace_function<&free_void>(); + + ipf(); + + CHECK(function_called == FunctionCalled::Free_Void_Called); + } +#endif + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_throwing) + { + { + auto ipf = etl::inplace_function::create(); + + CHECK_THROW(ipf(), std::runtime_error); + CHECK_THROW(ipf.call_if(), std::runtime_error); + } + + { + auto ipf = etl::inplace_function::create(); + + CHECK_THROW({ipf.call_or(alternative, VALUE1, VALUE2);}, std::runtime_error); + CHECK_THROW({ipf.call_or(VALUE1, VALUE2);}, std::runtime_error); + } + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_free_int_run_time) + { + etl::inplace_function ipf(free_int); + + ipf(VALUE1, VALUE2); + + CHECK(function_called == FunctionCalled::Free_Int_Called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_free_int_compile_time) + { + auto ipf = etl::inplace_function::create(); + + ipf(VALUE1, VALUE2); + + CHECK(function_called == FunctionCalled::Free_Int_Called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_make_free_int_run_time) + { + auto ipf = etl::make_inplace_function(free_int); + + ipf(VALUE1, VALUE2); + + CHECK(function_called == FunctionCalled::Free_Int_Called); + CHECK(parameter_correct); + } + +#if ETL_USING_CPP17 + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_make_free_int_compile_time) + { + auto ipf = etl::make_inplace_function<&free_int>(); + + ipf(VALUE1, VALUE2); + + CHECK(function_called == FunctionCalled::Free_Int_Called); + CHECK(parameter_correct); + } +#endif + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_free_reference_run_time) + { + etl::inplace_function ipf(free_reference); + + Data data; + data.ipf = VALUE1; + + ipf(data, VALUE2); + + CHECK(function_called == FunctionCalled::Free_Reference_Called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_free_reference_compile_time) + { + auto ipf = etl::inplace_function::create(); + + Data data; + data.ipf = VALUE1; + + ipf(data, VALUE2); + + CHECK(function_called == FunctionCalled::Free_Reference_Called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_make_free_reference_run_time) + { + auto ipf = etl::make_inplace_function(free_reference); + + Data data; + data.ipf = VALUE1; + + ipf(data, VALUE2); + + CHECK(function_called == FunctionCalled::Free_Reference_Called); + CHECK(parameter_correct); + } + +#if ETL_USING_CPP17 + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_make_free_reference_compile_time) + { + auto ipf = etl::make_inplace_function<&free_reference>(); + + Data data; + data.ipf = VALUE1; + + ipf(data, VALUE2); + + CHECK(function_called == FunctionCalled::Free_Reference_Called); + CHECK(parameter_correct); + } +#endif + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_free_moveableonly_run_time) + { + etl::inplace_function ipf(free_moveableonly); + + MoveableOnlyData data; + data.ipf = VALUE1; + + ipf(std::move(data)); + + CHECK(function_called == FunctionCalled::Free_Moveableonly_Called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_free_moveableonly_compile_time) + { + auto ipf = etl::inplace_function::create(); + + MoveableOnlyData data; + data.ipf = VALUE1; + + ipf(std::move(data)); + + CHECK(function_called == FunctionCalled::Free_Moveableonly_Called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_make_free_moveableonly_run_time) + { + auto ipf = etl::make_inplace_function(free_moveableonly); + + MoveableOnlyData data; + data.ipf = VALUE1; + + ipf(std::move(data)); + + CHECK(function_called == FunctionCalled::Free_Moveableonly_Called); + CHECK(parameter_correct); + } + +#if ETL_USING_CPP17 + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_make_free_moveableonly_compile_time) + { + auto ipf = etl::make_inplace_function<&free_moveableonly>(); + + MoveableOnlyData data; + data.ipf = VALUE1; + + ipf(std::move(data)); + + CHECK(function_called == FunctionCalled::Free_Moveableonly_Called); + CHECK(parameter_correct); + } +#endif + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_lambda_int) + { + auto lambda = [](int i, int j) { function_called = FunctionCalled::Lambda_Called; parameter_correct = (i == VALUE1) && (j == VALUE2); }; + + etl::inplace_function ipf(lambda); + + ipf(VALUE1, VALUE2); + + CHECK(function_called == FunctionCalled::Lambda_Called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_make_inplace_function_lambda_int_run_time) + { + auto lambda = [](int i, int j) { function_called = FunctionCalled::Lambda_Called; parameter_correct = (i == VALUE1) && (j == VALUE2); }; + + auto ipf = etl::make_inplace_function(lambda); + + ipf(VALUE1, VALUE2); + + CHECK(function_called == FunctionCalled::Lambda_Called); + CHECK(parameter_correct); + } + +#if ETL_USING_CPP17 + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_make_inplace_function_lambda_int_compile_time) + { + static auto lambda = [](int i, int j) { function_called = FunctionCalled::Lambda_Called; parameter_correct = (i == VALUE1) && (j == VALUE2); }; + + auto ipf = etl::make_inplace_function(); + + ipf(VALUE1, VALUE2); + + CHECK(function_called == FunctionCalled::Lambda_Called); + CHECK(parameter_correct); + } +#endif + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_capturing_lambda_int) + { + int value = VALUE1; + + auto lambda = [value](int i, int j) -> int { function_called = FunctionCalled::Lambda_Called; parameter_correct = (i == VALUE1) && (j == VALUE2); return value + VALUE1 + VALUE2; }; + + etl::inplace_function ipf(lambda); + + int result = ipf(VALUE1, VALUE2); + + CHECK(function_called == FunctionCalled::Lambda_Called); + CHECK(parameter_correct); + CHECK_EQUAL(result, VALUE1 + VALUE1 + VALUE2); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_make_inplace_function_capturing_lambda_int_run_time) + { + int value = VALUE1; + + auto lambda = [value](int i, int j) -> int { function_called = FunctionCalled::Lambda_Called; parameter_correct = (i == VALUE1) && (j == VALUE2); return value + VALUE1 + VALUE2; }; + + auto ipf = etl::make_inplace_function(lambda); + + int result = ipf(VALUE1, VALUE2); + + CHECK(function_called == FunctionCalled::Lambda_Called); + CHECK(parameter_correct); + CHECK_EQUAL(result, VALUE1 + VALUE1 + VALUE2); + } + +#if ETL_USING_CPP17 + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_make_inplace_function_capturing_lambda_int_compile_time) + { + int value = VALUE1; + + static auto lambda = [value](int i, int j) -> int { function_called = FunctionCalled::Lambda_Called; parameter_correct = (i == VALUE1) && (j == VALUE2); return value + VALUE1 + VALUE2; }; + + auto ipf = etl::make_inplace_function(); + + int result = ipf(VALUE1, VALUE2); + + CHECK(function_called == FunctionCalled::Lambda_Called); + CHECK(parameter_correct); + CHECK_EQUAL(result, VALUE1 + VALUE1 + VALUE2); + } +#endif + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_member_operator_void) + { + Object object; + + etl::inplace_function ipf(object); + + ipf(); + + CHECK_EQUAL(0, object.call_count); // Ensure the original object is not modified. + CHECK(function_called == FunctionCalled::Operator_Called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_member_operator_void_const) + { + const Object object; + + etl::inplace_function ipf(object); + + ipf(); + + CHECK_EQUAL(0, object.call_count); // Ensure the original object is not modified. + CHECK(function_called == FunctionCalled::Operator_Const_Called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_make_inplace_function_member_operator_void_const) + { + const FunctorConst object; + + auto ipf = etl::make_inplace_function(object); + + ipf(); + + CHECK(function_called == FunctionCalled::Operator_Const_Called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_member_operator_void_compile_time) + { + auto ipf = etl::inplace_function::create(); + + ipf(); + + CHECK(function_called == FunctionCalled::Operator_Called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_member_operator_void_compile_time_const) + { + auto ipf = etl::inplace_function::create(); + + ipf(); + + CHECK(function_called == FunctionCalled::Operator_Const_Called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_make_inplace_functor_operator_void_run_time) + { + auto ipf = etl::make_inplace_function(functor_static); + + ipf(); + + CHECK(function_called == FunctionCalled::Operator_Called); + } + + //************************************************************************* +#if ETL_USING_CPP17 + TEST_FIXTURE(SetupFixture, test_make_inplace_functor_operator_void_compile_time) + { + auto ipf = etl::make_inplace_function(); + + ipf(); + + CHECK(function_called == FunctionCalled::Operator_Called); + } +#endif + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_make_inplace_function_member_operator_const_void_run_time) + { + auto ipf = etl::make_inplace_function(const_functor_static); + + ipf(); + + CHECK(function_called == FunctionCalled::Operator_Const_Called); + } + + //************************************************************************* +#if ETL_USING_CPP17 + TEST_FIXTURE(SetupFixture, test_make_inplace_function_member_operator_const_void_compile_time) + { + auto ipf = etl::make_inplace_function(); + + ipf(); + + CHECK(function_called == FunctionCalled::Operator_Const_Called); + } +#endif + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_assignment_member_operator_void) + { + Object object; + + etl::inplace_function ipf; + + ipf = object; + + ipf(); + + CHECK_EQUAL(0, object.call_count); // Ensure the original object is not modified. + CHECK(function_called == FunctionCalled::Operator_Called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_member_void) + { + auto ipf = etl::inplace_function::create(); + + ipf(); + + CHECK(function_called == FunctionCalled::Member_Void_Called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_make_inplace_function_member_void_run_time) + { + static Object object; + + auto ipf = etl::make_inplace_function(&Object::member_void, object); + + ipf(); + + CHECK_EQUAL(0, object.call_count); // Ensure the original object is not modified. + CHECK(function_called == FunctionCalled::Member_Void_Called); + } + +#if ETL_USING_CPP17 + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_make_inplace_function_member_void_compile_time) + { + auto ipf = etl::make_inplace_function(); + + ipf(); + + CHECK(function_called == FunctionCalled::Member_Void_Called); + } +#endif + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_member_void_const) + { + auto ipf = etl::inplace_function::create(); + + ipf(); + + CHECK(function_called == FunctionCalled::Member_Void_Const_Called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_make_inplace_function_member_void_const_run_time) + { + static const Object object; + + auto ipf = etl::make_inplace_function(&Object::member_void_const, object); + + ipf(); + + CHECK_EQUAL(0, object.call_count); // Ensure the original object is not modified. + CHECK(function_called == FunctionCalled::Member_Void_Const_Called); + } + + //************************************************************************* +#if ETL_USING_CPP17 + TEST_FIXTURE(SetupFixture, test_make_inplace_function_member_void_const_compile_time) + { + auto ipf = etl::make_inplace_function(); + + ipf(); + + CHECK(function_called == FunctionCalled::Member_Void_Const_Called); + } +#endif + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_member_int) + { + auto ipf = etl::inplace_function::create(); + + ipf(VALUE1, VALUE2); + + CHECK(function_called == FunctionCalled::Member_Int_Called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_make_inplace_function_member_int_run_time) + { + Object object; + + auto ipf = etl::make_inplace_function(&Object::member_int, object); // Pass it by value to the inplace function. + + ipf(VALUE1, VALUE2); + + CHECK_EQUAL(0, object.call_count); // Ensure the original object is not modified. + CHECK(function_called == FunctionCalled::Member_Int_Called); + CHECK(parameter_correct); + } + + //************************************************************************* +#if ETL_USING_CPP17 + TEST_FIXTURE(SetupFixture, test_make_inplace_function_member_int_compile_time) + { + auto ipf = etl::make_inplace_function(); + + ipf(VALUE1, VALUE2); + + CHECK(function_called == FunctionCalled::Member_Int_Called); + CHECK(parameter_correct); + } +#endif + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_member_int_const) + { + auto ipf = etl::inplace_function::create(); + + ipf(VALUE1, VALUE2); + + CHECK(function_called == FunctionCalled::Member_Int_Const_Called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_make_inplace_function_member_int_const_run_time) + { + Object object; + + auto ipf = etl::make_inplace_function(&Object::member_int_const, object); + + ipf(VALUE1, VALUE2); + + CHECK_EQUAL(0, object.call_count); // Ensure the original object is not modified. + CHECK(function_called == FunctionCalled::Member_Int_Const_Called); + CHECK(parameter_correct); + } + + //************************************************************************* +#if ETL_USING_CPP17 + TEST_FIXTURE(SetupFixture, test_make_inplace_function_member_int_const_compile_time) + { + auto ipf = etl::make_inplace_function(); + + ipf(VALUE1, VALUE2); + + CHECK(function_called == FunctionCalled::Member_Int_Const_Called); + CHECK(parameter_correct); + } +#endif + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_member_reference) + { + Object object; + auto ipf = etl::inplace_function(&Object::member_reference, object); + + Data data; + data.ipf = VALUE1; + + ipf(data, VALUE2); + + CHECK_EQUAL(0, object.call_count); // Ensure the original object is not modified. + CHECK(function_called == FunctionCalled::Member_Reference_Called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_make_member_reference_run_time) + { + Object object; + auto ipf = etl::make_inplace_function(&Object::member_reference, object); + + Data data; + data.ipf = VALUE1; + + ipf(data, VALUE2); + + CHECK_EQUAL(0, object.call_count); // Ensure the original object is not modified. + CHECK(function_called == FunctionCalled::Member_Reference_Called); + CHECK(parameter_correct); + } + +#if ETL_USING_CPP17 + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_make_member_reference_compile_time) + { + auto ipf = etl::make_inplace_function(); + + Data data; + data.ipf = VALUE1; + + ipf(data, VALUE2); + + CHECK(function_called == FunctionCalled::Member_Reference_Called); + CHECK(parameter_correct); + } +#endif + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_member_reference_const) + { + Object object; + auto ipf = etl::inplace_function(&Object::member_reference_const, object); + + Data data; + data.ipf = VALUE1; + + ipf(data, VALUE2); + + CHECK_EQUAL(0, object.call_count); // Ensure the original object is not modified. + CHECK(function_called == FunctionCalled::Member_Reference_Const_Called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_make_member_reference_run_time_const) + { + Object object; + auto ipf = etl::make_inplace_function(&Object::member_reference_const, object); + + Data data; + data.ipf = VALUE1; + + ipf(data, VALUE2); + + CHECK_EQUAL(0, object.call_count); // Ensure the original object is not modified. + CHECK(function_called == FunctionCalled::Member_Reference_Const_Called); + CHECK(parameter_correct); + } + +#if ETL_USING_CPP17 + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_make_member_reference_compile_time_const) + { + auto ipf = etl::make_inplace_function(); + + Data data; + data.ipf = VALUE1; + + ipf(data, VALUE2); + + CHECK(function_called == FunctionCalled::Member_Reference_Const_Called); + CHECK(parameter_correct); + } +#endif + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_member_moveableonly) + { + Object object; + auto ipf = etl::inplace_function(&Object::member_moveableonly, object); + + MoveableOnlyData data; + data.ipf = VALUE1; + + ipf(std::move(data)); + + CHECK_EQUAL(0, object.call_count); // Ensure the original object is not modified. + CHECK(function_called == FunctionCalled::Member_Moveableonly_Called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_member_static) + { + auto ipf = etl::inplace_function(Object::member_static); + + Data data; + data.ipf = VALUE1; + + ipf(data, VALUE2); + + CHECK(function_called == FunctionCalled::Member_Static_Called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_make_member_static_run_time) + { + auto ipf = etl::make_inplace_function(Object::member_static); + + Data data; + data.ipf = VALUE1; + + ipf(data, VALUE2); + + CHECK(function_called == FunctionCalled::Member_Static_Called); + CHECK(parameter_correct); + } + +#if ETL_USING_CPP17 + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_make_member_static_compile_time) + { + auto ipf = etl::make_inplace_function(); + + Data data; + data.ipf = VALUE1; + + ipf(data, VALUE2); + + CHECK(function_called == FunctionCalled::Member_Static_Called); + CHECK(parameter_correct); + } +#endif + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_set_free_int_run_time) + { + // Start with a destructible object to check that it is properly destroyed + DestructibleMovableObject object; + etl::inplace_function ipf(object); + + ipf.set(free_int); + + CHECK_TRUE(DestructibleMovableObject::destructor_called); + + ipf(VALUE1, VALUE2); + + CHECK_EQUAL(0, object.call_count); // Ensure the original object is not modified. + CHECK(function_called == FunctionCalled::Free_Int_Called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_set_free_int_compile_time) + { + etl::inplace_function ipf; + + ipf.set<&free_int>(); + + ipf(VALUE1, VALUE2); + + CHECK(function_called == FunctionCalled::Free_Int_Called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_set_lambda_int_run_time) + { + etl::inplace_function ipf; + + auto lambda = [](int i, int j) { function_called = FunctionCalled::Lambda_Called; parameter_correct = (i == VALUE1) && (j == VALUE2); }; + + ipf.set(lambda); + + ipf(VALUE1, VALUE2); + + CHECK(function_called == FunctionCalled::Lambda_Called); + CHECK(parameter_correct); + } + +#if ETL_USING_CPP17 + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_set_lambda_int_compile_time) + { + etl::inplace_function ipf; + + ipf.set(); + + ipf(VALUE1, VALUE2); + + CHECK(function_called == FunctionCalled::Lambda_Called); + CHECK(parameter_correct); + } +#endif + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_set_functor_run_time) + { + etl::inplace_function ipf; + + Functor functor; + + ipf.set(functor); + + ipf(); + + CHECK(function_called == FunctionCalled::Operator_Called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_set_functor_compile_time) + { + etl::inplace_function ipf; + + ipf.set(); + + ipf(); + + CHECK(function_called == FunctionCalled::Operator_Called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_set_member_reference_run_time) + { + Object object; + etl::inplace_function ipf; + + ipf.set(&Object::member_reference, object); + + Data data; + data.ipf = VALUE1; + + ipf(data, VALUE2); + + CHECK_EQUAL(0, object.call_count); // Ensure the original object is not modified. + CHECK(function_called == FunctionCalled::Member_Reference_Called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_set_member_reference_compile_time) + { + Object object; + etl::inplace_function ipf; + + ipf.set(&Object::member_reference, object); + + Data data; + data.ipf = VALUE1; + + ipf(data, VALUE2); + + CHECK(function_called == FunctionCalled::Member_Reference_Called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_set_member_reference_const_run_time) + { + const Object object; + etl::inplace_function ipf; + + ipf.set(&Object::member_reference_const, object); + + Data data; + data.ipf = VALUE1; + + ipf(data, VALUE2); + + CHECK_EQUAL(0, object.call_count); // Ensure the original object is not modified. + CHECK(function_called == FunctionCalled::Member_Reference_Const_Called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_set_member_reference_const_compile_time) + { + const Object object; + etl::inplace_function ipf; + + ipf.set(&Object::member_reference_const, object); + + Data data; + data.ipf = VALUE1; + + ipf(data, VALUE2); + + CHECK(function_called == FunctionCalled::Member_Reference_Const_Called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_construct_run_time_contruction) + { + Object object; + + auto d1 = etl::inplace_function(&Object::member_int, object); + auto d2(d1); + + d2(VALUE1, VALUE2); + + CHECK_EQUAL(0, object.call_count); // Ensure the original object is not modified. + CHECK(function_called == FunctionCalled::Member_Int_Called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_construct_compile_time_contruction) + { + auto d1 = etl::inplace_function::create(); + auto d2(d1); + + d2(VALUE1, VALUE2); + + CHECK(function_called == FunctionCalled::Member_Int_Called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_construct_different_size) + { + auto d1 = etl::inplace_function(free_int); + auto d2 = etl::inplace_function(free_int); + auto d3 = etl::inplace_function(free_int); + auto d4 = etl::inplace_function(free_int); + + // These should not trigger any static asserts. + decltype(d1) d1_1_copy(d1); + decltype(d1) d1_4_copy(d4); + + decltype(d2) d2_1_copy(d1); + decltype(d2) d2_2_copy(d2); + + decltype(d3) d3_3_copy(d3); + decltype(d3) d3_4_copy(d4); + + CHECK_EQUAL(d1.size(), d1_1_copy.size()); + CHECK_EQUAL(d1.alignment(), d1_1_copy.alignment()); + + CHECK_EQUAL(d1.size(), d1_4_copy.size()); + CHECK_EQUAL(d1.alignment(), d1_4_copy.alignment()); + + CHECK_EQUAL(d2.size(), d2_1_copy.size()); + CHECK_EQUAL(d2.alignment(), d2_1_copy.alignment()); + + CHECK_EQUAL(d2.size(), d2_2_copy.size()); + CHECK_EQUAL(d2.alignment(), d2_2_copy.alignment()); + + CHECK_EQUAL(d3.size(), d3_3_copy.size()); + CHECK_EQUAL(d3.alignment(), d3_3_copy.alignment()); + + CHECK_EQUAL(d3.size(), d3_4_copy.size()); + CHECK_EQUAL(d3.alignment(), d3_4_copy.alignment()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_assignment) + { + DestructibleMovableObject object; + + auto d1 = etl::inplace_function(object); + etl::inplace_function d2; + + d2 = d1; + + d2(VALUE1, VALUE2); + + CHECK_EQUAL(0, object.call_count); // Ensure the original object is not modified. + CHECK_TRUE(DestructibleMovableObject::function_operator_called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_move_assignment) + { + DestructibleMovableObject object; + + auto d1 = etl::inplace_function(object); + etl::inplace_function d2; + + d2 = etl::move(d1); + + d2(VALUE1, VALUE2); + + CHECK_EQUAL(0, object.call_count); // Ensure the original object is not modified. + CHECK_TRUE(DestructibleMovableObject::function_operator_called); + } + + //************************************************************************* + TEST(test_vector_of_inplace_functions) + { + etl::vector, 5> vector_of_inplace_functions; + + vector_of_inplace_functions.push_back(etl::inplace_function::create()); + + CHECK_EQUAL(42, vector_of_inplace_functions.front()(21)); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_call_or_run_time_normal) + { + auto ipf = etl::inplace_function(normal); + + int result = ipf.call_or(alternative, VALUE1, VALUE2); + + CHECK_EQUAL(VALUE1 + VALUE2, result); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_call_or_run_time_alternative) + { + etl::inplace_function ipf; + + int result = ipf.call_or(alternative, VALUE1, VALUE2); + + CHECK_EQUAL(VALUE1 + VALUE2 + 1, result); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_call_or_compile_time_alternative) + { + etl::inplace_function ipf; + + int result = ipf.call_or(VALUE1, VALUE2); + + CHECK_EQUAL(VALUE1 + VALUE2 + 1, result); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_call_or_inplace_function_alternative) + { + etl::inplace_function ipf; + + auto alt = etl::inplace_function::create(); + + int result = ipf.call_or(alt, VALUE1, VALUE2); + + CHECK_EQUAL(VALUE1 + VALUE2 + 1, result); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_call_if_and_valid) + { + auto ipf = etl::inplace_function::create(); + + etl::optional result = ipf.call_if(VALUE1, VALUE2); + + CHECK(bool(result)); + CHECK_EQUAL(VALUE1 + VALUE2, result.value()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_call_if_and_not_valid) + { + etl::inplace_function ipf; + + etl::optional result = ipf.call_if(VALUE1, VALUE2); + + CHECK(!bool(result)); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_call_if_and_valid_returning_void) + { + auto ipf = etl::inplace_function::create(); + + bool was_called = ipf.call_if(VALUE1, VALUE2); + + CHECK(was_called); + CHECK(function_called == FunctionCalled::Normal_Returning_Void_Called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_call_if_and_not_valid_returning_void) + { + etl::inplace_function ipf; + + bool was_called = ipf.call_if(VALUE1, VALUE2); + + CHECK(!was_called); + CHECK(function_called == FunctionCalled::Not_Called); + CHECK(!parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_inplace_function_for) + { + FunctorSized<32> functor32; + + auto ipf = etl::inplace_function_for(functor32); + + int size = 0; + + function_called = FunctionCalled::Not_Called; + size = ipf(); + CHECK_EQUAL(functor32.size(), size); + CHECK_TRUE(function_called == FunctionCalled::Operator_Called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_inplace_function_for_any) + { + FunctorSized<8> functor8; + FunctorSized<16> functor16; + FunctorSized<32> functor32; + + auto ipf = etl::inplace_function_for_any, FunctorSized<16>, FunctorSized<32>>(); + int size = 0; + + function_called = FunctionCalled::Not_Called; + ipf.set(functor8); + size = ipf(); + CHECK_TRUE(function_called == FunctionCalled::Operator_Called); + CHECK_EQUAL(functor8.size(), size); + + function_called = FunctionCalled::Not_Called; + ipf.set(functor16); + size = ipf(); + CHECK_TRUE(function_called == FunctionCalled::Operator_Called); + CHECK_EQUAL(functor16.size(), size); + + function_called = FunctionCalled::Not_Called; + ipf.set(functor32); + size = ipf(); + CHECK_TRUE(function_called == FunctionCalled::Operator_Called); + CHECK_EQUAL(functor32.size(), size); + } + + //************************************************************************* + TEST(make_inplace_function_from_free_function_name) + { + // Create from function name (decays to function pointer) + auto ipf = etl::make_inplace_function(&free_int_return); + + CHECK_TRUE(bool(ipf)); + CHECK_EQUAL(7, ipf(3, 4)); + } + + //************************************************************************* + TEST(make_inplace_function_from_free_function_pointer_variable) + { + // Create from explicit function pointer variable + int (*fp)(int, int) = &free_int_return; + + auto ipf = etl::make_inplace_function(fp); + + CHECK_TRUE(ipf.is_valid()); + CHECK_EQUAL(13, ipf(6, 7)); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_assignment_to_an_ipf_of_function_over_a_lambda_and_back) + { + etl::inplace_function ipf; + + int value = 1; + auto lambda = [value](int i, int j) -> int { return value + i + j; }; + + int result = 0; + + ipf = lambda; + result = ipf(2, 3); + CHECK_EQUAL(1 + 2 + 3, result); + + ipf = normal; + result = ipf(3, 4); + CHECK_EQUAL(3 + 4, result); + + ipf = lambda; + result = ipf(5, 6); + CHECK_EQUAL(1 + 5 + 6, result); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_valid_valid) + { + Object object; + + // ipf1 -> normal, ipf2 -> member_int + etl::inplace_function ipf1(normal); + etl::inplace_function ipf2(&Object::member_int, object); + + int r1_before = ipf1(VALUE1, VALUE2); + int r2_before = ipf2(VALUE1, VALUE2); + CHECK_EQUAL(VALUE1 + VALUE2, r1_before); + CHECK_EQUAL(VALUE1 + VALUE2 + 1, r2_before); + + swap(ipf1, ipf2); // ADL swap uses member swap + + int r1_after = ipf1(VALUE1, VALUE2); + int r2_after = ipf2(VALUE1, VALUE2); + // After swap ipf1 should now hold 'member_int', ipf2 should hold 'normal' + CHECK_EQUAL(VALUE1 + VALUE2 + 1, r1_after); + CHECK_EQUAL(VALUE1 + VALUE2, r2_after); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_valid_empty) + { + etl::inplace_function ipf_valid(normal); + etl::inplace_function ipf_empty; // default constructed + + CHECK_TRUE(ipf_valid.is_valid()); + CHECK_FALSE(ipf_empty.is_valid()); + + swap(ipf_valid, ipf_empty); + + // ipf_valid should now be empty, ipf_empty should now have 'normal' + CHECK_FALSE(ipf_valid.is_valid()); + CHECK_TRUE(ipf_empty.is_valid()); + + CHECK_EQUAL(VALUE1 + VALUE2, ipf_empty(VALUE1, VALUE2)); + CHECK_THROW(ipf_valid(VALUE1, VALUE2), etl::inplace_function_uninitialized); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_empty_empty) + { + etl::inplace_function ipf_empty1; // default constructed + etl::inplace_function ipf_empty2; // default constructed + + CHECK_FALSE(ipf_empty1.is_valid()); + CHECK_FALSE(ipf_empty2.is_valid()); + + swap(ipf_empty1, ipf_empty2); + + // Both should still be empty + CHECK_FALSE(ipf_empty1.is_valid()); + CHECK_FALSE(ipf_empty2.is_valid()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_self_noop) + { + etl::inplace_function ipf(normal); + int before = ipf(VALUE1, VALUE2); + ipf.swap(ipf); // self-swap should be a no-op + int after = ipf(VALUE1, VALUE2); + CHECK_EQUAL(before, after); + CHECK_EQUAL(VALUE1 + VALUE2, after); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_runtime_functor_and_function) + { + struct PlusOne + { + int operator()(int a, int b) { return a + b + 1; } + } functor; + + etl::inplace_function ipf_functor(functor); + etl::inplace_function ipf_function(normal); + + CHECK_EQUAL(VALUE1 + VALUE2 + 1, ipf_functor(VALUE1, VALUE2)); + CHECK_EQUAL(VALUE1 + VALUE2, ipf_function(VALUE1, VALUE2)); + + ipf_functor.swap(ipf_function); + + CHECK_EQUAL(VALUE1 + VALUE2, ipf_functor(VALUE1, VALUE2)); // now holds 'normal' + CHECK_EQUAL(VALUE1 + VALUE2 + 1, ipf_function(VALUE1, VALUE2)); // now holds functor + } + +#if defined(ETL_NEGATIVE_TEST_INPLACE_FUNCTION_BAD_RETURN) + //************************************************************************* + // Triggers: return type not convertible (void -> int) + TEST(test_inplace_function_static_assert_bad_return) + { + auto bad = [](int) { /* returns void */ }; + // static_assert in lambda_stub/const_lambda_stub should trigger: + // "etl::inplace_function: bound lambda/functor is not compatible with the inplace_function signature" + auto ipf = etl::inplace_function(bad); + (void)ipf; + } +#endif + +#if defined(ETL_NEGATIVE_TEST_INPLACE_FUNCTION_RVALUE_PARAM_MISMATCH_NONCONST) + //************************************************************************* + // Triggers: parameter ref-qualification mismatch (expects rvalue, lambda takes lvalue ref) + TEST(test_inplace_function_static_assert_param_mismatch_nonconst) + { + auto bad = [](int&) { /* needs lvalue */ }; + // Not invocable with int&&, so is_compatible_callable is false, so static_assert triggers + auto ipf = etl::inplace_function(bad); + (void)ipf; + } +#endif + +#if defined(ETL_NEGATIVE_TEST_INPLACE_FUNCTION_RVALUE_PARAM_MISMATCH_CONST) + //************************************************************************* + // Same as above, but binds a const lambda to hit const_lambda_stub + TEST(test_inplace_function_static_assert_param_mismatch_const) + { + const auto bad = [](int&) { /* needs lvalue */ }; + // Not invocable with int&&, so is_compatible_callable is false, so static_assert triggers + auto ipf = etl::inplace_function(bad); + (void)ipf; + } +#endif + } +} + diff --git a/test/test_invoke.cpp b/test/test_invoke.cpp index 4e4bf10b..7d060e52 100644 --- a/test/test_invoke.cpp +++ b/test/test_invoke.cpp @@ -28,155 +28,457 @@ SOFTWARE. #include "unit_test_framework.h" +#include +#include + +#include "etl/type_traits.h" #include "etl/invoke.h" -#include namespace { - struct TestClass + //************************************************************************* + // Callable subjects + int free_add(int a, int b) { return a + b; } + int free_noexcept(int v) noexcept { return v; } + int free_throw(int v) { throw v; return v; } + + // C-style variadic function + int varfn(int first, ...) { return first; } + + //********************************************* + struct Base { - int member_obj = 42; - std::string member_str = "hello"; + int data; + Base(int d = 10) : data(d) {} - int get_int() - { - return member_obj; - } + int add(int v) { return data + v; } + int add_const(int v) const { return data + v + 1; } - int const_get_int() const - { - return member_obj + 10; - } - void set_int(int v) - { - member_obj = v; - } - static int static_func(int x) - { - return x * 2; - } + int ref_only(int v)& { return data + v + 2; } + int rref_only(int v)&& { return data + v + 3; } + + static int static_function(int v) { return v + 1; } + int noexcept_member(int v) noexcept { return data + v; } }; - int standalone_func(int a, int b) + //********************************************* + struct Derived : Base { - return a + b; - } + Derived(int d = 20) : Base(d) {} + }; + //********************************************* + struct VolatileBase + { + int x; + VolatileBase(int v = 0) : x(v) {} + int read() const volatile { return x; } + }; + + //********************************************* struct Functor { - int operator()(int x) const - { - return x * 5; - } + int x; + explicit Functor(int x_) : x(x_) {} + int operator()(int i) { return i + x; } }; - SUITE(test_invoke) + //********************************************* + struct ConstFunctor { - //************************************************************************* - TEST(test_type_traits_functions) + int x; + explicit ConstFunctor(int x_) : x(x_) {} + int operator()(int i) const { return i + x; } + }; + + //********************************************* + struct OverloadedFunctor + { + int operator()(int i)& { return i + 1; } + int operator()(int i)&& { return i + 2; } + }; + + //********************************************* + struct MoveOnlyFunctor + { + MoveOnlyFunctor() = default; + MoveOnlyFunctor(const MoveOnlyFunctor&) = delete; + MoveOnlyFunctor(MoveOnlyFunctor&&) = default; + int operator()(int i) { return i + 1; } + }; + + //********************************************* + struct NoThrowFunctor + { + int operator()(int i) const noexcept { return i + 2; } + }; + + //********************************************* + struct ThrowingFunctor + { + int operator()(int) { throw 42; } + }; + + //********************************************* + struct MemberObj + { + MemberObj(int v) : i(v) { - CHECK_TRUE(etl::is_function::value); - CHECK_TRUE(!etl::is_function::value); - CHECK_TRUE(!etl::is_function::value); - CHECK_TRUE(!etl::is_function::value); - CHECK_TRUE(!etl::is_function::value); } - //************************************************************************* - TEST(test_type_traits_member_pointers) - { - using MemObjPtr = int TestClass::*; - using MemFnPtr = int (TestClass::*)(); + int i; + }; - CHECK_TRUE(etl::is_member_pointer::value); - CHECK_TRUE(etl::is_member_pointer::value); - CHECK_TRUE(!etl::is_member_pointer::value); + //********************************************* + template + struct IntegralOnly + { + template ::value>::type> + int operator()(U u) { return static_cast(u) + 1; } - CHECK_TRUE(etl::is_member_object_pointer::value); - CHECK_TRUE(!etl::is_member_object_pointer::value); + template ::value>::type, typename = void> + int operator()(U) = delete; + }; - CHECK_TRUE(!etl::is_member_function_pointer::value); - CHECK_TRUE(etl::is_member_function_pointer::value); - } + //********************************************* + // Non-capturing lambda (convertible to function pointer) + static auto lambda_nc = [](int a, int b) { return a + b; }; - //************************************************************************* - TEST(test_invoke_callable) - { - CHECK_EQUAL(30, etl::invoke(standalone_func, 10, 20)); +#if ETL_USING_CPP14 + //********************************************* + // Generic lambda (C++14+) + static auto lambda_generic = [](auto x, auto y) { return x + y; }; +#endif - auto lambda = [](int x) - { return x * 3; }; - CHECK_EQUAL(15, etl::invoke(lambda, 5)); + //********************************************* + // Overload set (not directly a single callable type for traits) + int overload(int i) { return i + 10; } + long overload(long l) { return l + 20; } - Functor f; - CHECK_EQUAL(60, etl::invoke(f, 12)); + int takes_ptr(const int* p) { return *(p + 1); } - CHECK_EQUAL(8, etl::invoke(TestClass::static_func, 4)); - } + //********************************************* + struct Selective + { + template ::value, int> = 0> + int operator()(T) { return 1; } - //************************************************************************* - TEST(test_invoke_mem_func_ptr) - { - TestClass obj; - TestClass* ptr = &obj; - const TestClass const_obj; + template ::value, int> = 0> + char operator()(T) { return 2; } - CHECK_EQUAL(42, etl::invoke(&TestClass::get_int, obj)); - CHECK_EQUAL(42, etl::invoke(&TestClass::get_int, ptr)); - CHECK_EQUAL(52, etl::invoke(&TestClass::const_get_int, const_obj)); + template ::value, int> = 0> + int operator()(T) = delete; + }; +} - etl::invoke(&TestClass::set_int, obj, 99); - CHECK_EQUAL(99, obj.member_obj); +//************************************************************************* +// Unit tests for etl::is_invocable / etl::is_invocable_r +//************************************************************************* +SUITE(test_invoke) +{ + //************************************************************************* + TEST(test_invoke_result) + { + int capture_value = 5; + auto lambda_cap = [capture_value](int a) { return a + capture_value; }; - etl::invoke(&TestClass::set_int, ptr, 101); - CHECK_EQUAL(101, ptr->member_obj); - } + CHECK_TRUE((etl::is_same, int>::value)); + CHECK_TRUE((etl::is_same, int>::value)); + CHECK_TRUE((etl::is_same, int>::value)); + CHECK_TRUE((etl::is_same, int>::value)); - //************************************************************************* - TEST(test_invoke_mem_obj_ptr) - { - TestClass obj; - TestClass* ptr = &obj; + CHECK_TRUE((etl::is_same, int>::value)); + CHECK_TRUE((etl::is_same, int>::value)); + CHECK_TRUE((etl::is_same, int>::value)); + CHECK_TRUE((etl::is_same, int>::value)); + CHECK_TRUE((etl::is_same, int>::value)); + CHECK_TRUE((etl::is_same, int>::value)); - CHECK_EQUAL(42, etl::invoke(&TestClass::member_obj, obj)); - CHECK_EQUAL(42, etl::invoke(&TestClass::member_obj, ptr)); - CHECK_EQUAL("hello", etl::invoke(&TestClass::member_str, obj)); + CHECK_TRUE((etl::is_same, int>::value)); + CHECK_TRUE((etl::is_same, int>::value)); + CHECK_TRUE((etl::is_same, int>::value)); + CHECK_TRUE((etl::is_same, int>::value)); + CHECK_TRUE((etl::is_same, int>::value)); + CHECK_TRUE((etl::is_same, int>::value)); - etl::invoke(&TestClass::member_obj, obj) = 1000; - CHECK_EQUAL(1000, obj.member_obj); + CHECK_TRUE((etl::is_same, int>::value)); - etl::invoke(&TestClass::member_obj, ptr) = 2000; - CHECK_EQUAL(2000, ptr->member_obj); - } + CHECK_TRUE((etl::is_same, int>::value)); + CHECK_TRUE((etl::is_same, int>::value)); + CHECK_TRUE((etl::is_same, int>::value)); + CHECK_TRUE((etl::is_same, int>::value)); + CHECK_TRUE((etl::is_same, int>::value)); + CHECK_TRUE((etl::is_same, int>::value)); + CHECK_TRUE((etl::is_same, int>::value)); - //************************************************************************* - TEST(test_invoke_result_t) - { - using MemFnPtr = decltype(&TestClass::get_int); - using ConstMemFnPtr = decltype(&TestClass::const_get_int); - using MemObjPtr_int = decltype(&TestClass::member_obj); - using FnPtr = int (*)(int, int); - - auto val = etl::is_same, int>::value; - CHECK_TRUE(val); + CHECK_TRUE((etl::is_same, int&>::value)); - val = etl::is_same, int>::value; - CHECK_TRUE(val); - - val = etl::is_same, int>::value; - CHECK_TRUE(val); - - val = etl::is_same, int>::value; - CHECK_TRUE(val); - - val = etl::is_same, int&>::value; - CHECK_TRUE(val); - - val = etl::is_same, const int&>::value; - CHECK_TRUE(val); - - val = etl::is_same, int&>::value; - CHECK_TRUE(val); - } + CHECK_TRUE((etl::is_same, int>, int>::value)); + + CHECK_TRUE((etl::is_same, int>::value)); + CHECK_TRUE((etl::is_same, int>::value)); +#if ETL_USING_CPP14 + CHECK_TRUE((etl::is_same, int>::value)); + CHECK_TRUE((etl::is_same, long>::value)); +#endif + + int (*ov_int)(int) = &overload; + CHECK_TRUE((etl::is_same, int>::value)); + + long (*ov_long)(long) = &overload; + CHECK_TRUE((etl::is_same, long>::value)); + + CHECK_TRUE((etl::is_same, int>::value)); + CHECK_TRUE((etl::is_same, char>::value)); + + CHECK_TRUE((etl::is_same, int>::value)); } -} \ No newline at end of file + + //************************************************************************* + TEST(test_free_function) + { + CHECK_EQUAL(3, etl::invoke(free_add, 1, 2)); + } + + //************************************************************************* + TEST(test_free_function_pointer_variable) + { + int (*fp)(int, int) = &free_add; + + CHECK_EQUAL(3, etl::invoke(fp, 1, 2)); + } + + //************************************************************************* + TEST(test_function_pointer_const_qualification) + { + int (*const cfp)(int, int) = &free_add; + + CHECK_EQUAL(3, etl::invoke(cfp, 1, 2)); + } + + //************************************************************************* + TEST(test_free_function_noexcept) + { + CHECK_EQUAL(1, etl::invoke(free_noexcept, 1)); + } + + //************************************************************************* + TEST(test_free_function_throw) + { + CHECK_THROW(etl::invoke(free_throw, 1), int); + } + + //************************************************************************* + TEST(test_static_member_function) + { + CHECK_EQUAL(2, etl::invoke(&Base::static_function, 1)); + } + + //************************************************************************* + TEST(test_member_function) + { + Base base(10); + const Base const_base(20); + + Base* p_base = &base; + const Base* p_const_base = &const_base; + + CHECK_EQUAL(11, etl::invoke(&Base::add, base, 1)); + CHECK_EQUAL(12, etl::invoke(&Base::add, p_base, 2)); + CHECK_EQUAL(14, etl::invoke(&Base::add_const, base, 3)); + CHECK_EQUAL(15, etl::invoke(&Base::add_const, p_base, 4)); + CHECK_EQUAL(26, etl::invoke(&Base::add_const, const_base, 5)); + CHECK_EQUAL(27, etl::invoke(&Base::add_const, p_const_base, 6)); + } + + //************************************************************************* + TEST(test_member_function_noexcept) + { + Base base(10); + + CHECK_EQUAL(11, etl::invoke(&Base::noexcept_member, base, 1)); + } + + //************************************************************************* + TEST(test_member_functions_ref_qualification) + { + Base base(10); + Base& base_ref = base; + + Base&& base_rref = Base(10); + + CHECK_EQUAL(13, etl::invoke(&Base::ref_only, base_ref, 1)); + CHECK_EQUAL(15, etl::invoke(&Base::rref_only, std::move(base_rref), 2)); + } + + //************************************************************************* + TEST(test_inheritance_member_function) + { + Derived derived(10); + Derived* p_derived = &derived; + + CHECK_EQUAL(11, etl::invoke(&Base::add, derived, 1)); + CHECK_EQUAL(12, etl::invoke(&Base::add, p_derived, 2)); + } + + //************************************************************************* + TEST(test_member_function_volatile) + { + VolatileBase volatile_base(10); + + CHECK_EQUAL(10, etl::invoke(&VolatileBase::read, volatile_base)); + } + + //************************************************************************* + TEST(test_member_object_pointer) + { + MemberObj obj(10); + + CHECK_EQUAL(10, etl::invoke(&MemberObj::i, obj)); + CHECK_EQUAL(20, etl::invoke(&MemberObj::i, obj) = 20); + } + + //************************************************************************* + TEST(test_functor_non_const) + { + Functor functor(10); + + CHECK_EQUAL(12, etl::invoke(functor, 2)); + } + + //************************************************************************* + TEST(test_functor_const) + { + const ConstFunctor functor(10); + + CHECK_EQUAL(12, etl::invoke(functor, 2)); + } + + //************************************************************************* + TEST(test_move_only_functor) + { + MoveOnlyFunctor functor; + + CHECK_EQUAL(11, etl::invoke(etl::move(functor), 10)); + } + + //************************************************************************* + TEST(test_overloaded_functor_ref_qualifier) + { + OverloadedFunctor functor; + OverloadedFunctor& functor_ref = functor; + OverloadedFunctor&& functor_rref = OverloadedFunctor(); + + CHECK_EQUAL(11, etl::invoke(functor_ref, 10)); + CHECK_EQUAL(12, etl::invoke(etl::move(functor_rref), 10)); + } + + //************************************************************************* + TEST(test_nothrow_and_throwing_functors) + { + NoThrowFunctor nothrow_functor; + ThrowingFunctor throwing_functor; + + CHECK_EQUAL(12, etl::invoke(nothrow_functor, 10)); + CHECK_THROW(etl::invoke(throwing_functor, 10), int); + } + + //************************************************************************* + TEST(test_lambda_non_capturing) + { + CHECK_EQUAL(3, etl::invoke(lambda_nc, 1, 2)); + } + + //************************************************************************* + TEST(test_lambda_capturing) + { + int capture_value = 5; + auto lambda_cap = [capture_value](int a) { return a + capture_value; }; + + CHECK_EQUAL(6, etl::invoke(lambda_cap, 1)); + } + +#if ETL_USING_CPP14 + //************************************************************************* + TEST(test_lambda_generic) + { + CHECK_EQUAL(3, etl::invoke(lambda_generic, 1, 2)); + CHECK_EQUAL(3L, etl::invoke(lambda_generic, 1L, 2L)); + CHECK_CLOSE(3.5, etl::invoke(lambda_generic, 1.5, 2.0), 0.001); + } +#endif + + //************************************************************************* + TEST(test_template_functor_integral_only) + { + CHECK_EQUAL(2, etl::invoke(IntegralOnly(), 1)); + } + + //************************************************************************* + TEST(test_additional_user_defined_conversion) + { + struct Converter { operator int() const { return 11; } }; + + CHECK_EQUAL(22, etl::invoke(free_add, Converter(), 11)); // Converter -> int + } + + //************************************************************************* + TEST(test_overload_set) + { + // Selecting explicit overload + int (*ov_i)(int) = &overload; + long (*ov_l)(long) = &overload; + + CHECK_EQUAL(11, etl::invoke(ov_i, 1)); + CHECK_EQUAL(21L, etl::invoke(ov_l, 1L)); + } + + //************************************************************************* + TEST(test_deleted_overload) + { + struct DeletedOverload + { + int operator()(double d) { return static_cast(2 * d); } + int operator()(int) = delete; + }; + + CHECK_CLOSE(6, etl::invoke(DeletedOverload(), 3.14), 0.001); + } + + //************************************************************************* + TEST(test_variadic_free_function) + { + CHECK_EQUAL(1, etl::invoke(varfn, 1)); + CHECK_EQUAL(2, etl::invoke(varfn, 2, 3.14, "test")); + } + + //************************************************************************* + TEST(test_array_decay_argument) + { + int arr[] = {1, 2, 3}; + + CHECK_EQUAL(2, etl::invoke(takes_ptr, arr)); + } + + //************************************************************************* + TEST(test_template_functor_multiple_enable_if) + { + CHECK_EQUAL(1, etl::invoke(Selective(), int(0))); + CHECK_EQUAL(2, etl::invoke(Selective(), char(0))); + } + + //************************************************************************* + TEST(test_rvalue_ref_member_on_temporary) + { + struct RR + { + int f() && { return 1; } + int g() & { return 2; } + }; + + RR rr; + + CHECK_EQUAL(1, etl::invoke(&RR::f, etl::move(rr))); + CHECK_EQUAL(2, etl::invoke(&RR::g, rr)); + } +} diff --git a/test/test_is_invocable.cpp b/test/test_is_invocable.cpp new file mode 100644 index 00000000..13036c8a --- /dev/null +++ b/test/test_is_invocable.cpp @@ -0,0 +1,1011 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "unit_test_framework.h" + +#include +#include + +#include "etl/type_traits.h" +#include "etl/invoke.h" +#include "etl/type_list.h" + +namespace +{ + //************************************************************************* + // Callable subjects + int free_add(int a, int b) { return a + b; } + short free_short(int a) { return static_cast(a); } + int free_noexcept(int v) noexcept { return v; } + int free_throw(int v) { throw v; return v; } + + // C-style variadic function + int varfn(int first, ...) + { + return first; + } + + //********************************************* + struct Base + { + int data; + Base(int d = 10) : data(d) {} + + int add(int v) { return data + v; } + int add_const(int v) const { return data + v + 1; } + + int ref_only(int v)& { return data + v + 2; } + int rref_only(int v)&& { return data + v + 3; } + + static int static_function(int v) { return v * 2; } + int member_noexcept(int v) noexcept { return data + v; } + int member_throw(int v) { throw v; return data + v; } + }; + + //********************************************* + struct NotBase + { + int data; + NotBase(int d = 0) : data(d) {} + }; + + //********************************************* + struct Derived : Base + { + Derived(int d = 20) : Base(d) {} + }; + + //********************************************* + struct NotDerived : NotBase + { + NotDerived(int d = 20) : NotBase(d) {} + }; + + //********************************************* + struct VolatileBase + { + int x; + VolatileBase(int v = 0) : x(v) {} + int read() const volatile { return x; } + }; + + //********************************************* + struct Functor + { + int factor; + explicit Functor(int f) : factor(f) {} + int operator()(int x) { return x * factor; } + }; + + //********************************************* + struct ConstFunctor + { + int bias; + explicit ConstFunctor(int b) : bias(b) {} + int operator()(int x) const { return x + bias; } + }; + + //********************************************* + struct OverloadedFunctor + { + int operator()(int)& { return 1; } + int operator()(int)&& { return 2; } + }; + + //********************************************* + struct MoveOnlyFunctor + { + MoveOnlyFunctor() = default; + MoveOnlyFunctor(const MoveOnlyFunctor&) = delete; + MoveOnlyFunctor(MoveOnlyFunctor&&) = default; + int operator()(int x) { return x + 100; } + }; + + //********************************************* + struct NothrowFunctor + { + int operator()() const noexcept { return 7; } + }; + + //********************************************* + struct ThrowingFunctor + { + int operator()() { throw 42; } + }; + + //********************************************* + struct MemberObj + { + int i; + }; + + //********************************************* + template + struct IntegralOnly + { + template ::value>::type> + int operator()(U u) { return static_cast(u) + 10; } + + template ::value>::type, typename = void> + int operator()(U) = delete; + }; + + //********************************************* + // Non-capturing lambda (convertible to function pointer) + static auto lambda_nc = [](int a, int b) { return a + b; }; + +#if ETL_USING_CPP14 + //********************************************* + // Generic lambda (C++14+) + static auto lambda_generic = [](auto x, auto y) { return x + y; }; +#endif + + //********************************************* + // Overload set (not directly a single callable type for traits) + int overload(int) { return 0; } + long overload(long) { return 0; } + + int takes_ptr(const int* p) { return *p; } + + //********************************************* + struct Selective + { + template ::value, int> = 0> + int operator()(T) { return 1; } + + template ::value, int> = 0> + char operator()(T) { return 1; } + + template ::value, int> = 0> + int operator()(T) = delete; + }; +} + +//************************************************************************* +// Unit tests for etl::is_invocable / etl::is_invocable_r +//************************************************************************* +SUITE(test_is_invocable) +{ + //************************************************************************* + TEST(use_free_functions) + { + // Ensure that clang does not discard them as unused. + CHECK_TRUE(free_add(1, 2) != 0); + CHECK_TRUE(free_short(1) != 0); + CHECK_TRUE(free_noexcept(1) != 0); + CHECK_THROW(free_throw(1), int); + CHECK_TRUE(lambda_nc(1, 2) != 0); +#if ETL_USING_CPP14 + CHECK_TRUE(lambda_generic(1, 2) != 0); +#endif + CHECK_TRUE(varfn(1, 2, 3) != 0); + + int value = 10; + CHECK_EQUAL(10, takes_ptr(&value)); + } + + //************************************************************************* + TEST(test_free_function) + { + CHECK_TRUE((etl::is_invocable::value)); + CHECK_FALSE((etl::is_invocable::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable::value)); // Non-convertible argument + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_FALSE((etl::is_invocable>::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable>::value)); // Non-convertible argument + } + + //************************************************************************* + TEST(test_free_function_return) + { + CHECK_TRUE((etl::is_invocable_r::value)); + CHECK_FALSE((etl::is_invocable_r::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable_r::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable_r::value)); // Non-convertible argument + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable_r>::value)); + CHECK_FALSE((etl::is_invocable_r>::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable_r>::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable_r>::value)); // Non-convertible argument + } + + //************************************************************************* + TEST(test_free_function_pointer_variable) + { + int (*fp)(int, int) = &free_add; + + CHECK_TRUE((etl::is_invocable::value)); + CHECK_FALSE((etl::is_invocable::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable::value)); // Non-convertible argument + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_FALSE((etl::is_invocable>::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable>::value)); // Non-convertible argument + } + + //************************************************************************* + TEST(test_free_function_pointer_variable_return) + { + int (*fp)(int, int) = &free_add; + + CHECK_TRUE((etl::is_invocable_r::value)); + CHECK_FALSE((etl::is_invocable_r::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable_r::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable_r::value)); // Non-convertible argument + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable_r>::value)); + CHECK_FALSE((etl::is_invocable_r>::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable_r>::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable_r>::value)); // Non-convertible argument + } + + //************************************************************************* + TEST(test_function_pointer_const_qualification) + { + int (*const cfp)(int, int) = &free_add; + + CHECK_TRUE((etl::is_invocable::value)); + CHECK_TRUE((etl::is_invocable_r::value)); + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_TRUE((etl::is_invocable_r>::value)); + } + + //************************************************************************* + TEST(test_free_function_noexcept) + { + CHECK_TRUE((etl::is_invocable::value)); + CHECK_FALSE((etl::is_invocable::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable::value)); // Non-convertible argument + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_FALSE((etl::is_invocable>::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable>::value)); // Non-convertible argument + } + + //************************************************************************* + TEST(test_free_function_noexcept_return) + { + CHECK_TRUE((etl::is_invocable_r::value)); + CHECK_FALSE((etl::is_invocable_r::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable_r::value)); // Non-convertible argument + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable_r>::value)); + CHECK_FALSE((etl::is_invocable_r>::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable>::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable_r>::value)); // Non-convertible argument + } + + //************************************************************************* + TEST(test_free_function_throw) + { + CHECK_TRUE((etl::is_invocable::value)); + CHECK_FALSE((etl::is_invocable::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable::value)); // Non-convertible argument + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_FALSE((etl::is_invocable>::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable>::value)); // Non-convertible argument + } + + //************************************************************************* + TEST(test_free_function_throw_return) + { + CHECK_TRUE((etl::is_invocable_r::value)); + CHECK_FALSE((etl::is_invocable_r::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable_r::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable_r::value)); // Non-convertible argument + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable_r>::value)); + CHECK_FALSE((etl::is_invocable_r>::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable_r>::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable_r>::value)); // Non-convertible argument + } + +#if ETL_USING_CPP17 + //************************************************************************* + TEST(test_no_throw_invocable) + { + CHECK_TRUE((etl::is_nothrow_invocable::value)); + CHECK_FALSE((etl::is_nothrow_invocable::value)); // Arity mismatch + CHECK_FALSE((etl::is_nothrow_invocable::value)); // Non-convertible argument + + CHECK_FALSE((etl::is_nothrow_invocable::value)); + CHECK_FALSE((etl::is_nothrow_invocable::value)); // Arity mismatch + CHECK_FALSE((etl::is_nothrow_invocable::value)); // Non-convertible argument + + CHECK_TRUE((etl::is_nothrow_invocable::value)); + CHECK_FALSE((etl::is_nothrow_invocable::value)); + + // Use etl::type_list + CHECK_TRUE((etl::is_nothrow_invocable>::value)); + CHECK_FALSE((etl::is_nothrow_invocable>::value)); // Arity mismatch + CHECK_FALSE((etl::is_nothrow_invocable>::value)); // Non-convertible argument + + CHECK_FALSE((etl::is_nothrow_invocable>::value)); + CHECK_FALSE((etl::is_nothrow_invocable>::value)); // Arity mismatch + CHECK_FALSE((etl::is_nothrow_invocable>::value)); // Non-convertible argument + + CHECK_TRUE((etl::is_nothrow_invocable>::value)); + CHECK_FALSE((etl::is_nothrow_invocable>::value)); + } + + //************************************************************************* + TEST(test_no_throw_invocable_return) + { + CHECK_TRUE((etl::is_nothrow_invocable_r::value)); + CHECK_FALSE((etl::is_nothrow_invocable_r::value)); // Return mismatch + CHECK_FALSE((etl::is_nothrow_invocable_r::value)); // Arity mismatch + CHECK_FALSE((etl::is_nothrow_invocable_r::value)); // Non-convertible argument + + CHECK_FALSE((etl::is_nothrow_invocable_r::value)); + CHECK_FALSE((etl::is_nothrow_invocable_r::value)); // Return mismatch + CHECK_FALSE((etl::is_nothrow_invocable_r::value)); // Arity mismatch + CHECK_FALSE((etl::is_nothrow_invocable_r::value)); // Non-convertible argument + + CHECK_TRUE((etl::is_nothrow_invocable_r::value)); + CHECK_FALSE((etl::is_nothrow_invocable_r::value)); + + // Use etl::type_list + CHECK_TRUE((etl::is_nothrow_invocable_r>::value)); + CHECK_FALSE((etl::is_nothrow_invocable_r>::value)); // Return mismatch + CHECK_FALSE((etl::is_nothrow_invocable_r>::value)); // Arity mismatch + CHECK_FALSE((etl::is_nothrow_invocable_r>::value)); // Non-convertible argument + + CHECK_FALSE((etl::is_nothrow_invocable_r>::value)); + CHECK_FALSE((etl::is_nothrow_invocable_r>::value)); // Return mismatch + CHECK_FALSE((etl::is_nothrow_invocable_r>::value)); // Arity mismatch + CHECK_FALSE((etl::is_nothrow_invocable_r>::value)); // Non-convertible argument + + CHECK_TRUE((etl::is_nothrow_invocable_r>::value)); + CHECK_FALSE((etl::is_nothrow_invocable_r>::value)); + } +#endif + + //************************************************************************* + TEST(test_static_member_function) + { + CHECK_TRUE((etl::is_invocable::value)); + CHECK_FALSE((etl::is_invocable::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable::value)); // Non-convertible argument + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_FALSE((etl::is_invocable>::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable>::value)); // Non-convertible argument + } + + //************************************************************************* + TEST(test_static_member_function_return) + { + CHECK_TRUE((etl::is_invocable_r::value)); + CHECK_FALSE((etl::is_invocable_r::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable_r::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable_r::value)); // Non-convertible argument + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable_r>::value)); + CHECK_FALSE((etl::is_invocable_r>::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable_r>::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable_r>::value)); // Non-convertible argument + } + + //************************************************************************* + TEST(test_member_function) + { + CHECK_TRUE((etl::is_invocable::value)); + CHECK_FALSE((etl::is_invocable::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable::value)); // Wrong object type + CHECK_FALSE((etl::is_invocable::value)); // Non-convertible argument + + CHECK_TRUE((etl::is_invocable::value)); + CHECK_FALSE((etl::is_invocable::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable::value)); // Wrong object type + CHECK_FALSE((etl::is_invocable::value)); // Non-convertible argument + + CHECK_TRUE((etl::is_invocable::value)); + CHECK_FALSE((etl::is_invocable::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable::value)); // Wrong object type + CHECK_FALSE((etl::is_invocable::value)); // Non-convertible argument + CHECK_FALSE((etl::is_invocable::value)); // Not const function + + CHECK_TRUE((etl::is_invocable::value)); + CHECK_FALSE((etl::is_invocable::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable::value)); // Wrong object type + CHECK_FALSE((etl::is_invocable::value)); // Non-convertible argument + CHECK_FALSE((etl::is_invocable::value)); // Not const function + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_FALSE((etl::is_invocable>::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable>::value)); // Wrong object type + CHECK_FALSE((etl::is_invocable>::value)); // Non-convertible argument + + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_FALSE((etl::is_invocable>::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable>::value)); // Wrong object type + CHECK_FALSE((etl::is_invocable>::value)); // Non-convertible argument + + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_FALSE((etl::is_invocable>::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable>::value)); // Wrong object type + CHECK_FALSE((etl::is_invocable>::value)); // Non-convertible argument + CHECK_FALSE((etl::is_invocable>::value)); // Not const function + + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_FALSE((etl::is_invocable>::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable>::value)); // Wrong object type + CHECK_FALSE((etl::is_invocable>::value)); // Non-convertible argument + CHECK_FALSE((etl::is_invocable>::value)); // Not const function + } + + //************************************************************************* + TEST(test_member_function_return) + { + CHECK_TRUE((etl::is_invocable_r::value)); + CHECK_FALSE((etl::is_invocable_r::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable_r::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable_r::value)); // Wrong object type + CHECK_FALSE((etl::is_invocable_r::value)); // Non-convertible argument + + CHECK_TRUE((etl::is_invocable_r::value)); + CHECK_FALSE((etl::is_invocable_r::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable_r::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable_r::value)); // Wrong object type + CHECK_FALSE((etl::is_invocable_r::value)); // Non-convertible argument + + CHECK_TRUE((etl::is_invocable_r::value)); + CHECK_FALSE((etl::is_invocable_r::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable_r::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable_r::value)); // Wrong object type + CHECK_FALSE((etl::is_invocable_r::value)); // Non-convertible argument + CHECK_FALSE((etl::is_invocable_r::value)); // Not const function + + CHECK_TRUE((etl::is_invocable_r::value)); + CHECK_FALSE((etl::is_invocable_r::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable_r::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable_r::value)); // Wrong object type + CHECK_FALSE((etl::is_invocable_r::value)); // Non-convertible argument + CHECK_FALSE((etl::is_invocable_r::value)); // Not const function + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable_r>::value)); + CHECK_FALSE((etl::is_invocable_r>::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable_r>::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable_r>::value)); // Wrong object type + CHECK_FALSE((etl::is_invocable_r>::value)); // Non-convertible argument + + CHECK_TRUE((etl::is_invocable_r>::value)); + CHECK_FALSE((etl::is_invocable_r>::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable_r>::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable_r>::value)); // Wrong object type + CHECK_FALSE((etl::is_invocable_r>::value)); // Non-convertible argument + + CHECK_TRUE((etl::is_invocable_r>::value)); + CHECK_FALSE((etl::is_invocable_r>::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable_r>::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable_r>::value)); // Wrong object type + CHECK_FALSE((etl::is_invocable_r>::value)); // Non-convertible argument + CHECK_FALSE((etl::is_invocable_r>::value)); // Not const function + + CHECK_TRUE((etl::is_invocable_r>::value)); + CHECK_FALSE((etl::is_invocable_r>::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable_r>::value)); // Arity mismatch + CHECK_FALSE((etl::is_invocable_r>::value)); // Wrong object type + CHECK_FALSE((etl::is_invocable_r>::value)); // Non-convertible argument + CHECK_FALSE((etl::is_invocable_r>::value)); // Not const function + } + + //************************************************************************* + TEST(test_member_function_noexcept) + { + CHECK_TRUE((etl::is_invocable::value)); + CHECK_TRUE((etl::is_invocable_r::value)); + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_TRUE((etl::is_invocable_r>::value)); + } + + //************************************************************************* + TEST(test_member_functions_ref_qualification) + { + CHECK_TRUE((etl::is_invocable::value)); + CHECK_FALSE((etl::is_invocable::value)); // rvalue object disallowed + + CHECK_TRUE((etl::is_invocable::value)); + CHECK_FALSE((etl::is_invocable::value)); // lvalue object disallowed + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_FALSE((etl::is_invocable>::value)); // rvalue object disallowed + + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_FALSE((etl::is_invocable>::value)); // lvalue object disallowed + } + + //************************************************************************* + TEST(test_inheritance_member_function) + { + CHECK_TRUE((etl::is_invocable::value)); + CHECK_TRUE((etl::is_invocable::value)); + + CHECK_FALSE((etl::is_invocable::value)); + CHECK_FALSE((etl::is_invocable::value)); + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_TRUE((etl::is_invocable>::value)); + + CHECK_FALSE((etl::is_invocable>::value)); + CHECK_FALSE((etl::is_invocable>::value)); + } + + //************************************************************************* + TEST(test_member_function_volatile) + { + CHECK_TRUE((etl::is_invocable::value)); + CHECK_FALSE((etl::is_invocable::value)); + + CHECK_TRUE((etl::is_invocable_r::value)); + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_FALSE((etl::is_invocable>::value)); + CHECK_TRUE((etl::is_invocable_r>::value)); + } + + //************************************************************************* + TEST(test_member_object_pointer) + { + int MemberObj::* p_int = &MemberObj::i; + + CHECK_TRUE((etl::is_invocable::value)); + CHECK_TRUE((etl::is_invocable::value)); + CHECK_FALSE((etl::is_invocable::value)); // Needs object + CHECK_FALSE((etl::is_invocable::value)); // Wrong object type + + // Non-const object: result is int&, should satisfy int& + CHECK_TRUE((etl::is_invocable_r::value)); + + // Const object: result is const int&, cannot bind to int& + CHECK_FALSE((etl::is_invocable_r::value)); + + // Const object can bind to const int& + CHECK_TRUE((etl::is_invocable_r::value)); + } + + //************************************************************************* + TEST(test_functor_non_const) + { + CHECK_TRUE((etl::is_invocable::value)); + CHECK_FALSE((etl::is_invocable::value)); // Arity mismatch + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_FALSE((etl::is_invocable>::value)); // Arity mismatch + } + + //************************************************************************* + TEST(test_functor_non_const_return) + { + CHECK_TRUE((etl::is_invocable_r::value)); + CHECK_TRUE((etl::is_invocable_r::value)); + CHECK_FALSE((etl::is_invocable_r::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable_r::value)); // Arity mismatch + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable_r>::value)); + CHECK_TRUE((etl::is_invocable_r>::value)); + CHECK_FALSE((etl::is_invocable_r>::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable_r>::value)); // Arity mismatch + } + + //************************************************************************* + TEST(test_functor_const) + { + CHECK_TRUE((etl::is_invocable::value)); + CHECK_FALSE((etl::is_invocable::value)); // Arity mismatch + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_FALSE((etl::is_invocable>::value)); // Arity mismatch + } + + //************************************************************************* + TEST(test_functor_const_return) + { + CHECK_TRUE((etl::is_invocable_r::value)); + CHECK_TRUE((etl::is_invocable_r::value)); + CHECK_FALSE((etl::is_invocable_r::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable_r::value)); // Arity mismatch + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable_r>::value)); + CHECK_TRUE((etl::is_invocable_r>::value)); + CHECK_FALSE((etl::is_invocable_r>::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable_r>::value)); // Arity mismatch + } + + //************************************************************************* + TEST(test_move_only_functor) + { + CHECK_TRUE((etl::is_invocable::value)); + CHECK_FALSE((etl::is_invocable::value)); // Arity mismatch + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_FALSE((etl::is_invocable>::value)); // Arity mismatch + } + + //************************************************************************* + TEST(test_move_only_functor_return) + { + CHECK_TRUE((etl::is_invocable_r::value)); + CHECK_TRUE((etl::is_invocable_r::value)); + CHECK_FALSE((etl::is_invocable_r::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable_r::value)); // Arity mismatch + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable_r>::value)); + CHECK_TRUE((etl::is_invocable_r>::value)); + CHECK_FALSE((etl::is_invocable_r>::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable_r>::value)); // Arity mismatch + } + + //************************************************************************* + TEST(test_overloaded_functor_ref_qualifier) + { + // lvalue should pick operator()& + CHECK_TRUE((etl::is_invocable::value)); + CHECK_FALSE((etl::is_invocable::value)); + + // rvalue temporary should pick operator()&& + CHECK_TRUE((etl::is_invocable::value)); + + // Use etl::type_list + // lvalue should pick operator()& + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_FALSE((etl::is_invocable>::value)); + + // rvalue temporary should pick operator()&& + CHECK_TRUE((etl::is_invocable>::value)); + } + + //************************************************************************* + TEST(test_nothrow_and_throwing_functors) + { + CHECK_TRUE((etl::is_invocable::value)); + CHECK_TRUE((etl::is_invocable_r::value)); + + CHECK_TRUE((etl::is_invocable::value)); + CHECK_TRUE((etl::is_invocable_r::value)); + } + + //************************************************************************* + TEST(test_lambda_non_capturing) + { + CHECK_TRUE((etl::is_invocable::value)); + CHECK_FALSE((etl::is_invocable::value)); // Arity mismatch + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_FALSE((etl::is_invocable>::value)); // Arity mismatch + } + + //************************************************************************* + TEST(test_lambda_non_capturing_return) + { + CHECK_TRUE((etl::is_invocable_r::value)); + CHECK_TRUE((etl::is_invocable_r::value)); + CHECK_FALSE((etl::is_invocable_r::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable_r::value)); // Arity mismatch + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable_r>::value)); + CHECK_TRUE((etl::is_invocable_r>::value)); + CHECK_FALSE((etl::is_invocable_r>::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable_r>::value)); // Arity mismatch + } + + //************************************************************************* + TEST(test_lambda_capturing) + { + int capture_value = 5; + auto lambda_cap = [capture_value](int a) { return a + capture_value; }; + + CHECK_TRUE((etl::is_invocable::value)); + CHECK_FALSE((etl::is_invocable::value)); // Arity mismatch + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_FALSE((etl::is_invocable, int>::value)); // Arity mismatch + } + + //************************************************************************* + TEST(test_lambda_capturing_return) + { + int capture_value = 5; + auto lambda_cap = [capture_value](int a) { return a + capture_value; }; + + CHECK_TRUE((etl::is_invocable_r::value)); + CHECK_TRUE((etl::is_invocable_r::value)); + CHECK_FALSE((etl::is_invocable_r::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable_r::value)); // Arity mismatch + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable_r>::value)); + CHECK_TRUE((etl::is_invocable_r>::value)); + CHECK_FALSE((etl::is_invocable_r>::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable_r>::value)); // Arity mismatch + } + +#if ETL_USING_CPP14 + //************************************************************************* + TEST(test_lambda_generic) + { + CHECK_TRUE((etl::is_invocable::value)); + CHECK_TRUE((etl::is_invocable::value)); + CHECK_FALSE((etl::is_invocable::value)); // Arity mismatch + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_FALSE((etl::is_invocable>::value)); // Arity mismatch + } + + //************************************************************************* + TEST(test_lambda_generic_return) + { + CHECK_TRUE((etl::is_invocable_r::value)); + CHECK_TRUE((etl::is_invocable_r::value)); + + CHECK_FALSE((etl::is_invocable_r::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable_r::value)); // Arity mismatch + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable_r>::value)); + CHECK_TRUE((etl::is_invocable_r>::value)); + CHECK_FALSE((etl::is_invocable_r>::value)); // Return mismatch + CHECK_FALSE((etl::is_invocable_r>::value)); // Arity mismatch + } +#endif + + //************************************************************************* + TEST(test_template_functor_integral_only) + { + CHECK_TRUE((etl::is_invocable, int>::value)); + CHECK_TRUE((etl::is_invocable_r, int>::value)); + + CHECK_FALSE((etl::is_invocable, double>::value)); + CHECK_FALSE((etl::is_invocable, float>::value)); + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable, etl::type_list>::value)); + CHECK_TRUE((etl::is_invocable_r, etl::type_list>::value)); + + CHECK_FALSE((etl::is_invocable, etl::type_list>::value)); + CHECK_FALSE((etl::is_invocable_r, etl::type_list>::value)); + } + + //************************************************************************* + TEST(test_return_type_conversion) + { + CHECK_TRUE((etl::is_invocable_r::value)); // short -> int + CHECK_TRUE((etl::is_invocable_r::value)); // exact + CHECK_TRUE((etl::is_invocable_r::value)); // short -> void + CHECK_FALSE((etl::is_invocable_r::value)); // mismatch + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable_r>::value)); // short -> int + CHECK_TRUE((etl::is_invocable_r>::value)); // exact + CHECK_TRUE((etl::is_invocable_r>::value)); // short -> void + CHECK_FALSE((etl::is_invocable_r>::value)); // mismatch + } + + //************************************************************************* + TEST(test_additional_user_defined_conversion) + { + struct Converter { operator int() const { return 11; } }; + + CHECK_TRUE((etl::is_invocable::value)); // Converter -> int + CHECK_TRUE((etl::is_invocable_r::value)); + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable>::value)); // Converter -> int + CHECK_TRUE((etl::is_invocable_r>::value)); + } + + //************************************************************************* + TEST(test_overload_set) + { + // Selecting explicit overload + int (*ov_i)(int) = &overload; + long (*ov_l)(long) = &overload; + + CHECK_TRUE((etl::is_invocable::value)); + CHECK_TRUE((etl::is_invocable::value)); + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_TRUE((etl::is_invocable>::value)); + } + + //************************************************************************* + TEST(test_overload_set_return) + { + int (*ov_i)(int) = &overload; + long (*ov_l)(long) = &overload; + + CHECK_TRUE((etl::is_invocable_r::value)); + CHECK_TRUE((etl::is_invocable_r::value)); + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable_r>::value)); + CHECK_TRUE((etl::is_invocable_r>::value)); + } + + //************************************************************************* + TEST(test_deleted_overload) + { + struct DeletedOverload + { + int operator()(double) { return 0; } + int operator()(int) = delete; + }; + + CHECK_TRUE((etl::is_invocable::value)); + CHECK_FALSE((etl::is_invocable::value)); // deleted + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_FALSE((etl::is_invocable>::value)); // deleted + } + + //************************************************************************* + TEST(test_variadic_free_function) + { + CHECK_TRUE((etl::is_invocable::value)); + CHECK_TRUE((etl::is_invocable::value)); + CHECK_FALSE((etl::is_invocable::value)); // Needs at least one argument + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_TRUE((etl::is_invocable>::value)); + } + + //************************************************************************* + TEST(test_array_decay_argument) + { + CHECK_TRUE((etl::is_invocable::value)); + CHECK_TRUE((etl::is_invocable::value)); // array decays + CHECK_FALSE((etl::is_invocable::value)); + CHECK_FALSE((etl::is_invocable::value)); + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_TRUE((etl::is_invocable>::value)); // array decays + CHECK_FALSE((etl::is_invocable>::value)); + } + + //************************************************************************* + TEST(test_template_functor_multiple_enable_if) + { + CHECK_TRUE((etl::is_invocable::value)); + CHECK_TRUE((etl::is_invocable::value)); + CHECK_FALSE((etl::is_invocable::value)); + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_FALSE((etl::is_invocable>::value)); + } + + //************************************************************************* + TEST(test_rvalue_ref_member_on_temporary) + { + struct RR + { + int f() && { return 1; } + int g() & { return 2; } + }; + + CHECK_TRUE((etl::is_invocable::value)); // rvalue-qualified on temporary + CHECK_FALSE((etl::is_invocable::value)); // cannot call on lvalue + CHECK_TRUE((etl::is_invocable::value)); // lvalue-qualified + CHECK_FALSE((etl::is_invocable::value)); // cannot call on rvalue + } + + //************************************************************************* + TEST(test_void_return_exactness) + { + struct VoidFn + { + void operator()(int) {} + }; + + CHECK_TRUE((etl::is_invocable::value)); + CHECK_TRUE((etl::is_invocable_r::value)); + CHECK_FALSE((etl::is_invocable_r::value)); // void not convertible to int + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable>::value)); + CHECK_TRUE((etl::is_invocable_r>::value)); + CHECK_FALSE((etl::is_invocable_r>::value)); // void not convertible to int + } + + //************************************************************************* + TEST(test_conversion_chain_failure) + { + enum class E : unsigned + { + A = 0 + }; + + struct NeedsE + { + int operator()(E) + { + return 0; + } + }; + + // int not implicitly convertible to scoped enum + CHECK_FALSE((etl::is_invocable::value)); + + // Underlying type convertible when cast explicit; still trait should be false without cast + CHECK_FALSE((etl::is_invocable_r::value)); + + // Use etl::type_list + CHECK_FALSE((etl::is_invocable>::value)); + CHECK_FALSE((etl::is_invocable_r>::value)); + } + + //************************************************************************* + TEST(test_invoke_with_null_member_pointer_type_only) + { + int (Base::*pmf)(int) = nullptr; + + // Trait should report invocable even though runtime call would be UB + CHECK_TRUE((etl::is_invocable::value)); + + // Use etl::type_list + CHECK_TRUE((etl::is_invocable>::value)); + } +} diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index a79e639b..6396b761 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -3544,6 +3544,7 @@ + @@ -10347,8 +10348,10 @@ + + diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index 4f1f3320..6deed683 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -1534,7 +1534,10 @@ UnitTest++\Header Files - UnitTest++\Header Files + ETL\Utilities + + + ETL\Utilities @@ -3761,6 +3764,12 @@ Tests\Callbacks & Delegates + + Tests\Callbacks & Delegates + + + Tests\Callbacks & Delegates + From 3206ac9feb44a22e0fb27bbbec5eecf156ee6231 Mon Sep 17 00:00:00 2001 From: mike919192 <91038685+mike919192@users.noreply.github.com> Date: Sun, 11 Jan 2026 12:05:21 -0500 Subject: [PATCH 072/298] ivector swap (#1256) * Etl vector swap implementation * Implement swap function overload * Fix nitpicks * Add size check * Remove unnessecary etl swap overloads * Use swap_range and move range --------- Co-authored-by: John Wellbelove --- include/etl/private/ivectorpointer.h | 50 +++++ include/etl/vector.h | 36 +++ test/test_vector.cpp | 114 ++++++++++ test/test_vector_external_buffer.cpp | 114 ++++++++++ test/test_vector_non_trivial.cpp | 81 +++++++ test/test_vector_pointer.cpp | 222 ++++++++++++++++++ test/test_vector_pointer_external_buffer.cpp | 223 +++++++++++++++++++ 7 files changed, 840 insertions(+) diff --git a/include/etl/private/ivectorpointer.h b/include/etl/private/ivectorpointer.h index 52f938fe..f9f6dd7e 100644 --- a/include/etl/private/ivectorpointer.h +++ b/include/etl/private/ivectorpointer.h @@ -467,6 +467,31 @@ namespace etl return iterator(base_t::erase(base_t::const_iterator(first), base_t::const_iterator(last))); } + //********************************************************************* + /// Swap contents with another vector. Performs operation on each individual element. + ///\param other The other vector to swap with. + //********************************************************************* + void swap(ivector& other) + { + if (this == &other) + { + return; + } + + ETL_ASSERT_OR_RETURN(this->max_size() >= other.size() && other.max_size() >= this->size(), ETL_ERROR(vector_full)); + + ivector& smaller = other.size() > this->size() ? *this : other; + ivector& larger = other.size() > this->size() ? other : *this; + + ETL_OR_STD::swap_ranges(smaller.begin(), smaller.end(), larger.begin()); + + typename ivector::iterator larger_itr = etl::next(larger.begin(), smaller.size()); + + etl::move(larger_itr, larger.end(), etl::back_inserter(smaller)); + + larger.erase(larger_itr, larger.end()); + } + //************************************************************************* /// Assignment operator. //************************************************************************* @@ -890,6 +915,31 @@ namespace etl return iterator(base_t::erase(base_t::iterator(first), base_t::iterator(last))); } + //********************************************************************* + /// Swap contents with another vector. Performs operation on each individual element. + ///\param other The other vector to swap with. + //********************************************************************* + void swap(ivector& other) + { + if (this == &other) + { + return; + } + + ETL_ASSERT_OR_RETURN(this->max_size() >= other.size() && other.max_size() >= this->size(), ETL_ERROR(vector_full)); + + ivector& smaller = other.size() > this->size() ? *this : other; + ivector& larger = other.size() > this->size() ? other : *this; + + ETL_OR_STD::swap_ranges(smaller.begin(), smaller.end(), larger.begin()); + + typename ivector::iterator larger_itr = etl::next(larger.begin(), smaller.size()); + + etl::move(larger_itr, larger.end(), etl::back_inserter(smaller)); + + larger.erase(larger_itr, larger.end()); + } + //************************************************************************* /// Assignment operator. //************************************************************************* diff --git a/include/etl/vector.h b/include/etl/vector.h index c36f9b55..92caf40c 100644 --- a/include/etl/vector.h +++ b/include/etl/vector.h @@ -947,6 +947,31 @@ namespace etl return first_; } + //********************************************************************* + /// Swap contents with another vector. Performs operation on each individual element. + ///\param other The other vector to swap with. + //********************************************************************* + void swap(ivector& other) + { + if (this == &other) + { + return; + } + + ETL_ASSERT_OR_RETURN(this->max_size() >= other.size() && other.max_size() >= this->size(), ETL_ERROR(vector_full)); + + ivector& smaller = other.size() > this->size() ? *this : other; + ivector& larger = other.size() > this->size() ? other : *this; + + ETL_OR_STD::swap_ranges(smaller.begin(), smaller.end(), larger.begin()); + + typename ivector::iterator larger_itr = etl::next(larger.begin(), smaller.size()); + + etl::move(larger_itr, larger.end(), etl::back_inserter(smaller)); + + larger.erase(larger_itr, larger.end()); + } + //************************************************************************* /// Assignment operator. //************************************************************************* @@ -1863,6 +1888,17 @@ namespace etl return d; } + + //********************************************************************* + /// Overloaded swap for etl::ivector + ///\param lhs The first vector to swap with. + ///\param rhs The second vector to swap with. + //********************************************************************* + template + void swap(ivector& lhs, ivector& rhs) + { + lhs.swap(rhs); + } } #endif diff --git a/test/test_vector.cpp b/test/test_vector.cpp index 03f6a615..c1e679a4 100644 --- a/test/test_vector.cpp +++ b/test/test_vector.cpp @@ -52,6 +52,8 @@ namespace Compare_Data different_data; Compare_Data insert_data; Compare_Data blank_data; + Compare_Data swap_data; + Compare_Data swap_other_data; //************************************************************************* struct SetupFixture @@ -63,6 +65,8 @@ namespace int n_less[] = { 0, 1, 2, 3, 3, 5, 6, 7, 8, 9 }; int n_greater[] = { 0, 1, 2, 4, 4, 5, 6, 7, 8, 9 }; int n_blank[] = { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99 }; + int n_swap[] = { 0, 1, 2, 3, 4, 5 }; + int n_swap_other[] = { 6, 7, 8, 9 }; initial_data.assign(std::begin(n), std::end(n)); insert_data.assign(std::begin(n_insert), std::end(n_insert)); @@ -71,6 +75,8 @@ namespace shorter_data.assign(std::begin(n_greater), std::end(n_greater) - 1); different_data.assign(initial_data.rbegin(), initial_data.rend()); blank_data.assign(std::begin(n_blank), std::end(n_blank)); + swap_data.assign(std::begin(n_swap), std::end(n_swap)); + swap_other_data.assign(std::begin(n_swap_other), std::end(n_swap_other)); } }; @@ -1620,5 +1626,113 @@ namespace CHECK(std::equal(blank_data.begin(), blank_data.end(), data.begin())); } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_same_capacity) + { + Data etl_data(swap_data.begin(), swap_data.end()); + Data etl_data2(swap_other_data.begin(), swap_other_data.end()); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_different_capacity) + { + const size_t other_size = 6; + Data etl_data(swap_data.begin(), swap_data.end()); + etl::vector etl_data2(swap_other_data.begin(), swap_other_data.end()); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == other_size); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + } + + //************************************************************************* + TEST(test_swap_insufficient_capacity) + { + etl::vector etl_data(4); + etl::vector etl_data2(6); + + CHECK_THROW(etl_data.swap(etl_data2), etl::vector_full); + CHECK_THROW(etl_data2.swap(etl_data), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_etl_swap_different_capacity) + { + const size_t other_size = 6; + Data etl_data(swap_data.begin(), swap_data.end()); + etl::vector etl_data2(swap_other_data.begin(), swap_other_data.end()); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + + etl::swap(etl_data, etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == other_size); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl::swap(etl_data, etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + } } } diff --git a/test/test_vector_external_buffer.cpp b/test/test_vector_external_buffer.cpp index 912ebc29..a65648fe 100644 --- a/test/test_vector_external_buffer.cpp +++ b/test/test_vector_external_buffer.cpp @@ -58,6 +58,8 @@ namespace Compare_Data shorter_data; Compare_Data different_data; Compare_Data insert_data; + Compare_Data swap_data; + Compare_Data swap_other_data; //************************************************************************* struct SetupFixture @@ -68,6 +70,8 @@ namespace int n_insert[] = { 11, 12, 13 }; int n_less[] = { 0, 1, 2, 3, 3, 5, 6, 7, 8, 9 }; int n_greater[] = { 0, 1, 2, 4, 4, 5, 6, 7, 8, 9 }; + int n_swap[] = { 0, 1, 2, 3, 4, 5 }; + int n_swap_other[] = { 6, 7, 8, 9 }; initial_data.assign(std::begin(n), std::end(n)); insert_data.assign(std::begin(n_insert), std::end(n_insert)); @@ -75,6 +79,8 @@ namespace greater_data.assign(std::begin(n_greater), std::end(n_greater)); shorter_data.assign(std::begin(n_greater), std::end(n_greater) - 1); different_data.assign(initial_data.rbegin(), initial_data.rend()); + swap_data.assign(std::begin(n_swap), std::end(n_swap)); + swap_other_data.assign(std::begin(n_swap_other), std::end(n_swap_other)); std::fill_n(buffer1, SIZE, -1); std::fill_n(buffer2, SIZE, -1); @@ -1320,5 +1326,113 @@ namespace CHECK_EQUAL(raw[4].i, dest[6].i); CHECK_EQUAL(raw[5].i, dest[7].i); } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_same_capacity) + { + Data etl_data(swap_data.begin(), swap_data.end(), buffer1, SIZE); + Data etl_data2(swap_other_data.begin(), swap_other_data.end(), buffer2, SIZE); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_different_capacity) + { + const size_t other_size = 6; + Data etl_data(swap_data.begin(), swap_data.end(), buffer1, SIZE); + Data etl_data2(swap_other_data.begin(), swap_other_data.end(), buffer2, other_size); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == other_size); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + } + + //************************************************************************* + TEST(test_swap_insufficient_capacity) + { + Data etl_data(4, buffer1, 4); + etl::vector etl_data2(6); + + CHECK_THROW(etl_data.swap(etl_data2), etl::vector_full); + CHECK_THROW(etl_data2.swap(etl_data), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_between_internal_and_external) + { + const size_t other_size = 6; + Data etl_data(swap_data.begin(), swap_data.end(), buffer1, SIZE); + etl::vector etl_data2(swap_other_data.begin(), swap_other_data.end()); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == other_size); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + } } } diff --git a/test/test_vector_non_trivial.cpp b/test/test_vector_non_trivial.cpp index aabd0e4a..1a10ac77 100644 --- a/test/test_vector_non_trivial.cpp +++ b/test/test_vector_non_trivial.cpp @@ -62,6 +62,8 @@ namespace CompareDataNDC shorter_data; CompareDataNDC different_data; CompareDataNDC insert_data; + CompareDataNDC swap_data; + CompareDataNDC swap_other_data; //************************************************************************* struct SetupFixture @@ -72,6 +74,8 @@ namespace NDC n_insert[] = { NDC("11"), NDC("12"), NDC("13") }; NDC n_less[] = { NDC("0"), NDC("1"), NDC("2"), NDC("3"), NDC("3"), NDC("5"), NDC("6"), NDC("7"), NDC("8"), NDC("9") }; NDC n_greater[] = { NDC("0"), NDC("1"), NDC("2"), NDC("4"), NDC("4"), NDC("5"), NDC("6"), NDC("7"), NDC("8"), NDC("9") }; + NDC n_swap[] = { NDC("0"), NDC("1"), NDC("2"), NDC("4"), NDC("4"), NDC("5") }; + NDC n_swap_other[] = { NDC("6"), NDC("7"), NDC("8"), NDC("9") }; initial_data.assign(std::begin(n), std::end(n)); insert_data.assign(std::begin(n_insert), std::end(n_insert)); @@ -79,6 +83,8 @@ namespace greater_data.assign(std::begin(n_greater), std::end(n_greater)); shorter_data.assign(std::begin(n_greater), std::end(n_greater) - 1); different_data.assign(initial_data.rbegin(), initial_data.rend()); + swap_data.assign(std::begin(n_swap), std::end(n_swap)); + swap_other_data.assign(std::begin(n_swap_other), std::end(n_swap_other)); } }; @@ -1407,5 +1413,80 @@ namespace const DataNDC initial2(initial_data.begin(), initial_data.end()); CHECK((initial >= initial2) == (initial_data >= initial_data)); } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_same_capacity) + { + DataNDC etl_data(swap_data.begin(), swap_data.end()); + DataNDC etl_data2(swap_other_data.begin(), swap_other_data.end()); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_different_capacity) + { + const size_t other_size = 6; + DataNDC etl_data(swap_data.begin(), swap_data.end()); + etl::vector etl_data2(swap_other_data.begin(), swap_other_data.end()); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == other_size); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + } + + //************************************************************************* + TEST(test_swap_insufficient_capacity) + { + etl::vector etl_data(4); + etl::vector etl_data2(6); + + CHECK_THROW(etl_data.swap(etl_data2), etl::vector_full); + CHECK_THROW(etl_data2.swap(etl_data), etl::vector_full); + } } } diff --git a/test/test_vector_pointer.cpp b/test/test_vector_pointer.cpp index ee6ce915..78d2b0db 100644 --- a/test/test_vector_pointer.cpp +++ b/test/test_vector_pointer.cpp @@ -54,6 +54,8 @@ namespace Compare_Data shorter_data; Compare_Data different_data; Compare_Data insert_data; + Compare_Data swap_data; + Compare_Data swap_other_data; int n0 = 0; int n1 = 1; @@ -78,6 +80,8 @@ namespace int* n_insert[] = { &n11, &n12, &n13 }; int* n_less[] = { &n0, &n1, &n2, &n3, &n3, &n5, &n6, &n7, &n8, &n9 }; int* n_greater[] = { &n0, &n1, &n2, &n4, &n4, &n5, &n6, &n7, &n8, &n9 }; + int* n_swap[] = { &n0, &n1, &n2, &n3, &n4, &n5 }; + int* n_swap_other[] = { &n6, &n7, &n8, &n9 }; initial_data.assign(std::begin(n), std::end(n)); insert_data.assign(std::begin(n_insert), std::end(n_insert)); @@ -85,6 +89,8 @@ namespace greater_data.assign(std::begin(n_greater), std::end(n_greater)); shorter_data.assign(std::begin(n_greater), std::end(n_greater) - 1); different_data.assign(initial_data.rbegin(), initial_data.rend()); + swap_data.assign(std::begin(n_swap), std::end(n_swap)); + swap_other_data.assign(std::begin(n_swap_other), std::end(n_swap_other)); } }; @@ -2199,5 +2205,221 @@ namespace CHECK_EQUAL(9, *data[9]); } #endif + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_same_capacity) + { + Data etl_data(swap_data.begin(), swap_data.end()); + Data etl_data2(swap_other_data.begin(), swap_other_data.end()); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_const_same_capacity) + { + CData etl_data(swap_data.begin(), swap_data.end()); + CData etl_data2(swap_other_data.begin(), swap_other_data.end()); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_different_capacity) + { + const size_t other_size = 6; + Data etl_data(swap_data.begin(), swap_data.end()); + etl::vector etl_data2(swap_other_data.begin(), swap_other_data.end()); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == other_size); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_const_different_capacity) + { + const size_t other_size = 6; + CData etl_data(swap_data.begin(), swap_data.end()); + etl::vector etl_data2(swap_other_data.begin(), swap_other_data.end()); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == other_size); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + } + + //************************************************************************* + TEST(test_swap_insufficient_capacity) + { + etl::vector etl_data(4); + etl::vector etl_data2(6); + + CHECK_THROW(etl_data.swap(etl_data2), etl::vector_full); + CHECK_THROW(etl_data2.swap(etl_data), etl::vector_full); + } + + //************************************************************************* + TEST(test_swap_const_insufficient_capacity) + { + etl::vector etl_data(4); + etl::vector etl_data2(6); + + CHECK_THROW(etl_data.swap(etl_data2), etl::vector_full); + CHECK_THROW(etl_data2.swap(etl_data), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_etl_swap_different_capacity) + { + const size_t other_size = 6; + Data etl_data(swap_data.begin(), swap_data.end()); + etl::vector etl_data2(swap_other_data.begin(), swap_other_data.end()); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + + etl::swap(etl_data, etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == other_size); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl::swap(etl_data, etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_etl_swap_const_different_capacity) + { + const size_t other_size = 6; + CData etl_data(swap_data.begin(), swap_data.end()); + etl::vector etl_data2(swap_other_data.begin(), swap_other_data.end()); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + + etl::swap(etl_data, etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == other_size); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl::swap(etl_data, etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + } } } diff --git a/test/test_vector_pointer_external_buffer.cpp b/test/test_vector_pointer_external_buffer.cpp index e6be4831..7fa4af32 100644 --- a/test/test_vector_pointer_external_buffer.cpp +++ b/test/test_vector_pointer_external_buffer.cpp @@ -62,6 +62,8 @@ namespace Compare_Data shorter_data; Compare_Data different_data; Compare_Data insert_data; + Compare_Data swap_data; + Compare_Data swap_other_data; //************************************************************************* struct SetupFixture @@ -87,6 +89,8 @@ namespace int* n_insert[] = { &n11, &n12, &n13 }; int* n_less[] = { &n0, &n1, &n2, &n3, &n3, &n5, &n6, &n7, &n8, &n9 }; int* n_greater[] = { &n0, &n1, &n2, &n4, &n4, &n5, &n6, &n7, &n8, &n9 }; + int* n_swap[] = { &n0, &n1, &n2, &n3, &n4, &n5 }; + int* n_swap_other[] = { &n6, &n7, &n8, &n9 }; initial_data.assign(std::begin(n), std::end(n)); insert_data.assign(std::begin(n_insert), std::end(n_insert)); @@ -94,6 +98,8 @@ namespace greater_data.assign(std::begin(n_greater), std::end(n_greater)); shorter_data.assign(std::begin(n_greater), std::end(n_greater) - 1); different_data.assign(initial_data.rbegin(), initial_data.rend()); + swap_data.assign(std::begin(n_swap), std::end(n_swap)); + swap_other_data.assign(std::begin(n_swap_other), std::end(n_swap_other)); std::fill_n(buffer1, SIZE, nullptr); std::fill_n(buffer2, SIZE, nullptr); @@ -2013,5 +2019,222 @@ namespace CHECK(i1 == *i2); CHECK(&i1 == i2); } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_same_capacity) + { + Data etl_data(swap_data.begin(), swap_data.end(), buffer1, SIZE); + Data etl_data2(swap_other_data.begin(), swap_other_data.end(), buffer2, SIZE); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_const_same_capacity) + { + CData etl_data(swap_data.begin(), swap_data.end(), buffer1, SIZE); + CData etl_data2(swap_other_data.begin(), swap_other_data.end(), buffer2, SIZE); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_different_capacity) + { + const size_t other_size = 6; + Data etl_data(swap_data.begin(), swap_data.end(), buffer1, SIZE); + Data etl_data2(swap_other_data.begin(), swap_other_data.end(), buffer2, other_size); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == other_size); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_const_different_capacity) + { + const size_t other_size = 6; + CData etl_data(swap_data.begin(), swap_data.end(), buffer1, SIZE); + CData etl_data2(swap_other_data.begin(), swap_other_data.end(), buffer2, other_size); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == other_size); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + } + + //************************************************************************* + TEST(test_swap_insufficient_capacity) + { + Data etl_data(4, buffer1, 4); + etl::vector etl_data2(6); + + CHECK_THROW(etl_data.swap(etl_data2), etl::vector_full); + CHECK_THROW(etl_data2.swap(etl_data), etl::vector_full); + } + + //************************************************************************* + TEST(test_swap_const_insufficient_capacity) + { + CData etl_data(4, buffer1, 4); + etl::vector etl_data2(6); + + CHECK_THROW(etl_data.swap(etl_data2), etl::vector_full); + CHECK_THROW(etl_data2.swap(etl_data), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_between_internal_and_external) + { + const size_t other_size = 6; + Data etl_data(swap_data.begin(), swap_data.end(), buffer1, SIZE); + etl::vector etl_data2(swap_other_data.begin(), swap_other_data.end()); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == other_size); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_swap_const_between_internal_and_external) + { + const size_t other_size = 6; + CData etl_data(swap_data.begin(), swap_data.end(), buffer1, SIZE); + etl::vector etl_data2(swap_other_data.begin(), swap_other_data.end()); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_data.size()); + CHECK(etl_data2.max_size() == other_size); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_other_data.size()); + CHECK(etl_data.max_size() == SIZE); + + etl_data.swap(etl_data2); + + CHECK(std::equal(swap_data.begin(), swap_data.end(), etl_data.begin())); + CHECK(etl_data.size() == swap_data.size()); + CHECK(etl_data.max_size() == SIZE); + CHECK(std::equal(swap_other_data.begin(), swap_other_data.end(), etl_data2.begin())); + CHECK(etl_data2.size() == swap_other_data.size()); + CHECK(etl_data2.max_size() == other_size); + } } } From 14ce8a93fb13937a5247839c69ffdd1c793f417e Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 11 Jan 2026 18:55:00 +0100 Subject: [PATCH 073/298] Updated release note and version --- arduino/library-arduino.json | 2 +- arduino/library-arduino.properties | 2 +- include/etl/version.h | 4 ++-- library.json | 2 +- library.properties | 2 +- support/Release notes.txt | 30 +++++++++++++++++++++++++++++- version.txt | 2 +- 7 files changed, 36 insertions(+), 8 deletions(-) diff --git a/arduino/library-arduino.json b/arduino/library-arduino.json index 1899443a..e6485f26 100644 --- a/arduino/library-arduino.json +++ b/arduino/library-arduino.json @@ -1,6 +1,6 @@ { "name": "Embedded Template Library ETL", - "version": "20.44.2", + "version": "20.45.0", "authors": { "name": "John Wellbelove", "email": "john.wellbelove@etlcpp.com" diff --git a/arduino/library-arduino.properties b/arduino/library-arduino.properties index e4799f0e..a63e6411 100644 --- a/arduino/library-arduino.properties +++ b/arduino/library-arduino.properties @@ -1,5 +1,5 @@ name=Embedded Template Library ETL -version=20.44.2 +version=20.45.0 author= John Wellbelove maintainer=John Wellbelove license=MIT diff --git a/include/etl/version.h b/include/etl/version.h index 3309a7df..02e931b1 100644 --- a/include/etl/version.h +++ b/include/etl/version.h @@ -39,8 +39,8 @@ SOFTWARE. ///\ingroup utilities #define ETL_VERSION_MAJOR 20 -#define ETL_VERSION_MINOR 44 -#define ETL_VERSION_PATCH 2 +#define ETL_VERSION_MINOR 45 +#define ETL_VERSION_PATCH 0 #define ETL_VERSION ETL_STRING(ETL_VERSION_MAJOR) "." ETL_STRING(ETL_VERSION_MINOR) "." ETL_STRING(ETL_VERSION_PATCH) #define ETL_VERSION_W ETL_WIDE_STRING(ETL_VERSION_MAJOR) L"." ETL_WIDE_STRING(ETL_VERSION_MINOR) L"." ETL_WIDE_STRING(ETL_VERSION_PATCH) diff --git a/library.json b/library.json index 887a37f3..7f66b3b7 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "Embedded Template Library", - "version": "20.44.2", + "version": "20.45.0", "authors": { "name": "John Wellbelove", "email": "john.wellbelove@etlcpp.com" diff --git a/library.properties b/library.properties index 59a1888c..16be9c21 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library -version=20.44.2 +version=20.45.0 author= John Wellbelove maintainer=John Wellbelove license=MIT diff --git a/support/Release notes.txt b/support/Release notes.txt index 7be7c7ae..d8ab88ea 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,12 +1,39 @@ =============================================================================== +20.45.0 + +Issues: +#1184 Request: Adding a method to check whether a etl::callback_timer_atomic is currently running +#1189 Request: make useage of osMutexRobust in etl::mutex optional +#1207 Monadic Operations for etl::expected +#1240 Add redundant semicolon checks to CMakeLists.txt and fix issues +#1241 Add -pedantic-errors to unit test CMakeLists.txt and fix issues +#1242 Add begin() and end() to etl::optional + +Pull requests: +#1232 Exception std based option +#1235 Bugfixes for compile errors in optimized tests +#1237 remove extra ; +#1238 Various cleanup +#1239 Indirect vector checks +#1244 Fix no check macros +#1245 Fix discrepancy with STL in max_element and minmax_element +#1246 Implement .begin() and .end() for etl::optional +#1251 Add etl::inplace_function +#1252 Add ThreadX mutex support +#1254 Make code base with tests compile under gcc-14 +#1255 Fix syntax errors in base64 test +#1256 ivector swap + + +=============================================================================== 20.44.2 Updates: Replaced locally defined logical_not_t with etl::negation Fixes: -#1228 unused parameter 'secure' #1224 Passing a const in optional::value_or() not compiling +#1228 unused parameter 'secure' Pull Requests: #1210 Fixed span reinterpret_as should return fixed span @@ -20,6 +47,7 @@ Pull Requests: #1226 Add missing include to optional #1229 variant_legacy.h: Rename template parameters #1231 Issue 1212 span constructor +#1256 ivector swap =============================================================================== 20.44.1 diff --git a/version.txt b/version.txt index 3e132281..aae4b050 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -20.44.2 +20.45.0 From cdd1de4b56b9e20af6ee6befc29b4efe18d59799 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 11 Jan 2026 18:55:00 +0100 Subject: [PATCH 074/298] Updated release note and version --- support/Release notes.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/support/Release notes.txt b/support/Release notes.txt index d8ab88ea..2c098449 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -24,7 +24,6 @@ Pull requests: #1255 Fix syntax errors in base64 test #1256 ivector swap - =============================================================================== 20.44.2 From e9c2577d8e98ca9dd3a9c211cd2bb9395890978e Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 11 Jan 2026 18:55:00 +0100 Subject: [PATCH 075/298] Updated release note and version --- support/Release notes.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/support/Release notes.txt b/support/Release notes.txt index 2c098449..8b438c1e 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -10,6 +10,8 @@ Issues: #1242 Add begin() and end() to etl::optional Pull requests: +#1204 Add etl::format +#1213 Added concepts.h and tests #1232 Exception std based option #1235 Bugfixes for compile errors in optimized tests #1237 remove extra ; @@ -46,7 +48,6 @@ Pull Requests: #1226 Add missing include to optional #1229 variant_legacy.h: Rename template parameters #1231 Issue 1212 span constructor -#1256 ivector swap =============================================================================== 20.44.1 From 0644f9827b253bb7e3eb305e629141cad30d412f Mon Sep 17 00:00:00 2001 From: Bo Rydberg <2945606+bolry@users.noreply.github.com> Date: Fri, 16 Jan 2026 09:02:46 +0100 Subject: [PATCH 076/298] Fix year_month arithmetic and correct chrono API behavior (#1257) * Fix & add more tests for year_month arithmetic * Minor addtions to previous commit * More missing values to be uninitialized * Update the default constructors to = default and correct default constructor tests accordingly * Fix & add more tests for year_month arithmetic * Minor addtions to previous commit * More missing values to be uninitialized * Update the default constructors to = default and correct default constructor tests accordingly * Restore default constructor behavior for chrono calender --- include/etl/private/chrono/day.h | 61 ++------------- include/etl/private/chrono/month.h | 54 ++----------- include/etl/private/chrono/weekday.h | 20 ----- include/etl/private/chrono/year.h | 66 +++++----------- include/etl/private/chrono/year_month.h | 16 ++-- include/etl/private/chrono/year_month_day.h | 20 +++-- .../etl/private/chrono/year_month_weekday.h | 12 ++- test/test_chrono_day.cpp | 9 --- test/test_chrono_month.cpp | 9 --- test/test_chrono_weekday_last.cpp | 1 - test/test_chrono_year.cpp | 23 +++--- test/test_chrono_year_month.cpp | 75 ++++++++++++++++++- test/test_chrono_year_month_day.cpp | 2 +- 13 files changed, 148 insertions(+), 220 deletions(-) diff --git a/include/etl/private/chrono/day.h b/include/etl/private/chrono/day.h index fa5bb712..6797c81f 100644 --- a/include/etl/private/chrono/day.h +++ b/include/etl/private/chrono/day.h @@ -57,39 +57,10 @@ namespace etl /// Construct from unsigned //*********************************************************************** ETL_CONSTEXPR explicit day(unsigned value_) ETL_NOEXCEPT - : value(static_cast(value_)) + : value(static_cast(value_)) { } - //*********************************************************************** - /// Copy constructor - //*********************************************************************** - ETL_CONSTEXPR14 day(const etl::chrono::day& other) ETL_NOEXCEPT - : value(other.value) - { - } - - //*********************************************************************** - /// Assignment operator - //*********************************************************************** - ETL_CONSTEXPR14 etl::chrono::day& operator =(const etl::chrono::day& rhs) ETL_NOEXCEPT - { - value = rhs.value; - - return *this; - } - - //*********************************************************************** - /// Assignment operator - //*********************************************************************** - template - ETL_CONSTEXPR14 etl::chrono::day& operator =(const etl::chrono::duration& rhs) - { - value = etl::chrono::duration_cast(rhs); - - return *this; - } - //*********************************************************************** /// Pre-increment operator //*********************************************************************** @@ -105,7 +76,7 @@ namespace etl //*********************************************************************** ETL_CONSTEXPR14 etl::chrono::day operator ++(int) ETL_NOEXCEPT { - const etl::chrono::day temp = *this; + etl::chrono::day temp = *this; ++value; return temp; @@ -126,7 +97,7 @@ namespace etl //*********************************************************************** ETL_CONSTEXPR14 etl::chrono::day operator --(int) ETL_NOEXCEPT { - const etl::chrono::day temp = *this; + etl::chrono::day temp = *this; --value; return temp; @@ -137,7 +108,7 @@ namespace etl //*********************************************************************** ETL_CONSTEXPR14 etl::chrono::day& operator +=(const etl::chrono::days& ds) ETL_NOEXCEPT { - value += static_cast(ds.count()); + value += static_cast(ds.count()); return *this; } @@ -147,7 +118,7 @@ namespace etl //*********************************************************************** ETL_CONSTEXPR14 etl::chrono::day& operator -=(const etl::chrono::days& ds) ETL_NOEXCEPT { - value -= static_cast(ds.count()); + value -= static_cast(ds.count()); return *this; } @@ -164,9 +135,9 @@ namespace etl //*********************************************************************** /// Conversion operator to unsigned int //*********************************************************************** - ETL_CONSTEXPR14 operator unsigned() const ETL_NOEXCEPT + ETL_CONSTEXPR14 /*explicit*/ operator unsigned() const ETL_NOEXCEPT { - return static_cast(value); + return value; } //*********************************************************************** @@ -184,24 +155,6 @@ namespace etl return 0; } - //*********************************************************************** - /// The minimum day value for which ok() will return true - //*********************************************************************** - ETL_NODISCARD - static ETL_CONSTEXPR14 etl::chrono::day min() ETL_NOEXCEPT - { - return etl::chrono::day(1); - } - - //*********************************************************************** - /// The maximum day value for which ok() will return true - //*********************************************************************** - ETL_NODISCARD - static ETL_CONSTEXPR14 etl::chrono::day max() ETL_NOEXCEPT - { - return etl::chrono::day(31); - } - private: rep value; diff --git a/include/etl/private/chrono/month.h b/include/etl/private/chrono/month.h index 1ab694d4..4f257da3 100644 --- a/include/etl/private/chrono/month.h +++ b/include/etl/private/chrono/month.h @@ -72,24 +72,6 @@ namespace etl { } - //*********************************************************************** - /// Copy constructor - //*********************************************************************** - ETL_CONSTEXPR14 month(const etl::chrono::month& other) ETL_NOEXCEPT - : value(other.value) - { - } - - //*********************************************************************** - /// Assignment operator - //*********************************************************************** - ETL_CONSTEXPR14 etl::chrono::month& operator =(const etl::chrono::month& rhs) ETL_NOEXCEPT - { - value = rhs.value; - - return *this; - } - //*********************************************************************** /// Pre-increment operator //*********************************************************************** @@ -105,9 +87,9 @@ namespace etl //*********************************************************************** ETL_CONSTEXPR14 etl::chrono::month operator ++(int) ETL_NOEXCEPT { - const etl::chrono::month temp = *this; + etl::chrono::month temp = *this; - *this += etl::chrono::months(1); + ++*this; return temp; } @@ -129,7 +111,7 @@ namespace etl { etl::chrono::month temp = *this; - *this -= etl::chrono::months(1); + --*this; return temp; } @@ -155,7 +137,7 @@ namespace etl } //*********************************************************************** - /// Returns true if the month is within the valid 1 to 31 range + /// Returns true if the month is within the valid 1 to 12 range //*********************************************************************** ETL_NODISCARD ETL_CONSTEXPR14 bool ok() const ETL_NOEXCEPT @@ -178,30 +160,12 @@ namespace etl return 0; } - //*********************************************************************** - /// The minimum month value for which ok() will return true - //*********************************************************************** - ETL_NODISCARD - static ETL_CONSTEXPR14 etl::chrono::month min() ETL_NOEXCEPT - { - return etl::chrono::month(1); - } - - //*********************************************************************** - /// The maximum month value for which ok() will return true - //*********************************************************************** - ETL_NODISCARD - static ETL_CONSTEXPR14 etl::chrono::month max() ETL_NOEXCEPT - { - return etl::chrono::month(12); - } - //*********************************************************************** /// Conversion operator to unsigned int //*********************************************************************** - ETL_CONSTEXPR14 operator unsigned() const ETL_NOEXCEPT + ETL_CONSTEXPR14 /*explicit*/ operator unsigned() const ETL_NOEXCEPT { - return static_cast(value); + return value; } private: @@ -331,10 +295,8 @@ namespace etl etl::chrono::months ms(difference); // Check for validity. - if (m1 == (m2 + ms)) - { - return ms; - } + assert(m1 == (m2 + ms)); + return ms; } return etl::chrono::months(); diff --git a/include/etl/private/chrono/weekday.h b/include/etl/private/chrono/weekday.h index de511a83..19246368 100644 --- a/include/etl/private/chrono/weekday.h +++ b/include/etl/private/chrono/weekday.h @@ -362,26 +362,6 @@ namespace etl { } - //*********************************************************************** - /// Copy constructor - //*********************************************************************** - ETL_CONSTEXPR14 weekday_indexed(const etl::chrono::weekday_indexed& other) ETL_NOEXCEPT - : wd(other.wd) - , i(other.i) - { - } - - //*********************************************************************** - /// Assignment operator - //*********************************************************************** - ETL_CONSTEXPR14 etl::chrono::weekday_indexed& operator =(const etl::chrono::weekday_indexed& rhs) ETL_NOEXCEPT - { - wd = rhs.wd; - i = rhs.i; - - return *this; - } - //*********************************************************************** /// Get weekday //*********************************************************************** diff --git a/include/etl/private/chrono/year.h b/include/etl/private/chrono/year.h index fd3d8096..b21c572e 100644 --- a/include/etl/private/chrono/year.h +++ b/include/etl/private/chrono/year.h @@ -54,31 +54,13 @@ namespace etl } //*********************************************************************** - /// Construct from unsigned + /// Construct from int //*********************************************************************** - ETL_CONSTEXPR explicit year(unsigned value_) ETL_NOEXCEPT + ETL_CONSTEXPR explicit year(int value_) ETL_NOEXCEPT : value(value_) { } - //*********************************************************************** - /// Copy constructor - //*********************************************************************** - ETL_CONSTEXPR14 year(const etl::chrono::year& other) ETL_NOEXCEPT - : value(other.value) - { - } - - //*********************************************************************** - /// Assignment operator - //*********************************************************************** - ETL_CONSTEXPR14 etl::chrono::year& operator =(const etl::chrono::year& rhs) ETL_NOEXCEPT - { - value = rhs.value; - - return *this; - } - //*********************************************************************** /// Pre-increment operator //*********************************************************************** @@ -94,7 +76,7 @@ namespace etl //*********************************************************************** ETL_CONSTEXPR14 etl::chrono::year operator ++(int) ETL_NOEXCEPT { - const etl::chrono::year temp = *this; + etl::chrono::year temp = *this; ++value; return temp; @@ -115,7 +97,7 @@ namespace etl //*********************************************************************** ETL_CONSTEXPR14 etl::chrono::year operator --(int) ETL_NOEXCEPT { - const etl::chrono::year temp = *this; + etl::chrono::year temp = *this; --value; return temp; @@ -126,7 +108,7 @@ namespace etl //*********************************************************************** ETL_CONSTEXPR14 etl::chrono::year& operator +=(const etl::chrono::years& ys) ETL_NOEXCEPT { - value += static_cast(ys.count()); + value += ys.count(); return *this; } @@ -136,7 +118,7 @@ namespace etl //*********************************************************************** ETL_CONSTEXPR14 etl::chrono::year& operator -=(const etl::chrono::years& ys) ETL_NOEXCEPT { - value -= static_cast(ys.count()); + value -= ys.count(); return *this; } @@ -182,9 +164,9 @@ namespace etl //*********************************************************************** /// Conversion operator to unsigned int //*********************************************************************** - ETL_CONSTEXPR14 operator int() const ETL_NOEXCEPT + ETL_CONSTEXPR14 /*explicit*/ operator int() const ETL_NOEXCEPT { - return static_cast(value); + return value; } //*********************************************************************** @@ -212,7 +194,7 @@ namespace etl //*********************************************************************** inline ETL_CONSTEXPR14 bool operator ==(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT { - return (static_cast(y1) == static_cast(y2)); + return (static_cast(y1) == static_cast(y2)); } //*********************************************************************** @@ -228,7 +210,7 @@ namespace etl //*********************************************************************** inline ETL_CONSTEXPR14 bool operator <(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT { - return (static_cast(y1) < static_cast(y2)); + return (static_cast(y1) < static_cast(y2)); } //*********************************************************************** @@ -236,7 +218,7 @@ namespace etl //*********************************************************************** inline ETL_CONSTEXPR14 bool operator <=(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT { - return (static_cast(y1) <= static_cast(y2)); + return (static_cast(y1) <= static_cast(y2)); } //*********************************************************************** @@ -244,7 +226,7 @@ namespace etl //*********************************************************************** inline ETL_CONSTEXPR14 bool operator >(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT { - return (static_cast(y1) > static_cast(y2)); + return (static_cast(y1) > static_cast(y2)); } //*********************************************************************** @@ -252,7 +234,7 @@ namespace etl //*********************************************************************** inline ETL_CONSTEXPR14 bool operator >=(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT { - return (static_cast(y1) >= static_cast(y2)); + return (static_cast(y1) >= static_cast(y2)); } //*********************************************************************** @@ -261,7 +243,7 @@ namespace etl #if ETL_USING_CPP20 [[nodiscard]] inline constexpr auto operator <=>(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT { - return (static_cast(y1) <=> static_cast(y2)); + return (static_cast(y1) <=> static_cast(y2)); } #endif @@ -304,27 +286,13 @@ namespace etl return result; } - //*********************************************************************** - /// Subtract etl::chrono::year from etl::chrono::years - ///\return etl::chrono::years - //*********************************************************************** - inline ETL_CONSTEXPR14 etl::chrono::year operator -(const etl::chrono::years& ys, const etl::chrono::year& y) ETL_NOEXCEPT - { - etl::chrono::year result(y); - - result -= ys; - - return result; - } - //*********************************************************************** /// Subtract etl::chrono::year from etl::chrono::year ///\return etl::chrono::years //*********************************************************************** inline ETL_CONSTEXPR14 etl::chrono::years operator -(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT { - return etl::chrono::years(static_cast(static_cast(y1)) - - static_cast(static_cast(y2))); + return etl::chrono::years(static_cast(y1) - static_cast(y2)); } } @@ -337,7 +305,7 @@ namespace etl { size_t operator()(const etl::chrono::year& y) const { - etl::chrono::year::rep value = static_cast(static_cast(y)); + etl::chrono::year::rep value = static_cast(static_cast(y)); const uint8_t* p = reinterpret_cast(&value); return etl::private_hash::generic_hash(p, p + sizeof(value)); @@ -362,7 +330,7 @@ namespace etl inline ETL_CONSTEXPR14 etl::chrono::year operator ""_y(unsigned long long y) ETL_NOEXCEPT #endif { - return etl::chrono::year(static_cast(y)); + return etl::chrono::year(static_cast(y)); } } } diff --git a/include/etl/private/chrono/year_month.h b/include/etl/private/chrono/year_month.h index 672aadd6..36ca0526 100644 --- a/include/etl/private/chrono/year_month.h +++ b/include/etl/private/chrono/year_month.h @@ -135,7 +135,12 @@ namespace etl inline ETL_CONSTEXPR14 etl::chrono::year_month operator +(const etl::chrono::year_month& ym, const etl::chrono::months& dm) ETL_NOEXCEPT { - return etl::chrono::year_month(ym.year(), ym.month() + dm); + int dmonths = static_cast(static_cast(ym.month())) - 1 + dm.count(); + int dyears = (dmonths - 11 * (dmonths < 0)) / 12; + dmonths -= dyears * 12; + ++dmonths; + return etl::chrono::year_month((ym.year() + etl::chrono::years(dyears)), + etl::chrono::month(static_cast(dmonths))); } //************************************************************************* @@ -144,7 +149,7 @@ namespace etl inline ETL_CONSTEXPR14 etl::chrono::year_month operator +(const etl::chrono::months& dm, const etl::chrono::year_month& ym) ETL_NOEXCEPT { - return etl::chrono::year_month(ym.year(), ym.month() + dm); + return ym + dm; } //************************************************************************* @@ -162,7 +167,7 @@ namespace etl inline ETL_CONSTEXPR14 etl::chrono::year_month operator -(const etl::chrono::year_month& ym, const etl::chrono::months& dm) ETL_NOEXCEPT { - return etl::chrono::year_month(ym.year(), ym.month() - dm); + return ym + -dm; } //************************************************************************* @@ -171,7 +176,8 @@ namespace etl inline ETL_CONSTEXPR14 etl::chrono::months operator -(const etl::chrono::year_month& ym1, const etl::chrono::year_month& ym2) ETL_NOEXCEPT { - return etl::chrono::months(static_cast(((int(ym1.year()) - int(ym2.year())) * 12) + (unsigned(ym1.month()) - unsigned(ym2.month())))); + return etl::chrono::months((ym1.year() - ym2.year()) + etl::chrono::months( + static_cast(static_cast(ym1.month())) - static_cast(static_cast(ym2.month())))); } //************************************************************************* @@ -273,7 +279,7 @@ namespace etl { size_t operator()(const etl::chrono::year_month& ym) const { - etl::chrono::year::rep y = static_cast(static_cast(ym.year())); + etl::chrono::year::rep y = static_cast(static_cast(ym.year())); etl::chrono::month::rep m = static_cast(static_cast(ym.month())); uint8_t buffer[sizeof(y) + sizeof(m)]; diff --git a/include/etl/private/chrono/year_month_day.h b/include/etl/private/chrono/year_month_day.h index 6dcfa9d3..0a911a54 100644 --- a/include/etl/private/chrono/year_month_day.h +++ b/include/etl/private/chrono/year_month_day.h @@ -76,6 +76,9 @@ namespace etl /// Construct from sys_days. //************************************************************************* ETL_CONSTEXPR14 year_month_day(const etl::chrono::sys_days& sd) ETL_NOEXCEPT + : y(0) + , m(0U) + , d(0U) { // Days since 1970-01-01 int days_since_epoch = static_cast(sd.time_since_epoch().count()); @@ -101,7 +104,7 @@ namespace etl // Find the month while (true) { - unsigned char days_in_month = etl::chrono::private_chrono::days_in_month[current_month]; + unsigned char days_in_month = etl::chrono::private_chrono::days_in_month[static_cast(current_month)]; if (current_month == etl::chrono::February && current_year.is_leap()) { ++days_in_month; @@ -126,6 +129,9 @@ namespace etl /// Construct from local_days. //************************************************************************* ETL_CONSTEXPR14 year_month_day(const etl::chrono::local_days& ld) ETL_NOEXCEPT + : y(0) + , m(0) + , d(0) { etl::chrono::year_month_day ymd = sys_days(ld.time_since_epoch()); @@ -254,7 +260,7 @@ namespace etl // Add days for months in the current year for (etl::chrono::month mth(1); mth < this->month(); ++mth) { - day_count += private_chrono::days_in_month[mth]; + day_count += private_chrono::days_in_month[static_cast(mth)]; if (mth == etl::chrono::February && this->year().is_leap()) { @@ -289,7 +295,7 @@ namespace etl if (y.ok() && m.ok()) { - count = private_chrono::days_in_month[m]; + count = private_chrono::days_in_month[static_cast(m)]; if (y.is_leap() && (m == February)) { @@ -507,9 +513,9 @@ namespace etl ETL_NODISCARD ETL_CONSTEXPR14 etl::chrono::day day() const ETL_NOEXCEPT { - etl::chrono::day d = etl::chrono::day(etl::chrono::private_chrono::days_in_month[m]); + etl::chrono::day d = etl::chrono::day(etl::chrono::private_chrono::days_in_month[static_cast(m)]); - return (d == 28) && y.is_leap() ? etl::chrono::day(29) : d; + return (d == etl::chrono::day(28)) && y.is_leap() ? etl::chrono::day(29) : d; } //************************************************************************* @@ -788,7 +794,7 @@ namespace etl { size_t operator()(const etl::chrono::year_month_day& ymd) const { - etl::chrono::year::rep y = static_cast(static_cast(ymd.year())); + etl::chrono::year::rep y = static_cast(static_cast(ymd.year())); etl::chrono::month::rep m = static_cast(static_cast(ymd.month())); etl::chrono::day::rep d = static_cast(static_cast(ymd.day())); @@ -812,7 +818,7 @@ namespace etl { size_t operator()(const etl::chrono::year_month_day_last& ymdl) const { - etl::chrono::year::rep y = static_cast(static_cast(ymdl.year())); + etl::chrono::year::rep y = static_cast(static_cast(ymdl.year())); etl::chrono::month::rep m = static_cast(static_cast(ymdl.month())); etl::chrono::day::rep d = static_cast(static_cast(ymdl.day())); diff --git a/include/etl/private/chrono/year_month_weekday.h b/include/etl/private/chrono/year_month_weekday.h index ef8d9b31..909ff007 100644 --- a/include/etl/private/chrono/year_month_weekday.h +++ b/include/etl/private/chrono/year_month_weekday.h @@ -69,6 +69,9 @@ namespace etl /// Construct from sys_days. //************************************************************************* ETL_CONSTEXPR14 year_month_weekday(const etl::chrono::sys_days& sd) ETL_NOEXCEPT + : y(0) + , m(0U) + , wdi(etl::chrono::weekday(0), 0U) { // Extract year, month, and day year_month_day ymd = year_month_day{sd}; @@ -84,7 +87,7 @@ namespace etl // We walk backward from the given day in steps of 7 days unsigned index = 1; - for (int offset = static_cast(dy) - 7; offset > 0; offset -= 7) + for (int offset = static_cast(static_cast(dy)) - 7; offset > 0; offset -= 7) { ++index; } @@ -98,6 +101,9 @@ namespace etl /// Construct from local_days. //************************************************************************* ETL_CONSTEXPR14 year_month_weekday(const etl::chrono::local_days& ld) ETL_NOEXCEPT + : y(0) + , m(0U) + , wdi(etl::chrono::weekday(0), 0U) { year_month_weekday ymwd(sys_days(ld.time_since_epoch())); @@ -506,7 +512,7 @@ namespace etl { size_t operator()(const etl::chrono::year_month_weekday& ymwd) const { - etl::chrono::year::rep y = static_cast(static_cast(ymwd.year())); + etl::chrono::year::rep y = static_cast(static_cast(ymwd.year())); etl::chrono::month::rep m = static_cast(static_cast(ymwd.month())); unsigned int wd = ymwd.weekday().c_encoding(); @@ -530,7 +536,7 @@ namespace etl { size_t operator()(const etl::chrono::year_month_weekday_last& ymwdl) const { - etl::chrono::year::rep y = static_cast(static_cast(ymwdl.year())); + etl::chrono::year::rep y = static_cast(static_cast(ymwdl.year())); etl::chrono::month::rep m = static_cast(static_cast(ymwdl.month())); unsigned int wd = ymwdl.weekday().c_encoding(); diff --git a/test/test_chrono_day.cpp b/test/test_chrono_day.cpp index af9dec6c..28d90d2e 100644 --- a/test/test_chrono_day.cpp +++ b/test/test_chrono_day.cpp @@ -240,15 +240,6 @@ namespace } } -#if ETL_USING_ETL_CHRONO - //************************************************************************* - TEST(test_min_max_day) - { - CHECK_EQUAL(1U, Chrono::day::min()); - CHECK_EQUAL(31U, Chrono::day::max()); - } -#endif - #if ETL_USING_ETL_CHRONO //************************************************************************* TEST(test_literal_day) diff --git a/test/test_chrono_month.cpp b/test/test_chrono_month.cpp index 765d018f..d2363528 100644 --- a/test/test_chrono_month.cpp +++ b/test/test_chrono_month.cpp @@ -269,15 +269,6 @@ namespace } } -#if ETL_USING_ETL_CHRONO - //************************************************************************* - TEST(test_min_max_month) - { - CHECK_EQUAL(1U, Chrono::month::min()); - CHECK_EQUAL(12U, Chrono::month::max()); - } -#endif - #if ETL_USING_ETL_CHRONO //************************************************************************* TEST(test_month_compare) diff --git a/test/test_chrono_weekday_last.cpp b/test/test_chrono_weekday_last.cpp index 9b949160..14fefb92 100644 --- a/test/test_chrono_weekday_last.cpp +++ b/test/test_chrono_weekday_last.cpp @@ -59,7 +59,6 @@ namespace //************************************************************************* TEST(test_constructor_in_range) { - for (unsigned i = 1U; i < 5U; ++i) { Chrono::weekday_last weekday_last_monday(Chrono::Monday); Chrono::weekday_last weekday_last_tuesday(Chrono::Tuesday); diff --git a/test/test_chrono_year.cpp b/test/test_chrono_year.cpp index e7ec7904..4bb91b85 100644 --- a/test/test_chrono_year.cpp +++ b/test/test_chrono_year.cpp @@ -71,7 +71,7 @@ namespace etl::chrono::year year(i); CHECK_TRUE(year.ok()); - CHECK_EQUAL(i, int(year)); + CHECK_EQUAL(i, static_cast(year)); } } @@ -87,7 +87,7 @@ namespace etl::chrono::year this_year = ++year; CHECK_TRUE(year.ok()); - CHECK_EQUAL(count, year); + CHECK_EQUAL(count, static_cast(year)); CHECK_EQUAL(this_year, year); } } @@ -226,16 +226,11 @@ namespace //************************************************************************* TEST(test_year_minus_year) { - etl::chrono::year year(256); - etl::chrono::years years(2); - - for (int i = 0; i < 128; ++i) - { - year = years - year; - - CHECK_TRUE(year.ok()); - CHECK_EQUAL((256 - (2 * i)) - 2, int(year)); - } + etl::chrono::year y1(2056); + CHECK_TRUE(y1 - y1 == etl::chrono::years(0)); + etl::chrono::year y2(2); + CHECK_TRUE(y1 - y2 == etl::chrono::years(2054)); + CHECK_TRUE(y2 - y1 == etl::chrono::years(-2054)); } //************************************************************************* @@ -256,8 +251,8 @@ namespace //************************************************************************* TEST(test_min_max_year) { - CHECK_EQUAL(-32767, etl::chrono::year::min()); - CHECK_EQUAL(32767, etl::chrono::year::max()); + CHECK_EQUAL(-32767, static_cast(etl::chrono::year::min())); + CHECK_EQUAL(32767, static_cast(etl::chrono::year::max())); } #endif diff --git a/test/test_chrono_year_month.cpp b/test/test_chrono_year_month.cpp index e016e8c4..556b82ba 100644 --- a/test/test_chrono_year_month.cpp +++ b/test/test_chrono_year_month.cpp @@ -128,7 +128,7 @@ namespace Chrono::year_month ym2{Chrono::year(2001), Chrono::January}; Chrono::year_month ym3{Chrono::year(2000), Chrono::February}; - CHECK_TRUE(ym1 == ym1); // Same year/month/day + CHECK_TRUE(ym1 == ym1); // Same year/month CHECK_FALSE(ym1 == ym2); // Different year CHECK_FALSE(ym1 == ym3); // Different month } @@ -140,9 +140,80 @@ namespace Chrono::year_month ym2{Chrono::year(2001), Chrono::January}; Chrono::year_month ym3{Chrono::year(2000), Chrono::February}; - CHECK_FALSE(ym1 != ym1); // Same year/month/day + CHECK_FALSE(ym1 != ym1); // Same year/month CHECK_TRUE(ym1 != ym2); // Different year CHECK_TRUE(ym1 != ym3); // Different month } + + //************************************************************************* + TEST(test_year_month_relational_operators) + { + Chrono::year_month ym1(Chrono::year(2021), Chrono::January); + CHECK_FALSE(ym1 < ym1); // Same year/month + CHECK_TRUE(ym1 <= ym1); + CHECK_FALSE(ym1 > ym1); + CHECK_TRUE(ym1 >= ym1); + + Chrono::year_month ym2(Chrono::year(2026), Chrono::December); + CHECK_TRUE(ym1 < ym2); // left year/month strict less + CHECK_TRUE(ym1 <= ym2); + CHECK_FALSE(ym1 > ym2); + CHECK_FALSE(ym1 >= ym2); + + CHECK_FALSE(ym2 < ym1); // left year/month strict greater + CHECK_FALSE(ym2 <= ym1); + CHECK_TRUE(ym2 > ym1); + CHECK_TRUE(ym2 >= ym1); + } + + //************************************************************************* + TEST(test_year_month_year_month_diff_operator) + { + Chrono::year_month ym1(Chrono::year(2021), Chrono::January); + Chrono::months dms = ym1 - ym1; + CHECK_EQUAL(dms.count(), 0); + Chrono::year_month ym2(Chrono::year(2026), Chrono::December); + dms = ym2 - ym1; // positive + CHECK_EQUAL(dms.count(), (2026 - 2021) * 12 + 11); + dms = ym1 - ym2; // negative + CHECK_EQUAL(dms.count(), (2021 - 2026) * 12 - 11); + } + + //************************************************************************* + TEST(test_year_month_add_sub_months_operators) + { + Chrono::year_month ym1(Chrono::year(2021), Chrono::January); + Chrono::months dms(0); // zero + CHECK_TRUE(dms + ym1 == ym1); + CHECK_TRUE(ym1 + dms == ym1); + CHECK_TRUE(ym1 - dms == ym1); + Chrono::year_month ym2(Chrono::year(2026), Chrono::December); + dms = ym1 - ym2; // negative + CHECK_TRUE(dms + ym2 == ym1); + CHECK_TRUE(ym2 + dms == ym1); + CHECK_TRUE(ym1 - dms == ym2); + dms = ym2 - ym1; // positive + CHECK_TRUE(dms + ym1 == ym2); + CHECK_TRUE(ym1 + dms == ym2); + CHECK_TRUE(ym2 - dms == ym1); + } + + //************************************************************************* + TEST(test_year_month_add_sub_years_operator) + { + Chrono::year_month ym(Chrono::year(2021), Chrono::January); + Chrono::years dys(0); // zero + CHECK_TRUE((ym + dys == Chrono::year_month(ym.year() + dys, ym.month()))); + CHECK_TRUE((dys + ym == Chrono::year_month(ym.year() + dys, ym.month()))); + CHECK_TRUE((ym - dys == Chrono::year_month(ym.year() - dys, ym.month()))); + dys = Chrono::years(-200); // negative + CHECK_TRUE((ym + dys == Chrono::year_month(ym.year() + dys, ym.month()))); + CHECK_TRUE((dys + ym == Chrono::year_month(ym.year() + dys, ym.month()))); + CHECK_TRUE((ym - dys == Chrono::year_month(ym.year() - dys, ym.month()))); + dys = Chrono::years(300); // positive + CHECK_TRUE((ym + dys == Chrono::year_month(ym.year() + dys, ym.month()))); + CHECK_TRUE((dys + ym == Chrono::year_month(ym.year() + dys, ym.month()))); + CHECK_TRUE((ym - dys == Chrono::year_month(ym.year() - dys, ym.month()))); + } } } diff --git a/test/test_chrono_year_month_day.cpp b/test/test_chrono_year_month_day.cpp index a5710e73..ae698465 100644 --- a/test/test_chrono_year_month_day.cpp +++ b/test/test_chrono_year_month_day.cpp @@ -151,7 +151,7 @@ namespace Chrono::year_month_day ymd{Chrono::sys_days(etl::chrono::days(10997))}; Chrono::year_month_day expected{Chrono::year(2000), Chrono::February, Chrono::day(10)}; - CHECK_EQUAL((unsigned)expected.year(), (unsigned)ymd.year()); + CHECK_EQUAL((int)expected.year(), (int)ymd.year()); CHECK_EQUAL((unsigned)expected.month(), (unsigned)ymd.month()); CHECK_EQUAL((unsigned)expected.day(), (unsigned)ymd.day()); } From 226caa30b5c349b1525667807c1e762c5abec9d6 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Fri, 16 Jan 2026 09:47:32 +0100 Subject: [PATCH 077/298] Changed ETL_OR_STD:: to etl:: (#1261) Co-authored-by: John Wellbelove --- include/etl/algorithm.h | 2 +- include/etl/private/ivectorpointer.h | 4 ++-- include/etl/vector.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/etl/algorithm.h b/include/etl/algorithm.h index 88b8f7b6..a5879e2c 100644 --- a/include/etl/algorithm.h +++ b/include/etl/algorithm.h @@ -186,7 +186,7 @@ namespace etl { while (first1 != last1) { - iter_swap(first1, first2); + etl::iter_swap(first1, first2); ++first1; ++first2; } diff --git a/include/etl/private/ivectorpointer.h b/include/etl/private/ivectorpointer.h index f9f6dd7e..597fc8ab 100644 --- a/include/etl/private/ivectorpointer.h +++ b/include/etl/private/ivectorpointer.h @@ -483,7 +483,7 @@ namespace etl ivector& smaller = other.size() > this->size() ? *this : other; ivector& larger = other.size() > this->size() ? other : *this; - ETL_OR_STD::swap_ranges(smaller.begin(), smaller.end(), larger.begin()); + etl::swap_ranges(smaller.begin(), smaller.end(), larger.begin()); typename ivector::iterator larger_itr = etl::next(larger.begin(), smaller.size()); @@ -931,7 +931,7 @@ namespace etl ivector& smaller = other.size() > this->size() ? *this : other; ivector& larger = other.size() > this->size() ? other : *this; - ETL_OR_STD::swap_ranges(smaller.begin(), smaller.end(), larger.begin()); + etl::swap_ranges(smaller.begin(), smaller.end(), larger.begin()); typename ivector::iterator larger_itr = etl::next(larger.begin(), smaller.size()); diff --git a/include/etl/vector.h b/include/etl/vector.h index 92caf40c..db6d7d99 100644 --- a/include/etl/vector.h +++ b/include/etl/vector.h @@ -963,7 +963,7 @@ namespace etl ivector& smaller = other.size() > this->size() ? *this : other; ivector& larger = other.size() > this->size() ? other : *this; - ETL_OR_STD::swap_ranges(smaller.begin(), smaller.end(), larger.begin()); + etl::swap_ranges(smaller.begin(), smaller.end(), larger.begin()); typename ivector::iterator larger_itr = etl::next(larger.begin(), smaller.size()); From 3780070bcf171a20eb382779abf4235c9430c0fa Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Fri, 16 Jan 2026 09:51:11 +0100 Subject: [PATCH 078/298] Suppress warnings from std in optimized builds (#1259) When testing with ./run-tests.sh 23 3 10, some warnings from std surfaced which resulted in build errors. --- include/etl/algorithm.h | 2 ++ include/etl/memory.h | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/etl/algorithm.h b/include/etl/algorithm.h index a5879e2c..74fbb8ed 100644 --- a/include/etl/algorithm.h +++ b/include/etl/algorithm.h @@ -338,7 +338,9 @@ namespace etl template ETL_CONSTEXPR20 TIterator2 move_backward(TIterator1 sb, TIterator1 se, TIterator2 de) { +#include "etl/private/diagnostic_array_bounds_push.h" return std::move_backward(sb, se, de); +#include "etl/private/diagnostic_pop.h" } #elif ETL_USING_CPP11 // For C++11 diff --git a/include/etl/memory.h b/include/etl/memory.h index 57b89879..1c282452 100644 --- a/include/etl/memory.h +++ b/include/etl/memory.h @@ -382,9 +382,13 @@ namespace etl ///\ingroup memory //***************************************************************************** template - TOutputIterator uninitialized_move(TInputIterator i_begin, TInputIterator i_end, TOutputIterator o_begin) + TOutputIterator uninitialized_move(TInputIterator i_begin, TInputIterator i_end, TOutputIterator o_begin) { +#include "etl/private/diagnostic_array_bounds_push.h" +#include "etl/private/diagnostic_stringop_overflow_push.h" return std::uninitialized_move(i_begin, i_end, o_begin); +#include "etl/private/diagnostic_pop.h" +#include "etl/private/diagnostic_pop.h" } //***************************************************************************** @@ -398,7 +402,9 @@ namespace etl { count += int32_t(etl::distance(i_begin, i_end)); +#include "etl/private/diagnostic_array_bounds_push.h" return std::uninitialized_move(i_begin, i_end, o_begin); +#include "etl/private/diagnostic_pop.h" } #else //***************************************************************************** From 3b1ca75ba2cc6aa313d2589f687b44035091bc92 Mon Sep 17 00:00:00 2001 From: Mike Bloom <91038685+mike919192@users.noreply.github.com> Date: Fri, 16 Jan 2026 03:57:09 -0500 Subject: [PATCH 079/298] Add template deduction guide for span from vector (#1264) * Create span from vector deduction * Use ivector for deduction. Add vector_ext to test * Add vector pointer to test * Finish tests * Initialize pdata_ext and others --- include/etl/span.h | 12 +++++ test/test_span_dynamic_extent.cpp | 87 +++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) diff --git a/include/etl/span.h b/include/etl/span.h index c6f18799..8f57148f 100644 --- a/include/etl/span.h +++ b/include/etl/span.h @@ -1258,6 +1258,18 @@ namespace etl span(const etl::array&) -> span; + // Forward declaration of etl::ivector + template + class ivector; + + template + span(etl::ivector&) + -> span; + + template + span(const etl::ivector&) + -> span; + #if ETL_USING_STL && ETL_USING_CPP11 template span(std::array&) diff --git a/test/test_span_dynamic_extent.cpp b/test/test_span_dynamic_extent.cpp index e9045504..7fc1c8c0 100644 --- a/test/test_span_dynamic_extent.cpp +++ b/test/test_span_dynamic_extent.cpp @@ -31,6 +31,7 @@ SOFTWARE. #include "etl/span.h" #include "etl/array.h" #include "etl/unaligned_type.h" +#include "etl/vector.h" #include #include @@ -778,6 +779,92 @@ namespace CHECK((std::is_same_v>)); } + //************************************************************************* + TEST(test_template_deduction_guide_for_etl_vector) + { + const size_t max_size = 10; + const size_t size = 4; + + int buffer1[max_size]; + int buffer2[max_size]; + int * buffer3[max_size]; + int * buffer4[max_size]; + const int * buffer5[max_size]; + const int * buffer6[max_size]; + + etl::vector data(size, 0); + const etl::vector data2(size, 0); + etl::vector_ext data_ext(size, 0, buffer1, max_size); + const etl::vector_ext data2_ext(size, 0, buffer2, max_size); + + etl::span span = data; + etl::span span2 = data2; + etl::span span_ext = data_ext; + etl::span span2_ext = data2_ext; + + CHECK_EQUAL(etl::dynamic_extent, span.extent); + CHECK_EQUAL(ETL_OR_STD17::size(data), span.size()); + CHECK_EQUAL(etl::dynamic_extent, span2.extent); + CHECK_EQUAL(ETL_OR_STD17::size(data2), span2.size()); + CHECK_EQUAL(etl::dynamic_extent, span_ext.extent); + CHECK_EQUAL(ETL_OR_STD17::size(data_ext), span_ext.size()); + CHECK_EQUAL(etl::dynamic_extent, span2_ext.extent); + CHECK_EQUAL(ETL_OR_STD17::size(data2_ext), span2_ext.size()); + + CHECK((std::is_same_v>)); + CHECK((std::is_same_v>)); + CHECK((std::is_same_v>)); + CHECK((std::is_same_v>)); + + etl::vector pdata(size, nullptr); + const etl::vector pdata2(size, nullptr); + etl::vector pdata3(size, nullptr); + const etl::vector pdata4(size, nullptr); + + etl::span pspan = pdata; + etl::span pspan2 = pdata2; + etl::span pspan3 = pdata3; + etl::span pspan4 = pdata4; + + CHECK_EQUAL(etl::dynamic_extent, pspan.extent); + CHECK_EQUAL(ETL_OR_STD17::size(pdata), pspan.size()); + CHECK_EQUAL(etl::dynamic_extent, pspan2.extent); + CHECK_EQUAL(ETL_OR_STD17::size(pdata2), pspan2.size()); + CHECK_EQUAL(etl::dynamic_extent, pspan3.extent); + CHECK_EQUAL(ETL_OR_STD17::size(pdata3), pspan3.size()); + CHECK_EQUAL(etl::dynamic_extent, pspan4.extent); + CHECK_EQUAL(ETL_OR_STD17::size(pdata4), pspan4.size()); + + CHECK((std::is_same_v>)); + CHECK((std::is_same_v>)); + CHECK((std::is_same_v>)); + CHECK((std::is_same_v>)); + + etl::vector_ext pdata_ext(size, nullptr, buffer3, max_size); + const etl::vector_ext pdata2_ext(size, nullptr, buffer4, max_size); + etl::vector_ext pdata3_ext(size, nullptr, buffer5, max_size); + const etl::vector_ext pdata4_ext(size, nullptr, buffer6, max_size); + + etl::span pspan_ext = pdata_ext; + etl::span pspan2_ext = pdata2_ext; + etl::span pspan3_ext = pdata3_ext; + etl::span pspan4_ext = pdata4_ext; + + CHECK_EQUAL(etl::dynamic_extent, pspan_ext.extent); + CHECK_EQUAL(ETL_OR_STD17::size(pdata_ext), pspan_ext.size()); + CHECK_EQUAL(etl::dynamic_extent, pspan2_ext.extent); + CHECK_EQUAL(ETL_OR_STD17::size(pdata2_ext), pspan2_ext.size()); + CHECK_EQUAL(etl::dynamic_extent, pspan3_ext.extent); + CHECK_EQUAL(ETL_OR_STD17::size(pdata3_ext), pspan3_ext.size()); + CHECK_EQUAL(etl::dynamic_extent, pspan4_ext.extent); + CHECK_EQUAL(ETL_OR_STD17::size(pdata4_ext), pspan4_ext.size()); + + CHECK((std::is_same_v>)); + CHECK((std::is_same_v>)); + CHECK((std::is_same_v>)); + CHECK((std::is_same_v>)); + } + //************************************************************************* TEST(test_template_deduction_guide_for_iterators) { From c92dbc2fced059d790b503699b08673128aa8c2c Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Sat, 17 Jan 2026 14:26:16 +0100 Subject: [PATCH 080/298] Document how to implement platform specifics (#1262) Some interfaces need to be implemented in every project or platform using the ETL: * etl_get_high_resolution_clock * etl_get_system_clock * etl_get_steady_clock * etl_putchar Co-authored-by: John Wellbelove --- README.md | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/README.md b/README.md index e9c9da8a..a4c26bdc 100644 --- a/README.md +++ b/README.md @@ -184,6 +184,84 @@ add_executable(foo main.cpp) target_link_libraries(foo PRIVATE etl::etl) ``` +## Profile definition + +When using ETL in a project, there is typically an `etl_profile.h` defined to +adjust ETL to the project needs. ETL will automatically find `etl_profile.h` +if it is available in the include path(s). If it's not available, ETL will +work with default values. + +### Example + +``` +#ifndef __ETL_PROFILE_H__ +#define __ETL_PROFILE_H__ + +#define ETL_TARGET_DEVICE_GENERIC +#define ETL_TARGET_OS_NONE + +#define ETL_NO_STL + +#endif +``` + +## Platform specific implementation + +Although ETL is generally a self-contained header-only library, some interfaces need to be +implemented in every project or platform, at least if those interfaces are actually being +used, due to project specifics: + +| ETL header | Platform specific API to be implemented | Needed when using | +|------------|-----------------------------------------|-------------------------------------| +| `chrono.h` | `etl_get_high_resolution_clock()` | `etl::high_resolution_clock::now()` | +| | `etl_get_system_clock()` | `etl::system_clock::now()` | +| | `etl_get_steady_clock()` | `etl::steady_clock::now()` | +| `print.h` | `etl_putchar()` | `etl::print()` | +| | | `etl::println()` | + +### Example + +``` +#include +#include + +extern "C" +{ + +etl::chrono::high_resolution_clock::rep etl_get_high_resolution_clock() +{ + etl::chrono::high_resolution_clock::rep(static_cast(getSystemTimeNs())); +} + +etl::chrono::system_clock::rep etl_get_system_clock() +{ + return etl::chrono::system_clock::rep(static_cast(getSystemTimeNs())); +} + +etl::chrono::system_clock::rep etl_get_steady_clock() +{ + return etl::chrono::system_clock::rep(static_cast(getSystemTimeNs())); +} + +void etl_putchar(int c) +{ + putByteToStdout(static_cast(c)); +} + +} +``` + +The following default values apply if the respective macros are not defined +(e.g. in `etl_profile.h`): + +| Macro | Default | +|-----------------------------------------------|----------------------------| +| `ETL_CHRONO_SYSTEM_CLOCK_DURATION` | `etl::chrono::nanoseconds` | +| `ETL_CHRONO_SYSTEM_CLOCK_IS_STEADY` | `true` | +| `ETL_CHRONO_HIGH_RESOLUTION_CLOCK_DURATION` | `etl::chrono::nanoseconds` | +| `ETL_CHRONO_HIGH_RESOLUTION_CLOCK_IS_STEADY` | `true` | +| `ETL_CHRONO_STEADY_CLOCK_DURATION` | `etl::chrono::nanoseconds` | + ## Arduino library The content of this repo is available as a library in the Arduino IDE (search for the "Embedded Template Library" in the IDE library manager). The Arduino library repository is available at ```https://github.com/ETLCPP/etl-arduino```, see there for more details. From 55503e0b97dc84087cf8fff6676cb51f6447b81d Mon Sep 17 00:00:00 2001 From: taltenbach <92919739+taltenbach@users.noreply.github.com> Date: Sat, 17 Jan 2026 23:04:52 +0100 Subject: [PATCH 081/298] Fix etl::as_bytes for etl::span (#1266) A missing 'const' in the etl::as_bytes implementation was causing a compile-time error when etl::as_bytes was called on a span of const values. Co-authored-by: John Wellbelove --- include/etl/span.h | 2 +- test/test_span_dynamic_extent.cpp | 3 ++- test/test_span_fixed_extent.cpp | 5 +++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/include/etl/span.h b/include/etl/span.h index 8f57148f..5d03632a 100644 --- a/include/etl/span.h +++ b/include/etl/span.h @@ -1303,7 +1303,7 @@ namespace etl span as_bytes(span s) ETL_NOEXCEPT { - return span(reinterpret_cast(s.data()), s.size_bytes()); + return span(reinterpret_cast(s.data()), s.size_bytes()); } //************************************************************************* diff --git a/test/test_span_dynamic_extent.cpp b/test/test_span_dynamic_extent.cpp index 7fc1c8c0..586eadcb 100644 --- a/test/test_span_dynamic_extent.cpp +++ b/test/test_span_dynamic_extent.cpp @@ -1325,8 +1325,9 @@ namespace TEST(test_convert_span_any_to_span_byte) { float data[2]{3.141592f, 2.71828f }; + const float const_data[2]{3.141592f, 2.71828f }; - auto const const_bytes = etl::as_bytes(etl::span{data}); + auto const const_bytes = etl::as_bytes(etl::span{const_data}); auto const writable_bytes = etl::as_writable_bytes(etl::span{data}); CHECK_EQUAL(const_bytes.size(), sizeof(data)); diff --git a/test/test_span_fixed_extent.cpp b/test/test_span_fixed_extent.cpp index 137bd9b8..a1825c2c 100644 --- a/test/test_span_fixed_extent.cpp +++ b/test/test_span_fixed_extent.cpp @@ -1163,12 +1163,13 @@ namespace TEST(test_convert_span_any_to_span_byte) { float data[2]{3.141592f, 2.71828f}; + const float const_data[2]{3.141592f, 2.71828f}; #if ETL_USING_CPP17 - auto const const_bytes = etl::as_bytes(etl::span{ data }); + auto const const_bytes = etl::as_bytes(etl::span{ const_data }); auto const writable_bytes = etl::as_writable_bytes(etl::span{ data }); #else - auto const const_bytes = etl::as_bytes(etl::span(data)); + auto const const_bytes = etl::as_bytes(etl::span(const_data)); auto const writable_bytes = etl::as_writable_bytes(etl::span(data)); #endif From a1744add1f14c3debc91de370daaa2a51f490c6c Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 20 Jan 2026 10:35:02 +0100 Subject: [PATCH 082/298] Remove AppVeyor build status badge Removed AppVeyor build status badge from README. --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index e9c9da8a..43da4261 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,6 @@ Embedded Template Library (ETL) ![GitHub Repo stars](https://img.shields.io/github/stars/ETLCPP/etl?style=flat) ![CI](https://github.com/ETLCPP/etl/actions/workflows/msvc.yml/badge.svg?branch=master) -[![Build status](https://ci.appveyor.com/api/projects/status/b7jgecv7unqjw4u0/branch/master?svg=true)](https://ci.appveyor.com/project/jwellbelove/etl/branch/master) ![CI](https://github.com/ETLCPP/etl/actions/workflows/gcc-c++11.yml/badge.svg?branch=master) ![CI](https://github.com/ETLCPP/etl/actions/workflows/gcc-c++14.yml/badge.svg?branch=master) From 142dff245ccf0826318815a79a1faf5c1c4daa39 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 20 Jan 2026 10:53:08 +0100 Subject: [PATCH 083/298] Update README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 43da4261..a762e43f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ -Embedded Template Library (ETL) -------------------------- +# ![alt text](https://github.com/ETLCPP/etl/blob/master/images/etl64.png?raw=true) Embedded Template Library (ETL) ![GitHub release (latest by date)](https://img.shields.io/github/v/release/jwellbelove/etl) [![Release date](https://img.shields.io/github/release-date/jwellbelove/etl?color=%231182c3)](https://img.shields.io/github/release-date/jwellbelove/etl?color=%231182c3) From 1b1145ea4eb7928c2866720b86b834ac0f0563e2 Mon Sep 17 00:00:00 2001 From: Bo Rydberg <2945606+bolry@users.noreply.github.com> Date: Tue, 20 Jan 2026 11:15:38 +0100 Subject: [PATCH 084/298] Remove some UB in test_vector_non_trivial.cpp (#1268) Some of the tests' UB are detectable by Gcc15 and thus give a compile error due to warnings-as-error flag. Co-authored-by: John Wellbelove --- test/test_vector_non_trivial.cpp | 41 ++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/test/test_vector_non_trivial.cpp b/test/test_vector_non_trivial.cpp index 1a10ac77..99772202 100644 --- a/test/test_vector_non_trivial.cpp +++ b/test/test_vector_non_trivial.cpp @@ -964,8 +964,9 @@ namespace DataNDC data; data.assign(initial_data.begin(), initial_data.begin() + INITIAL_SIZE); - DataNDC data2; - CHECK_THROW(data.insert(data2.cbegin(), INITIAL_VALUE), etl::vector_out_of_bounds); + DataNDC::iterator it = data.begin(); + --it; + CHECK_THROW(data.insert(it, INITIAL_VALUE), etl::vector_out_of_bounds); } //************************************************************************* @@ -1002,19 +1003,34 @@ namespace const std::string INITIAL_VALUE("1"); DataNDC data; - DataNDC data2; data.assign(initial_data.begin(), initial_data.begin() + INITIAL_SIZE); - CHECK_THROW(data.emplace(data2.cbegin(), INITIAL_VALUE), etl::vector_out_of_bounds); + DataNDC::const_iterator it = data.cend(); + ++it; + CHECK_THROW(data.emplace(it, INITIAL_VALUE), etl::vector_out_of_bounds); } //************************************************************************* - TEST(test_emplace_out_of_range) + TEST(test_emplace_out_of_range_past_end) { DataNDC data; - DataNDC data2; + DataNDC::iterator it = data.end(); + ++it; + const std::string INITIAL_VALUE("1"); - CHECK_THROW(data.emplace(data2.end(), INITIAL_VALUE);, etl::vector_out_of_bounds); + CHECK_THROW(data.emplace(it, INITIAL_VALUE), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST(test_emplace_out_of_range_before_begin) + { + DataNDC data; + DataNDC::iterator it = data.begin(); + --it; + + const std::string INITIAL_VALUE("1"); + + CHECK_THROW(data.emplace(it, INITIAL_VALUE), etl::vector_out_of_bounds); } //************************************************************************* @@ -1072,10 +1088,11 @@ namespace TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) { DataNDC data; - DataNDC data2; + DataNDC::const_iterator it = data.cend(); + ++it; const NDC INITIAL_VALUE("1"); - CHECK_THROW(data.insert(data2.end(), 1, INITIAL_VALUE);, etl::vector_out_of_bounds); + CHECK_THROW(data.insert(it, 1, INITIAL_VALUE), etl::vector_out_of_bounds); } //************************************************************************* @@ -1163,7 +1180,7 @@ namespace DataNDC data; DataNDC data2; - CHECK_THROW(data.insert(data2.end(), insert_data.cbegin(), insert_data.cend());, etl::vector_out_of_bounds); + CHECK_THROW(data.insert(data2.end(), insert_data.cbegin(), insert_data.cend()), etl::vector_out_of_bounds); } //************************************************************************* @@ -1190,7 +1207,7 @@ namespace { DataNDC data(initial_data.begin(), initial_data.end()); - CHECK_THROW(data.erase(data.end());, etl::vector_out_of_bounds); + CHECK_THROW(data.erase(data.end()), etl::vector_out_of_bounds); } //************************************************************************* @@ -1218,7 +1235,7 @@ namespace DataNDC data(initial_data.begin(), initial_data.end()); DataNDC data2(initial_data.begin(), initial_data.end()); - CHECK_THROW(data.erase(data2.begin(), data2.end());, etl::vector_out_of_bounds); + CHECK_THROW(data.erase(data2.begin(), data2.end()), etl::vector_out_of_bounds); } //************************************************************************* From 2c78c3d151e8bc15ef124e9d68215fb94117c1e9 Mon Sep 17 00:00:00 2001 From: Bo Rydberg <2945606+bolry@users.noreply.github.com> Date: Tue, 20 Jan 2026 11:36:14 +0100 Subject: [PATCH 085/298] Update C++26 deprecated constructs to ensure future standard compliance (#1267) * Update C++26 deprecated constructs to ensure future standard compliance I replaced std::is_trivial with a combination of std::is_trivially_default_constructible and std::is_trivially_copyable. Additionally, I added the required comma before the ellipsis in variadic functions to match updated language specifications. * Some additional is_trivial related changes not found directly when compiling tests in C++26 --------- Co-authored-by: John Wellbelove --- include/etl/generators/type_traits_generator.h | 4 ++-- include/etl/type_traits.h | 4 ++-- test/test_successor.cpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/etl/generators/type_traits_generator.h b/include/etl/generators/type_traits_generator.h index 68c937f8..1588544f 100644 --- a/include/etl/generators/type_traits_generator.h +++ b/include/etl/generators/type_traits_generator.h @@ -1227,11 +1227,11 @@ typedef integral_constant true_type; /// is_pod ///\ingroup type_traits template - struct is_pod : std::integral_constant::value && std::is_trivial::value> {}; + struct is_pod : std::integral_constant::value && std::is_trivially_default_constructible::value && std::is_trivially_copyable::value> {}; #if ETL_USING_CPP17 template - inline constexpr bool is_pod_v = std::is_standard_layout_v && std::is_trivial_v; + inline constexpr bool is_pod_v = std::is_standard_layout_v && std::is_trivially_default_constructible_v && std::is_trivially_copyable_v; #endif #if defined(ETL_COMPILER_GCC) diff --git a/include/etl/type_traits.h b/include/etl/type_traits.h index 26cd6aef..524b74eb 100644 --- a/include/etl/type_traits.h +++ b/include/etl/type_traits.h @@ -1215,11 +1215,11 @@ typedef integral_constant true_type; /// is_pod ///\ingroup type_traits template - struct is_pod : std::integral_constant::value && std::is_trivial::value> {}; + struct is_pod : std::integral_constant::value && std::is_trivially_default_constructible::value && std::is_trivially_copyable::value> {}; #if ETL_USING_CPP17 template - inline constexpr bool is_pod_v = std::is_standard_layout_v && std::is_trivial_v; + inline constexpr bool is_pod_v = std::is_standard_layout_v && std::is_trivially_default_constructible_v && std::is_trivially_copyable_v; #endif #if defined(ETL_COMPILER_GCC) diff --git a/test/test_successor.cpp b/test/test_successor.cpp index 2e42c0d1..ebbd1300 100644 --- a/test/test_successor.cpp +++ b/test/test_successor.cpp @@ -39,7 +39,7 @@ namespace { } - SuccessorBase(SuccessorBase& successors...) + SuccessorBase(SuccessorBase& successors, ...) : successor(successors) { } @@ -55,7 +55,7 @@ namespace { } - SuccessorSameBase1(SuccessorBase& successors...) + SuccessorSameBase1(SuccessorBase& successors, ...) : SuccessorBase(successors) , value(0) { From fcd50486ce9e6249acb44f3f23ce878852024fc9 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 21 Jan 2026 09:00:51 +0100 Subject: [PATCH 086/298] Update CONTRIBUTING.md Updated the instructions for contributing. --- CONTRIBUTING.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 693910fe..6231d084 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,13 +1,16 @@ # How to contribute -If your are considering creating a pull request, please observe the following: +Thanks for considering a contribution! Here’s what you need to know before opening a pull request: - If you are adding or modifying a feature, add *new* unit tests that test that feature. - If you are fixing a bug, add a unit test that *fails* before the bug fix is implemented. -- Do not initiate a pull request until all of the units tests pass. -- Branches should be based on the branch `master`. +- Do not initiate a pull request until all of the units tests pass. See below for information on project files and test scripts. +- Branches should be based on the branch `master`. If `development` has pending updates, I’ll rebase the PR against it before pulling.. -There is a project file for VS2022 for C++14, 17, 20, and bash scripts that run the tests for C++11, 14, 17, 20 under Linux with GCC and Clang. +There is a project file for VS2022 for C++14, 17, 20, 23, and bash scripts that run the tests for C++11, 14, 17, 20, 23 under Linux with GCC and Clang. +There are syntax-only check bash scripts that cover C++03, 11, 14, 17, 20, 23 under Linux with GCC and Clang. If you are thinking of adding a new feature then raise this on the GitHub Issues page for discussion as the maintainers and user of the ETL may have questions or suggestions. -It is possible that the maintainer of the ETL or another contributor is already working on the same or a related feature. +It is possible that the maintainer of the ETL or another contributor is already working on the same or a related feature. + +Take a look through our current issues and see if anything sparks your interest! From 2cae4966205e7c01a498afb03bddc4a1bc9a60de Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 21 Jan 2026 09:26:48 +0100 Subject: [PATCH 087/298] Added etl::type_list to etl::observer --- include/etl/observer.h | 14 ++++++ test/test_observer.cpp | 107 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 119 insertions(+), 2 deletions(-) diff --git a/include/etl/observer.h b/include/etl/observer.h index 3e915a59..133f8392 100644 --- a/include/etl/observer.h +++ b/include/etl/observer.h @@ -57,6 +57,7 @@ SOFTWARE. #include "exception.h" #include "error_handler.h" #include "utility.h" +#include "type_list.h" namespace etl { @@ -338,6 +339,19 @@ namespace etl virtual void notification() = 0; }; + //***************************************************************** + /// The observer class for N types. + /// Configured from a type list. + ///\ingroup observer + //***************************************************************** + template + class observer> : public observer + { + public: + + using observer::notification; + }; + #else //********************************************************************* diff --git a/test/test_observer.cpp b/test/test_observer.cpp index bf08e17b..5ae52139 100644 --- a/test/test_observer.cpp +++ b/test/test_observer.cpp @@ -68,12 +68,24 @@ namespace // The Notification2 is passed by reference. // The Notification3 is passed by const reference. //***************************************************************************** - typedef etl::observer ObserverType; + using ObserverType = etl::observer; + +#if !defined(ETL_OBSERVER_FORCE_CPP03_IMPLEMENTATION) + //***************************************************************************** + // The observer base type. + // Declare what notifications you want to observe and how they are passed to 'notification'. + // The Notification1 is passed by value. + // The Notification2 is passed by reference. + // The Notification3 is passed by const reference. + //***************************************************************************** + using NotificationList = etl::type_list; + using ObserverTypeFromTypeList = etl::observer; +#endif //***************************************************************************** // The observer base type that does not take a notification type. //***************************************************************************** - typedef etl::observer ObserverVoidIntType; + using ObserverVoidIntType = etl::observer; } //***************************************************************************** @@ -115,6 +127,29 @@ public: } }; +#if !defined(ETL_OBSERVER_FORCE_CPP03_IMPLEMENTATION) +//***************************************************************************** +// The concrete observable 3 class. +//***************************************************************************** +class Observable3 : public etl::observable +{ +public: + + Notification1 data1; + Notification2 data2; + Notification1& data3 = data1; + + //********************************* + // Notify all of the observers. + //********************************* + void send_notifications() + { + notify_observers(data3); + notify_observers(data2); + } +}; +#endif + //***************************************************************************** // The concrete observable 3 class. //***************************************************************************** @@ -229,6 +264,53 @@ public: int data3_count; }; +#if !defined(ETL_OBSERVER_FORCE_CPP03_IMPLEMENTATION) +//***************************************************************************** +// The third observer type. +// If any one of the overloads is missing or a parameter declaration is incorrect +// then the class will be 'abstract' and will not compile. +//***************************************************************************** +class Observer3 : public ObserverTypeFromTypeList +{ +public: + + Observer3() + : data1_count(0) + , data2_count(0) + , data3_count(0) + { + } + + //******************************************* + // Notification1 is passed by value. + //******************************************* + void notification(Notification1 /*data1*/) + { + ++data1_count; + } + + //******************************************* + // Notification2 is passed by reference. + //******************************************* + void notification(Notification2& /*data2*/) + { + ++data2_count; + } + + //******************************************* + // Notification3 is passed by const reference. + //******************************************* + void notification(const Notification3& /*data3*/) + { + ++data3_count; + } + + int data1_count; + int data2_count; + int data3_count; +}; +#endif + //***************************************************************************** // The third observer type. // If any one of the overloads is missing or a parameter declaration is incorrect @@ -399,6 +481,27 @@ namespace CHECK_EQUAL(3, observer2.data1_count); } +#if !defined(ETL_OBSERVER_FORCE_CPP03_IMPLEMENTATION) + //************************************************************************* + TEST(test_observer_created_from_a_type_list) + { + // The observable objects. + Observable3 observable3; + + // The observer objects. + Observer3 observer3; + + observable3.add_observer(observer3); + + // Send the notifications. + observable3.send_notifications(); // Updates data1 & data2. + + CHECK_EQUAL(1, observer3.data1_count); + CHECK_EQUAL(1, observer3.data2_count); + CHECK_EQUAL(0, observer3.data3_count); + } +#endif + //************************************************************************* TEST(test_8_notifications) { From 2862b3b247abb2727ea6724bd456879e2bfdb111 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 21 Jan 2026 09:50:15 +0100 Subject: [PATCH 088/298] Added etl::type_list to etl::nth_type --- include/etl/nth_type.h | 8 ++++++++ test/test_nth_type.cpp | 11 +++++++++++ 2 files changed, 19 insertions(+) diff --git a/include/etl/nth_type.h b/include/etl/nth_type.h index 01f2a6e8..20c4d2d9 100644 --- a/include/etl/nth_type.h +++ b/include/etl/nth_type.h @@ -31,6 +31,7 @@ SOFTWARE. #include "platform.h" #include "static_assert.h" +#include "type_list.h" #if ETL_USING_CPP11 namespace etl @@ -60,6 +61,13 @@ namespace etl using type = typename private_nth_type::nth_type_helper::type; }; + //*********************************** + template + struct nth_type> : public nth_type + { + using nth_type::type; + }; + //*********************************** template using nth_type_t = typename nth_type::type; diff --git a/test/test_nth_type.cpp b/test/test_nth_type.cpp index a5339292..843d7607 100644 --- a/test/test_nth_type.cpp +++ b/test/test_nth_type.cpp @@ -29,6 +29,7 @@ SOFTWARE. #include "unit_test_framework.h" #include "etl/nth_type.h" +#include "etl/type_list.h" #include namespace @@ -42,5 +43,15 @@ namespace CHECK((std::is_same, long>::value)); CHECK((std::is_same, double>::value)); } + + //************************************************************************* + TEST(test_nth_type_from_type_list) + { + using types = etl::type_list; + + CHECK((std::is_same, int>::value)); + CHECK((std::is_same, long>::value)); + CHECK((std::is_same, double>::value)); + } } } From 01a0b6391957fa31b14d3a1cc8473fe2137ee4f7 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 21 Jan 2026 11:26:14 +0100 Subject: [PATCH 089/298] Added missing 'typename' to type_list nth_type --- include/etl/nth_type.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/etl/nth_type.h b/include/etl/nth_type.h index 20c4d2d9..a38a25f5 100644 --- a/include/etl/nth_type.h +++ b/include/etl/nth_type.h @@ -65,7 +65,7 @@ namespace etl template struct nth_type> : public nth_type { - using nth_type::type; + using typename nth_type::type; }; //*********************************** From b82bf3b79d06d1b211d7fb0775eda4f86466ed1a Mon Sep 17 00:00:00 2001 From: Mike Bloom <91038685+mike919192@users.noreply.github.com> Date: Wed, 21 Jan 2026 13:40:19 -0500 Subject: [PATCH 090/298] Fix return value of get_token_list (#1271) Co-authored-by: John Wellbelove --- include/etl/string_utilities.h | 6 ++--- test/test_string_utilities.cpp | 42 ++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/include/etl/string_utilities.h b/include/etl/string_utilities.h index d20225c9..64e0365e 100644 --- a/include/etl/string_utilities.h +++ b/include/etl/string_utilities.h @@ -782,9 +782,9 @@ namespace etl etl::optional token; size_t count = 0; - while ((count != output.max_size()) && - (count != max_n_tokens) && - (token = etl::get_token(input, delimiters, token, ignore_empty_tokens))) + while ((token = etl::get_token(input, delimiters, token, ignore_empty_tokens)) && + (count != output.max_size()) && + (count != max_n_tokens)) { output.push_back(token.value()); ++count; diff --git a/test/test_string_utilities.cpp b/test/test_string_utilities.cpp index 0f450da3..a5df21ec 100644 --- a/test/test_string_utilities.cpp +++ b/test/test_string_utilities.cpp @@ -1115,6 +1115,48 @@ namespace CHECK_EQUAL(std::string("mat"), std::string(views[5].begin(), views[5].end())); } + //************************************************************************* + //before the issue fix, + //the return value was false when output vector max size equaled the number of tokens + //it should be true + TEST(test_issue_1270_output_vector_max_size_equals_num_tokens) + { + String text(STR(",,,The,cat,sat,,on,the,mat")); + etl::vector views; + + bool all_views_found = etl::get_token_list(text, views, STR(","), true); + + CHECK_TRUE(all_views_found); + CHECK_EQUAL(6, views.size()); + CHECK_EQUAL(std::string("The"), std::string(views[0].begin(), views[0].end())); + CHECK_EQUAL(std::string("cat"), std::string(views[1].begin(), views[1].end())); + CHECK_EQUAL(std::string("sat"), std::string(views[2].begin(), views[2].end())); + CHECK_EQUAL(std::string("on"), std::string(views[3].begin(), views[3].end())); + CHECK_EQUAL(std::string("the"), std::string(views[4].begin(), views[4].end())); + CHECK_EQUAL(std::string("mat"), std::string(views[5].begin(), views[5].end())); + } + + //************************************************************************* + //before the issue fix, + //the return value was false when max number of tokens equaled the number of tokens + //it should be true + TEST(test_issue_1270_max_tokens_equals_num_tokens) + { + String text(STR(",,,The,cat,sat,,on,the,mat")); + VectorOfViews7 views; + + bool all_views_found = etl::get_token_list(text, views, STR(","), true, 6); + + CHECK_TRUE(all_views_found); + CHECK_EQUAL(6, views.size()); + CHECK_EQUAL(std::string("The"), std::string(views[0].begin(), views[0].end())); + CHECK_EQUAL(std::string("cat"), std::string(views[1].begin(), views[1].end())); + CHECK_EQUAL(std::string("sat"), std::string(views[2].begin(), views[2].end())); + CHECK_EQUAL(std::string("on"), std::string(views[3].begin(), views[3].end())); + CHECK_EQUAL(std::string("the"), std::string(views[4].begin(), views[4].end())); + CHECK_EQUAL(std::string("mat"), std::string(views[5].begin(), views[5].end())); + } + //************************************************************************* TEST(test_get_token_list_to_vector_of_string_view_all_but_1_tokens_captured_ignore_empty_tokens) { From f9dc1caa94e67738f512cb9cc5dcf21cc457a2d3 Mon Sep 17 00:00:00 2001 From: Bryton Flecker Date: Wed, 21 Jan 2026 22:30:20 -0600 Subject: [PATCH 091/298] Fix etl::tuple template signature error in pair assignment operator (#1265) * Fix etl::tuple template signature error in pair assignment operator * Remove AppVeyor build status badge Removed AppVeyor build status badge from README. * Update README.md * Update etl::tuple to explicitly use etl::pair or std::pair in assignment operator * Added tests for etl::tuple assignment from pair --------- Co-authored-by: Bryton Flecker Co-authored-by: John Wellbelove --- README.md | 4 +-- include/etl/tuple.h | 20 +++++++-------- test/test_tuple.cpp | 62 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index a4c26bdc..c199268c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ -Embedded Template Library (ETL) -------------------------- +# ![alt text](https://github.com/ETLCPP/etl/blob/master/images/etl64.png?raw=true) Embedded Template Library (ETL) ![GitHub release (latest by date)](https://img.shields.io/github/v/release/jwellbelove/etl) [![Release date](https://img.shields.io/github/release-date/jwellbelove/etl?color=%231182c3)](https://img.shields.io/github/release-date/jwellbelove/etl?color=%231182c3) @@ -10,7 +9,6 @@ Embedded Template Library (ETL) ![GitHub Repo stars](https://img.shields.io/github/stars/ETLCPP/etl?style=flat) ![CI](https://github.com/ETLCPP/etl/actions/workflows/msvc.yml/badge.svg?branch=master) -[![Build status](https://ci.appveyor.com/api/projects/status/b7jgecv7unqjw4u0/branch/master?svg=true)](https://ci.appveyor.com/project/jwellbelove/etl/branch/master) ![CI](https://github.com/ETLCPP/etl/actions/workflows/gcc-c++11.yml/badge.svg?branch=master) ![CI](https://github.com/ETLCPP/etl/actions/workflows/gcc-c++14.yml/badge.svg?branch=master) diff --git a/include/etl/tuple.h b/include/etl/tuple.h index c4a9440b..ffc6db11 100644 --- a/include/etl/tuple.h +++ b/include/etl/tuple.h @@ -559,9 +559,9 @@ namespace etl //********************************* /// Assign from lvalue pair tuple type. //********************************* - template , etl::enable_if_t = 0> + template (), etl::enable_if_t = 0> ETL_CONSTEXPR14 - tuple& operator =(pair& p) + tuple& operator =(ETL_OR_STD::pair& p) { get_value() = p.first; get_base().get_value() = p.second; @@ -572,9 +572,9 @@ namespace etl //********************************* /// Assign from const lvalue pair tuple type. //********************************* - template , etl::enable_if_t = 0> + template (), etl::enable_if_t = 0> ETL_CONSTEXPR14 - tuple& operator =(const pair& p) + tuple& operator =(const ETL_OR_STD::pair& p) { get_value() = p.first; get_base().get_value() = p.second; @@ -585,9 +585,9 @@ namespace etl //********************************* /// Assign from rvalue pair tuple type. //********************************* - template , etl::enable_if_t = 0> + template (), etl::enable_if_t = 0> ETL_CONSTEXPR14 - tuple& operator =(pair&& p) + tuple& operator =(ETL_OR_STD::pair&& p) { get_value() = etl::forward(p.first); get_base().get_value() = etl::forward(p.second); @@ -598,12 +598,12 @@ namespace etl //********************************* /// Assign from const rvalue pair tuple type. //********************************* - template , etl::enable_if_t = 0> + template (), etl::enable_if_t = 0> ETL_CONSTEXPR14 - tuple& operator =(const pair&& p) + tuple& operator =(const ETL_OR_STD::pair&& p) { - get_value() = etl::forward(p.first); - get_base().get_value() = etl::forward(p.second); + get_value() = p.first; + get_base().get_value() = p.second; return *this; } diff --git a/test/test_tuple.cpp b/test/test_tuple.cpp index 01a4ca1f..1a292dcc 100644 --- a/test/test_tuple.cpp +++ b/test/test_tuple.cpp @@ -756,5 +756,67 @@ namespace CHECK_EQUAL(etl::get<2>(tp), s); } #endif + + //************************************************************************* + TEST(test_assign_from_lvalue_pair) + { + ETL_OR_STD::pair p(1, Data("2")); + + etl::tuple tp(0, Data("")); + + tp = p; + + int i = etl::get<0>(tp); + Data d = etl::get<1>(tp); + + CHECK_EQUAL(1, i); + CHECK_EQUAL(std::string("2"), d.value); + } + + //************************************************************************* + TEST(test_assign_from_const_lvalue_pair) + { + const ETL_OR_STD::pair p(1, Data("2")); + + etl::tuple tp(0, Data("")); + + tp = p; + + int i = etl::get<0>(tp); + Data d = etl::get<1>(tp); + + CHECK_EQUAL(1, i); + CHECK_EQUAL(std::string("2"), d.value); + } + + //************************************************************************* + TEST(test_assign_from_rvalue_pair) + { + etl::tuple tp(0, Data("")); + + tp = ETL_OR_STD::pair(1, Data("2")); + + int i = etl::get<0>(tp); + Data d = etl::get<1>(tp); + + CHECK_EQUAL(1, i); + CHECK_EQUAL(std::string("2"), d.value); + } + + //************************************************************************* + TEST(test_assign_from_const_rvalue_pair) + { + const ETL_OR_STD::pair p(1, Data("2")); + + etl::tuple tp(0, Data("")); + + tp = static_cast&&>(p); + + int i = etl::get<0>(tp); + Data d = etl::get<1>(tp); + + CHECK_EQUAL(1, i); + CHECK_EQUAL(std::string("2"), d.value); + } } } From c600605734360f851347e0caa61c81c078886ad9 Mon Sep 17 00:00:00 2001 From: Sergei Date: Thu, 22 Jan 2026 11:22:23 +0200 Subject: [PATCH 092/298] Fix for issue 1276 "Data corruption in the etl::bip_buffer_spsc_atomic" (#1277) * Reproduce data corruption bug in the `etl::bip_buffer_spsc_atomic`. * Fix data corruption bug in the `etl::bip_buffer_spsc_atomic`. --- include/etl/bip_buffer_spsc_atomic.h | 3 + test/test_bip_buffer_spsc_atomic.cpp | 119 +++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) diff --git a/include/etl/bip_buffer_spsc_atomic.h b/include/etl/bip_buffer_spsc_atomic.h index 14d03ca2..9a557eae 100644 --- a/include/etl/bip_buffer_spsc_atomic.h +++ b/include/etl/bip_buffer_spsc_atomic.h @@ -281,6 +281,9 @@ namespace etl else { ETL_ASSERT_OR_RETURN((windex == 0) && ((wsize + 1) <= read_index), ETL_ERROR(bip_buffer_reserve_invalid)); + + // Correct wrapping point + last.store(write_index, etl::memory_order_release); } // Always update write index diff --git a/test/test_bip_buffer_spsc_atomic.cpp b/test/test_bip_buffer_spsc_atomic.cpp index 9711685d..c5f3aec5 100644 --- a/test/test_bip_buffer_spsc_atomic.cpp +++ b/test/test_bip_buffer_spsc_atomic.cpp @@ -28,6 +28,8 @@ SOFTWARE. #include "unit_test_framework.h" +#include +#include #include #include #include @@ -332,6 +334,123 @@ namespace CHECK(stream.empty()); } + //************************************************************************* + TEST(test_optimal_write_issue_1276) + { + etl::bip_buffer_spsc_atomic stream; + etl::ibip_buffer_spsc_atomic& istream = stream; + + // 1. Make all `read`, `write` and `last` in the end of the buffer. + { + const auto writer = istream.write_reserve_optimal(5); + CHECK_EQUAL(5U, writer.size()); + writer[0] = '0'; + writer[1] = '1'; + writer[2] = '2'; + writer[3] = '3'; + writer[4] = '4'; + CHECK_NO_THROW(istream.write_commit(writer)); // [0 1 2 3 4] + const auto reader = istream.read_reserve(); + CHECK_EQUAL(5U, reader.size()); + CHECK_NO_THROW(istream.read_commit(reader)); // * * * * *[] + } + // 2. Write & read 4 bytes. + { + const auto writer = istream.write_reserve_optimal(4); + CHECK_EQUAL(4U, writer.size()); + writer[0] = '5'; + writer[1] = '6'; + writer[2] = '7'; + writer[3] = '8'; + CHECK_NO_THROW(istream.write_commit(writer.subspan(0U, 4U))); // 5 6 7 8] *[ + + const auto reader = istream.read_reserve(); + CHECK_EQUAL(4U, reader.size()); + CHECK_EQUAL('5', reader[0]); + CHECK_EQUAL('6', reader[1]); + CHECK_EQUAL('7', reader[2]); + CHECK_EQUAL('8', reader[3]); + CHECK_NO_THROW(istream.read_commit(reader)); // * * * *[]* + } + // 3. Write and read 2 bytes. + { + const auto writer = istream.write_reserve_optimal(2); + CHECK_EQUAL(3U, writer.size()); + writer[0] = '9'; + writer[1] = 'A'; + CHECK_NO_THROW(istream.write_commit(writer.subspan(0, 2))); // 9 A]* *[* + + const auto reader = istream.read_reserve(); + CHECK_EQUAL(2U, reader.size()); + CHECK_EQUAL('9', reader[0]); + CHECK_EQUAL('A', reader[1]); + } + } + + //************************************************************************* + TEST(test_write_random_back_pressure) + { + // Deliberately seeded with fixed number, so that if it fails then always in the same way. + std::mt19937 mte(123); + + constexpr size_t N = 256; + etl::bip_buffer_spsc_atomic stream; + etl::ibip_buffer_spsc_atomic& istream = stream; + + auto makeRandomNumber = [&mte](const size_t n) -> size_t { return mte() % n; }; + + auto verifyIota = [&](const etl::span& seq) + { + if (!seq.empty()) + { + auto prev = seq[0]; + for (auto i = 1U; i < seq.size(); ++i) + { + const auto curr = seq[i]; + if (prev > curr) + { + CHECK(prev <= curr); + std::cerr << "prev(" << prev << ") should not be bigger than curr(" << curr << ")!\n"; + } + prev = curr; + } + } + }; + + const auto all = istream.write_reserve(N); + CHECK_EQUAL(N, all.size()); + std::fill_n(all.begin(), all.size(), 0); + + int iota = 0; + // Loop writing a bit more than reading. + // 10K iterations is enough to detect 2 failures. + for (int i = 0; i < 10000; ++i) + { + // Write [0...N/16] chunks - on average N/32. + { + const size_t toWrite = makeRandomNumber(N / 16 + 1); + const auto reserve = istream.write_reserve(toWrite); + if (reserve.size() >= toWrite) + { + ++iota; + const auto written = makeRandomNumber(toWrite + 1); + std::fill_n(reserve.begin(), written, iota); + istream.write_commit(reserve.first(written)); + verifyIota(reserve.first(written)); + } + } + + // Read a bit less [0...N/17] chunks - on average N/34. + if (const size_t toRead = makeRandomNumber(N / 17 + 1)) + { + const auto reserve = istream.read_reserve(toRead); + verifyIota(reserve); + const auto read = makeRandomNumber(reserve.size() + 1); + istream.read_commit(reserve.first(read)); + } + } + } + //************************************************************************* #if REALTIME_TEST && defined(ETL_COMPILER_MICROSOFT) #if defined(ETL_TARGET_OS_WINDOWS) // Only Windows priority is currently supported From af1caa88fd1f2da58ed6b6fb67f0a64da7e4f347 Mon Sep 17 00:00:00 2001 From: Sergei Date: Thu, 22 Jan 2026 11:22:23 +0200 Subject: [PATCH 093/298] Fix for issue 1276 "Data corruption in the etl::bip_buffer_spsc_atomic" (#1277) * Reproduce data corruption bug in the `etl::bip_buffer_spsc_atomic`. * Fix data corruption bug in the `etl::bip_buffer_spsc_atomic`. --- include/etl/bip_buffer_spsc_atomic.h | 3 + test/test_bip_buffer_spsc_atomic.cpp | 119 +++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) diff --git a/include/etl/bip_buffer_spsc_atomic.h b/include/etl/bip_buffer_spsc_atomic.h index 14d03ca2..9a557eae 100644 --- a/include/etl/bip_buffer_spsc_atomic.h +++ b/include/etl/bip_buffer_spsc_atomic.h @@ -281,6 +281,9 @@ namespace etl else { ETL_ASSERT_OR_RETURN((windex == 0) && ((wsize + 1) <= read_index), ETL_ERROR(bip_buffer_reserve_invalid)); + + // Correct wrapping point + last.store(write_index, etl::memory_order_release); } // Always update write index diff --git a/test/test_bip_buffer_spsc_atomic.cpp b/test/test_bip_buffer_spsc_atomic.cpp index 9711685d..c5f3aec5 100644 --- a/test/test_bip_buffer_spsc_atomic.cpp +++ b/test/test_bip_buffer_spsc_atomic.cpp @@ -28,6 +28,8 @@ SOFTWARE. #include "unit_test_framework.h" +#include +#include #include #include #include @@ -332,6 +334,123 @@ namespace CHECK(stream.empty()); } + //************************************************************************* + TEST(test_optimal_write_issue_1276) + { + etl::bip_buffer_spsc_atomic stream; + etl::ibip_buffer_spsc_atomic& istream = stream; + + // 1. Make all `read`, `write` and `last` in the end of the buffer. + { + const auto writer = istream.write_reserve_optimal(5); + CHECK_EQUAL(5U, writer.size()); + writer[0] = '0'; + writer[1] = '1'; + writer[2] = '2'; + writer[3] = '3'; + writer[4] = '4'; + CHECK_NO_THROW(istream.write_commit(writer)); // [0 1 2 3 4] + const auto reader = istream.read_reserve(); + CHECK_EQUAL(5U, reader.size()); + CHECK_NO_THROW(istream.read_commit(reader)); // * * * * *[] + } + // 2. Write & read 4 bytes. + { + const auto writer = istream.write_reserve_optimal(4); + CHECK_EQUAL(4U, writer.size()); + writer[0] = '5'; + writer[1] = '6'; + writer[2] = '7'; + writer[3] = '8'; + CHECK_NO_THROW(istream.write_commit(writer.subspan(0U, 4U))); // 5 6 7 8] *[ + + const auto reader = istream.read_reserve(); + CHECK_EQUAL(4U, reader.size()); + CHECK_EQUAL('5', reader[0]); + CHECK_EQUAL('6', reader[1]); + CHECK_EQUAL('7', reader[2]); + CHECK_EQUAL('8', reader[3]); + CHECK_NO_THROW(istream.read_commit(reader)); // * * * *[]* + } + // 3. Write and read 2 bytes. + { + const auto writer = istream.write_reserve_optimal(2); + CHECK_EQUAL(3U, writer.size()); + writer[0] = '9'; + writer[1] = 'A'; + CHECK_NO_THROW(istream.write_commit(writer.subspan(0, 2))); // 9 A]* *[* + + const auto reader = istream.read_reserve(); + CHECK_EQUAL(2U, reader.size()); + CHECK_EQUAL('9', reader[0]); + CHECK_EQUAL('A', reader[1]); + } + } + + //************************************************************************* + TEST(test_write_random_back_pressure) + { + // Deliberately seeded with fixed number, so that if it fails then always in the same way. + std::mt19937 mte(123); + + constexpr size_t N = 256; + etl::bip_buffer_spsc_atomic stream; + etl::ibip_buffer_spsc_atomic& istream = stream; + + auto makeRandomNumber = [&mte](const size_t n) -> size_t { return mte() % n; }; + + auto verifyIota = [&](const etl::span& seq) + { + if (!seq.empty()) + { + auto prev = seq[0]; + for (auto i = 1U; i < seq.size(); ++i) + { + const auto curr = seq[i]; + if (prev > curr) + { + CHECK(prev <= curr); + std::cerr << "prev(" << prev << ") should not be bigger than curr(" << curr << ")!\n"; + } + prev = curr; + } + } + }; + + const auto all = istream.write_reserve(N); + CHECK_EQUAL(N, all.size()); + std::fill_n(all.begin(), all.size(), 0); + + int iota = 0; + // Loop writing a bit more than reading. + // 10K iterations is enough to detect 2 failures. + for (int i = 0; i < 10000; ++i) + { + // Write [0...N/16] chunks - on average N/32. + { + const size_t toWrite = makeRandomNumber(N / 16 + 1); + const auto reserve = istream.write_reserve(toWrite); + if (reserve.size() >= toWrite) + { + ++iota; + const auto written = makeRandomNumber(toWrite + 1); + std::fill_n(reserve.begin(), written, iota); + istream.write_commit(reserve.first(written)); + verifyIota(reserve.first(written)); + } + } + + // Read a bit less [0...N/17] chunks - on average N/34. + if (const size_t toRead = makeRandomNumber(N / 17 + 1)) + { + const auto reserve = istream.read_reserve(toRead); + verifyIota(reserve); + const auto read = makeRandomNumber(reserve.size() + 1); + istream.read_commit(reserve.first(read)); + } + } + } + //************************************************************************* #if REALTIME_TEST && defined(ETL_COMPILER_MICROSOFT) #if defined(ETL_TARGET_OS_WINDOWS) // Only Windows priority is currently supported From 9757860241d6a57e27abd32fab14d0e2d015ec4f Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Fri, 23 Jan 2026 19:33:08 +0100 Subject: [PATCH 094/298] Remove advance() on static spans (#1281) * Remove AppVeyor build status badge Removed AppVeyor build status badge from README. * Update README.md * Update CONTRIBUTING.md Updated the instructions for contributing. * Fix for issue 1276 "Data corruption in the etl::bip_buffer_spsc_atomic" (#1277) * Reproduce data corruption bug in the `etl::bip_buffer_spsc_atomic`. * Fix data corruption bug in the `etl::bip_buffer_spsc_atomic`. * Remove advance() on static spans Since the size of a static span is constant, we can't reasonably advance() on it. --------- Co-authored-by: John Wellbelove Co-authored-by: Sergei --- CONTRIBUTING.md | 13 ++++++++----- include/etl/span.h | 10 ---------- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 693910fe..6231d084 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,13 +1,16 @@ # How to contribute -If your are considering creating a pull request, please observe the following: +Thanks for considering a contribution! Here’s what you need to know before opening a pull request: - If you are adding or modifying a feature, add *new* unit tests that test that feature. - If you are fixing a bug, add a unit test that *fails* before the bug fix is implemented. -- Do not initiate a pull request until all of the units tests pass. -- Branches should be based on the branch `master`. +- Do not initiate a pull request until all of the units tests pass. See below for information on project files and test scripts. +- Branches should be based on the branch `master`. If `development` has pending updates, I’ll rebase the PR against it before pulling.. -There is a project file for VS2022 for C++14, 17, 20, and bash scripts that run the tests for C++11, 14, 17, 20 under Linux with GCC and Clang. +There is a project file for VS2022 for C++14, 17, 20, 23, and bash scripts that run the tests for C++11, 14, 17, 20, 23 under Linux with GCC and Clang. +There are syntax-only check bash scripts that cover C++03, 11, 14, 17, 20, 23 under Linux with GCC and Clang. If you are thinking of adding a new feature then raise this on the GitHub Issues page for discussion as the maintainers and user of the ETL may have questions or suggestions. -It is possible that the maintainer of the ETL or another contributor is already working on the same or a related feature. +It is possible that the maintainer of the ETL or another contributor is already working on the same or a related feature. + +Take a look through our current issues and see if anything sparks your interest! diff --git a/include/etl/span.h b/include/etl/span.h index 5d03632a..c60a9125 100644 --- a/include/etl/span.h +++ b/include/etl/span.h @@ -605,16 +605,6 @@ namespace etl #endif } - //************************************************************************* - /// Moves the pointer to the first element of the span further by a specified number of elements. - ///\tparam elements Number of elements to move forward - //************************************************************************* - void advance(size_t elements) ETL_NOEXCEPT - { - elements = etl::min(elements, size()); - pbegin += elements; - } - //************************************************************************* /// Reinterpret the span as a span with different element type. //************************************************************************* From 682b1e7011c8cd75f988e85eb9be878539f24216 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 25 Jan 2026 11:09:59 +0100 Subject: [PATCH 095/298] Added type_list definitions for nth_type and observer --- include/etl/nth_type.h | 8 +++++--- include/etl/observer.h | 6 ++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/include/etl/nth_type.h b/include/etl/nth_type.h index a38a25f5..82e58ef4 100644 --- a/include/etl/nth_type.h +++ b/include/etl/nth_type.h @@ -58,14 +58,16 @@ namespace etl { ETL_STATIC_ASSERT(Index < sizeof...(TTypes), "etl::nth_type index 'Index' out of bounds"); - using type = typename private_nth_type::nth_type_helper::type; + using type = typename private_nth_type::nth_type_helper::type; + using type_list = etl::type_list; }; //*********************************** template - struct nth_type> : public nth_type + struct nth_type> { - using typename nth_type::type; + using type = typename nth_type::type; + using type_list = typename nth_type::type_list; }; //*********************************** diff --git a/include/etl/observer.h b/include/etl/observer.h index 133f8392..d722262b 100644 --- a/include/etl/observer.h +++ b/include/etl/observer.h @@ -309,6 +309,7 @@ namespace etl using observer::notification; using observer::notification; + using type_list = etl::type_list; }; //***************************************************************** @@ -323,6 +324,8 @@ namespace etl virtual ~observer() = default; virtual void notification(T1) = 0; + + using type_list = etl::type_list; }; //***************************************************************** @@ -337,6 +340,8 @@ namespace etl virtual ~observer() = default; virtual void notification() = 0; + + using type_list = etl::type_list<>; }; //***************************************************************** @@ -350,6 +355,7 @@ namespace etl public: using observer::notification; + using type_list = etl::type_list; }; #else From 61796bee8f7ca5043e36f180bffc97d28b722acd Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 25 Jan 2026 11:10:38 +0100 Subject: [PATCH 096/298] Added etl::type_list to etl::variant --- include/etl/private/variant_variadic.h | 26 +++++++++++++---- test/test_variant_variadic.cpp | 39 ++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/include/etl/private/variant_variadic.h b/include/etl/private/variant_variadic.h index 8ec3f195..9571a2fd 100644 --- a/include/etl/private/variant_variadic.h +++ b/include/etl/private/variant_variadic.h @@ -253,7 +253,7 @@ namespace etl template struct variant_alternative> { - using type = etl::nth_type_t; + using type = etl::nth_type_t::type_list>; }; template @@ -370,7 +370,6 @@ namespace etl //*************************************************************************** /// A template class that can store any of the types defined in the template parameter list. - /// Supports up to 8 types. ///\ingroup variant //*************************************************************************** template @@ -378,6 +377,8 @@ namespace etl { public: + using type_list = etl::type_list; + //*************************************************************************** /// get() is a friend function. //*************************************************************************** @@ -1217,13 +1218,26 @@ namespace etl size_t type_id; }; + //*************************************************************************** + /// Delcare a variant using an etl::type_list. + //*************************************************************************** + template + class variant> : public etl::variant + { + public: + + using base_type = etl::variant; + using type_list = typename base_type::type_list; + using base_type::base_type; // inherit all ctors + }; + //*************************************************************************** /// Checks if the variant v holds the alternative T. //*************************************************************************** template ETL_CONSTEXPR14 bool holds_alternative(const etl::variant& v) ETL_NOEXCEPT - { - constexpr size_t Index = etl::type_list_index_of_type, T>::value; + { + constexpr size_t Index = etl::type_list_index_of_type::type_list, T>::value; return (Index == variant_npos) ? false : (v.index() == Index); } @@ -1254,7 +1268,7 @@ namespace etl get(etl::variant& v) { #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11) - static_assert(Index < sizeof...(TTypes), "Index out of range"); + static_assert(Index < etl::type_list_size::type_list>::value, "Index out of range"); #endif ETL_ASSERT(Index == v.index(), ETL_ERROR(etl::variant_incorrect_type_exception)); @@ -1427,7 +1441,7 @@ namespace etl template struct variant_size> - : etl::integral_constant + : etl::integral_constant::type_list>::value> { }; diff --git a/test/test_variant_variadic.cpp b/test/test_variant_variadic.cpp index dc8373ac..6e91fa34 100644 --- a/test/test_variant_variadic.cpp +++ b/test/test_variant_variadic.cpp @@ -462,6 +462,45 @@ namespace test_variant_t variant_etl; + CHECK_TRUE((std::is_same>::value)); + + CHECK_TRUE(etl::holds_alternative(variant_etl)); + CHECK_FALSE(etl::holds_alternative(variant_etl)); + CHECK_FALSE(etl::holds_alternative(variant_etl)); + CHECK_EQUAL(1, etl::get<0U>(variant_etl).value); + + CHECK_TRUE(etl::holds_alternative<0U>(variant_etl)); + CHECK_FALSE(etl::holds_alternative<1U>(variant_etl)); + CHECK_FALSE(etl::holds_alternative<2U>(variant_etl)); + + CHECK_TRUE(etl::holds_alternative(0U, variant_etl)); + CHECK_FALSE(etl::holds_alternative(1U, variant_etl)); + CHECK_FALSE(etl::holds_alternative(2U, variant_etl)); + CHECK_FALSE(etl::holds_alternative(99U, variant_etl)); + } + + //************************************************************************* + TEST(test_constructor_default_variant_from_type_list) + { + struct DefaultConstructible + { + DefaultConstructible() + : value(1) + { + } + + int value = 0; + }; + + using variant_types = etl::type_list; + using test_variant_t = etl::variant; + + CHECK_NO_THROW(test_variant_t variant_etl); + + test_variant_t variant_etl; + + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE(etl::holds_alternative(variant_etl)); CHECK_FALSE(etl::holds_alternative(variant_etl)); CHECK_FALSE(etl::holds_alternative(variant_etl)); From 1c0d7a87de3ad8084034329eb5c1f26579b20e80 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 25 Jan 2026 19:19:18 +0100 Subject: [PATCH 097/298] Updated comments --- include/etl/private/variant_variadic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/etl/private/variant_variadic.h b/include/etl/private/variant_variadic.h index 9571a2fd..ddcdd33c 100644 --- a/include/etl/private/variant_variadic.h +++ b/include/etl/private/variant_variadic.h @@ -1228,7 +1228,7 @@ namespace etl using base_type = etl::variant; using type_list = typename base_type::type_list; - using base_type::base_type; // inherit all ctors + using base_type::base_type; // Inherit all ctors }; //*************************************************************************** From c67c617d8c7a78aba872e3cbffafeae27c1593f5 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 24 Dec 2025 20:01:38 +0000 Subject: [PATCH 098/298] Addedetl::type~_list to message_router, observer, visitor # Conflicts: # include/etl/observer.h # test/vs2022/etl.vcxproj.filters --- include/etl/message_router.h | 139 +++- include/etl/observer.h | 17 + include/etl/visitor.h | 36 + test/test_message_router_with_type_list.cpp | 741 +++++++++++++++++++ test/test_observer_with_type_list.cpp | 583 +++++++++++++++ test/test_visitor_with_type_list.cpp | 761 ++++++++++++++++++++ test/vs2022/etl.vcxproj | 3 + 7 files changed, 2279 insertions(+), 1 deletion(-) create mode 100644 test/test_message_router_with_type_list.cpp create mode 100644 test/test_observer_with_type_list.cpp create mode 100644 test/test_visitor_with_type_list.cpp diff --git a/include/etl/message_router.h b/include/etl/message_router.h index cc6ea40c..e08c8344 100644 --- a/include/etl/message_router.h +++ b/include/etl/message_router.h @@ -64,6 +64,7 @@ SOFTWARE. #include "placement_new.h" #include "successor.h" #include "type_traits.h" +#include "type_list.h" #include @@ -410,7 +411,8 @@ namespace etl { public: - typedef etl::message_packet message_packet; + using message_packet = etl::message_packet; + using type_list = etl::type_list; //********************************************** message_router() @@ -566,6 +568,10 @@ namespace etl typedef etl::message_packet message_packet; +#if ETL_USING_CPP11 + using type_list = etl::type_list; +#endif + //********************************************** message_router(etl::message_router_id_t id_) : imessage_router(id_) @@ -717,6 +723,10 @@ namespace etl typedef etl::message_packet message_packet; +#if ETL_USING_CPP11 + using type_list = etl::type_list; +#endif + //********************************************** message_router(etl::message_router_id_t id_) : imessage_router(id_) @@ -868,6 +878,10 @@ namespace etl typedef etl::message_packet message_packet; +#if ETL_USING_CPP11 + using type_list = etl::type_list; +#endif + //********************************************** message_router(etl::message_router_id_t id_) : imessage_router(id_) @@ -1018,6 +1032,10 @@ namespace etl typedef etl::message_packet message_packet; +#if ETL_USING_CPP11 + using type_list = etl::type_list; +#endif + //********************************************** message_router(etl::message_router_id_t id_) : imessage_router(id_) @@ -1166,6 +1184,10 @@ namespace etl typedef etl::message_packet message_packet; +#if ETL_USING_CPP11 + using type_list = etl::type_list; +#endif + //********************************************** message_router(etl::message_router_id_t id_) : imessage_router(id_) @@ -1313,6 +1335,10 @@ namespace etl typedef etl::message_packet message_packet; +#if ETL_USING_CPP11 + using type_list = etl::type_list; +#endif + //********************************************** message_router(etl::message_router_id_t id_) : imessage_router(id_) @@ -1459,6 +1485,10 @@ namespace etl typedef etl::message_packet message_packet; +#if ETL_USING_CPP11 + using type_list = etl::type_list; +#endif + //********************************************** message_router(etl::message_router_id_t id_) : imessage_router(id_) @@ -1604,6 +1634,10 @@ namespace etl typedef etl::message_packet message_packet; +#if ETL_USING_CPP11 + using type_list = etl::type_list; +#endif + //********************************************** message_router(etl::message_router_id_t id_) : imessage_router(id_) @@ -1747,6 +1781,10 @@ namespace etl typedef etl::message_packet message_packet; +#if ETL_USING_CPP11 + using type_list = etl::type_list; +#endif + //********************************************** message_router(etl::message_router_id_t id_) : imessage_router(id_) @@ -1889,6 +1927,10 @@ namespace etl typedef etl::message_packet message_packet; +#if ETL_USING_CPP11 + using type_list = etl::type_list; +#endif + //********************************************** message_router(etl::message_router_id_t id_) : imessage_router(id_) @@ -2029,6 +2071,10 @@ namespace etl typedef etl::message_packet message_packet; +#if ETL_USING_CPP11 + using type_list = etl::type_list; +#endif + //********************************************** message_router(etl::message_router_id_t id_) : imessage_router(id_) @@ -2168,6 +2214,10 @@ namespace etl typedef etl::message_packet message_packet; +#if ETL_USING_CPP11 + using type_list = etl::type_list; +#endif + //********************************************** message_router(etl::message_router_id_t id_) : imessage_router(id_) @@ -2305,6 +2355,10 @@ namespace etl typedef etl::message_packet message_packet; +#if ETL_USING_CPP11 + using type_list = etl::type_list; +#endif + //********************************************** message_router(etl::message_router_id_t id_) : imessage_router(id_) @@ -2441,6 +2495,10 @@ namespace etl typedef etl::message_packet message_packet; +#if ETL_USING_CPP11 + using type_list = etl::type_list; +#endif + //********************************************** message_router(etl::message_router_id_t id_) : imessage_router(id_) @@ -2576,6 +2634,10 @@ namespace etl typedef etl::message_packet message_packet; +#if ETL_USING_CPP11 + using type_list = etl::type_list; +#endif + //********************************************** message_router(etl::message_router_id_t id_) : imessage_router(id_) @@ -2710,6 +2772,10 @@ namespace etl typedef etl::message_packet< T1> message_packet; +#if ETL_USING_CPP11 + using type_list = etl::type_list; +#endif + //********************************************** message_router(etl::message_router_id_t id_) : imessage_router(id_) @@ -2830,6 +2896,77 @@ namespace etl return true; } }; + + // Helper: select type at index I from a `type_list`, or `void` if out of range. + template + struct message_router_type_or_void + { + typedef typename etl::conditional<(I < etl::type_list_size::value), + etl::type_list_type_at_index, + etl::type_identity>::type::type type; + }; + + // For C++14 and below, map the `type_list` to up to 16 message type parameters (fill with `void`). + template + class message_router, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void> + : public message_router>::type, + typename etl::message_router_type_or_void<1, etl::type_list>::type, + typename etl::message_router_type_or_void<2, etl::type_list>::type, + typename etl::message_router_type_or_void<3, etl::type_list>::type, + typename etl::message_router_type_or_void<4, etl::type_list>::type, + typename etl::message_router_type_or_void<5, etl::type_list>::type, + typename etl::message_router_type_or_void<6, etl::type_list>::type, + typename etl::message_router_type_or_void<7, etl::type_list>::type, + typename etl::message_router_type_or_void<8, etl::type_list>::type, + typename etl::message_router_type_or_void<9, etl::type_list>::type, + typename etl::message_router_type_or_void<10, etl::type_list>::type, + typename etl::message_router_type_or_void<11, etl::type_list>::type, + typename etl::message_router_type_or_void<12, etl::type_list>::type, + typename etl::message_router_type_or_void<13, etl::type_list>::type, + typename etl::message_router_type_or_void<14, etl::type_list>::type, + typename etl::message_router_type_or_void<15, etl::type_list>::type> + { + // Enforce the maximum number of message types supported by the C++14 implementation. + static_assert(sizeof...(TMessageTypes) <= 16, "etl::message_router supports up to 16 message types for C++14"); + + public: + using base = message_router>::type, + typename etl::message_router_type_or_void<1, etl::type_list>::type, + typename etl::message_router_type_or_void<2, etl::type_list>::type, + typename etl::message_router_type_or_void<3, etl::type_list>::type, + typename etl::message_router_type_or_void<4, etl::type_list>::type, + typename etl::message_router_type_or_void<5, etl::type_list>::type, + typename etl::message_router_type_or_void<6, etl::type_list>::type, + typename etl::message_router_type_or_void<7, etl::type_list>::type, + typename etl::message_router_type_or_void<8, etl::type_list>::type, + typename etl::message_router_type_or_void<9, etl::type_list>::type, + typename etl::message_router_type_or_void<10, etl::type_list>::type, + typename etl::message_router_type_or_void<11, etl::type_list>::type, + typename etl::message_router_type_or_void<12, etl::type_list>::type, + typename etl::message_router_type_or_void<13, etl::type_list>::type, + typename etl::message_router_type_or_void<14, etl::type_list>::type, + typename etl::message_router_type_or_void<15, etl::type_list>::type>; + + using base::base; // Inherit constructors + using typename base::message_packet; + using type_list = etl::type_list; + }; +#endif + +#if ETL_USING_CPP11 && !defined(ETL_MESSAGE_ROUTER_FORCE_CPP03_IMPLEMENTATION) + template + class message_router> + : public message_router + { + public: + + using this_type = message_router>; + using base_type = message_router; + using type_list = etl::type_list; + using base_type::base_type; + }; #endif } diff --git a/include/etl/observer.h b/include/etl/observer.h index d722262b..d7a75776 100644 --- a/include/etl/observer.h +++ b/include/etl/observer.h @@ -321,6 +321,8 @@ namespace etl { public: + using type_list = etl::type_list; + virtual ~observer() = default; virtual void notification(T1) = 0; @@ -337,6 +339,8 @@ namespace etl { public: + using type_list = etl::type_list<>; + virtual ~observer() = default; virtual void notification() = 0; @@ -358,6 +362,19 @@ namespace etl using type_list = etl::type_list; }; + //***************************************************************** + /// The specialised observer class for etl::type_list. + ///\ingroup observer + //**************************************************************** + template + class observer> : public observer + { + public: + + using observer::observer; + using observer::notification; + }; + #else //********************************************************************* diff --git a/include/etl/visitor.h b/include/etl/visitor.h index 2975c678..941af701 100644 --- a/include/etl/visitor.h +++ b/include/etl/visitor.h @@ -33,6 +33,7 @@ SOFTWARE. #include "platform.h" #include "type_traits.h" +#include "type_list.h" //***************************************************************************** ///\defgroup visitor visitor @@ -64,6 +65,7 @@ namespace etl using visitable::accept; using visitable::accept; + using type_list = etl::type_list; }; //***************************************************************** @@ -75,11 +77,30 @@ namespace etl { public: + using type_list = etl::type_list; + virtual ~visitable() = default; virtual void accept(T1&) = 0; }; + //***************************************************************** + /// The visitable class for an etl::type_list. + /// Expands the type_list into the existing variadic visitable. + ///\ingroup visitor + //***************************************************************** + template + class visitable> : public visitable + { + ETL_STATIC_ASSERT(sizeof...(TTypes) != 0, "etl::type_list must not be empty"); + + public: + + using type_list = etl::type_list; + + using visitable::accept; + }; + #else //***************************************************************** @@ -187,6 +208,21 @@ namespace etl virtual void visit(T1) = 0; }; + //***************************************************************** + /// The visitor class for an etl::type_list. + /// Expands the type_list into the existing variadic visitor. + ///\ingroup visitor + //***************************************************************** + template + class visitor> : public visitor + { + ETL_STATIC_ASSERT(sizeof...(TTypes) != 0, "etl::type_list must not be empty"); + + public: + + using visitor::visit; + }; + #else //***************************************************************** diff --git a/test/test_message_router_with_type_list.cpp b/test/test_message_router_with_type_list.cpp new file mode 100644 index 00000000..b997f59f --- /dev/null +++ b/test/test_message_router_with_type_list.cpp @@ -0,0 +1,741 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2017 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "unit_test_framework.h" + +#include "etl/message_router.h" +#include "etl/queue.h" +#include "etl/largest.h" + +//*************************************************************************** +// The set of messages. +//*************************************************************************** +namespace +{ + enum + { + MESSAGE0, + MESSAGE1, + MESSAGE2, + MESSAGE3, + MESSAGE4, + MESSAGE5 + }; + + enum + { + ROUTER1, + ROUTER2, + ROUTER3 + }; + + //*********************************** + struct NotInterface + { + virtual ~NotInterface() {} + virtual int VirtualFunction() const = 0; + }; + + ////*********************************** + // Uncomment to demonstrate static assert + //struct Message0 : public etl::message + //{ + //}; + + //*********************************** + struct Message1 : public etl::message + { + Message1(etl::imessage_router& callback_) + : callback(callback_) + { + } + + etl::imessage_router& callback; + }; + + //*********************************** + struct Message2 : public etl::message + { + Message2(etl::imessage_router& callback_) + : callback(callback_) + { + } + + etl::imessage_router& callback; + }; + + //*********************************** + struct Message3 : public etl::message + { + Message3(etl::imessage_router& callback_) + : callback(callback_) + { + } + + etl::imessage_router& callback; + int value[10]; + }; + + //*********************************** + struct Message4 : public etl::message + { + Message4(etl::imessage_router& callback_) + : callback(callback_) + { + } + + etl::imessage_router& callback; + }; + + //*********************************** + struct Message5 : public etl::message + { + }; + + Message5 message5; + + using Router1Messages = etl::type_list; + using Router2Messages = etl::type_list; + using Router3Messages = etl::type_list; + + //*************************************************************************** + // Router that handles messages 1, 2, 3, 4 and 5 and returns nothing. + //*************************************************************************** + class Router1 : public etl::message_router + { + public: + + Router1() + : message_router(ROUTER1), + message1_count(0), + message2_count(0), + message3_count(0), + message4_count(0), + message_unknown_count(0), + callback_count(0) + { + + } + + void on_receive(const Message1& msg) + { + ++message1_count; + etl::send_message(msg.callback, message5); + //CHECK_EQUAL(1, msg.VirtualFunction()); + } + + void on_receive(const Message2& msg) + { + ++message2_count; + etl::send_message(msg.callback, message5); + } + + void on_receive(const Message3& msg) + { + ++message3_count; + etl::send_message(msg.callback, message5); + } + + void on_receive(const Message4& msg) + { + ++message4_count; + etl::send_message(msg.callback, message5); + } + + void on_receive(const Message5&) + { + ++callback_count; + } + + void on_receive_unknown(const etl::imessage&) + { + ++message_unknown_count; + } + + int message1_count; + int message2_count; + int message3_count; + int message4_count; + int message_unknown_count; + int callback_count; + }; + + //*************************************************************************** + // Router that handles messages 1, 2, 4 and 5 and returns nothing. + //*************************************************************************** + class Router2 : public etl::message_router + { + public: + + Router2() + : message_router(ROUTER2), + message1_count(0), + message2_count(0), + message4_count(0), + message_unknown_count(0), + callback_count(0), + sender_id(0) + { + + } + + Router2(etl::imessage_router& successor_) + : message_router(ROUTER2, successor_), + message1_count(0), + message2_count(0), + message4_count(0), + message_unknown_count(0), + callback_count(0), + sender_id(0) + { + + } + + void on_receive(const Message1& msg) + { + ++message1_count; + sender_id = msg.callback.get_message_router_id(); + etl::send_message(msg.callback, message5); + //CHECK_EQUAL(1, msg.VirtualFunction()); + } + + void on_receive(const Message2& msg) + { + ++message2_count; + sender_id = msg.callback.get_message_router_id(); + etl::send_message(msg.callback, message5); + } + + void on_receive(const Message4& msg) + { + ++message4_count; + sender_id = msg.callback.get_message_router_id(); + etl::send_message(msg.callback, message5); + } + + void on_receive(const Message5&) + { + ++callback_count; + } + + void on_receive_unknown(const etl::imessage&) + { + ++message_unknown_count; + sender_id = 0; + } + + int message1_count; + int message2_count; + int message4_count; + int message_unknown_count; + int callback_count; + int sender_id; + }; + + //*************************************************************************** + // Router that handles messages 1, 2, 3. + // 'receive' is overridden. + //*************************************************************************** + class Router3 : public etl::message_router + { + public: + + using base = etl::message_router; + + Router3() + : message_router(ROUTER3) + , message1_received(false) + , message2_received(false) + , message3_received(false) + , unknown_message_received(false) + { + } + + void receive(const etl::imessage& msg) override + { + switch (msg.get_message_id()) + { + case MESSAGE1: + { + message1_received = true; + break; + } + + case MESSAGE2: + { + message2_received = true; + break; + } + + case MESSAGE3: + { + message3_received = true; + break; + } + + default: + { + unknown_message_received = true; + break; + } + } + } + + void on_receive(const Message1&) + { + } + + void on_receive(const Message2&) + { + } + + void on_receive(const Message3&) + { + } + + void on_receive_unknown(const etl::imessage&) + { + } + + bool message1_received; + bool message2_received; + bool message3_received; + bool unknown_message_received; + }; + + etl::imessage_router* p_router; + + SUITE(test_message_router_with_type_list) + { + //************************************************************************* + TEST(message_router) + { + Router1 r1; + Router2 r2; + + p_router = &r1; + + Message1 message1(r2); + Message2 message2(r2); + Message3 message3(r2); + Message4 message4(r2); + + // CHECK(!r1.is_null_router()); + CHECK(r1.is_producer()); + CHECK(r1.is_consumer()); + + p_router->receive(message1); + CHECK_EQUAL(1, r1.message1_count); + CHECK_EQUAL(0, r1.message2_count); + CHECK_EQUAL(0, r1.message3_count); + CHECK_EQUAL(0, r1.message4_count); + CHECK_EQUAL(0, r1.message_unknown_count); + CHECK_EQUAL(1, r2.callback_count); + + p_router->receive(message2); + CHECK_EQUAL(1, r1.message1_count); + CHECK_EQUAL(1, r1.message2_count); + CHECK_EQUAL(0, r1.message3_count); + CHECK_EQUAL(0, r1.message4_count); + CHECK_EQUAL(0, r1.message_unknown_count); + CHECK_EQUAL(2, r2.callback_count); + + p_router->receive(message3); + CHECK_EQUAL(1, r1.message1_count); + CHECK_EQUAL(1, r1.message2_count); + CHECK_EQUAL(1, r1.message3_count); + CHECK_EQUAL(0, r1.message4_count); + CHECK_EQUAL(0, r1.message_unknown_count); + CHECK_EQUAL(3, r2.callback_count); + + p_router->receive(message4); + CHECK_EQUAL(1, r1.message1_count); + CHECK_EQUAL(1, r1.message2_count); + CHECK_EQUAL(1, r1.message3_count); + CHECK_EQUAL(1, r1.message4_count); + CHECK_EQUAL(0, r1.message_unknown_count); + CHECK_EQUAL(4, r2.callback_count); + } + + //************************************************************************* + TEST(message_null_router) + { + Router2 router; + etl::null_message_router null_router; + + Message1 message1(null_router); + Message2 message2(null_router); + Message3 message3(null_router); + Message4 message4(null_router); + + // CHECK(null_router.is_null_router()); + CHECK(!null_router.is_producer()); + CHECK(!null_router.is_consumer()); + + // Send from the null router. + etl::send_message(router, message1); + CHECK_EQUAL(1, router.message1_count); + CHECK_EQUAL(0, router.message2_count); + CHECK_EQUAL(0, router.message4_count); + CHECK_EQUAL(0, router.message_unknown_count); + + etl::send_message(router, message2); + CHECK_EQUAL(1, router.message1_count); + CHECK_EQUAL(1, router.message2_count); + CHECK_EQUAL(0, router.message4_count); + CHECK_EQUAL(0, router.message_unknown_count); + + etl::send_message(router, message3); + CHECK_EQUAL(1, router.message1_count); + CHECK_EQUAL(1, router.message2_count); + CHECK_EQUAL(0, router.message4_count); + CHECK_EQUAL(1, router.message_unknown_count); + + etl::send_message(router, message4); + CHECK_EQUAL(1, router.message1_count); + CHECK_EQUAL(1, router.message2_count); + CHECK_EQUAL(1, router.message4_count); + CHECK_EQUAL(1, router.message_unknown_count); + + // Send to the null router. + etl::send_message(null_router, message1); + CHECK_EQUAL(1, router.message1_count); + CHECK_EQUAL(1, router.message2_count); + CHECK_EQUAL(1, router.message4_count); + CHECK_EQUAL(1, router.message_unknown_count); + + etl::send_message(null_router, message2); + CHECK_EQUAL(1, router.message1_count); + CHECK_EQUAL(1, router.message2_count); + CHECK_EQUAL(1, router.message4_count); + CHECK_EQUAL(1, router.message_unknown_count); + + etl::send_message(null_router, message3); + CHECK_EQUAL(1, router.message1_count); + CHECK_EQUAL(1, router.message2_count); + CHECK_EQUAL(1, router.message4_count); + CHECK_EQUAL(1, router.message_unknown_count); + + etl::send_message(null_router, message4); + CHECK_EQUAL(1, router.message1_count); + CHECK_EQUAL(1, router.message2_count); + CHECK_EQUAL(1, router.message4_count); + CHECK_EQUAL(1, router.message_unknown_count); + } + + //************************************************************************* + TEST(message_producer) + { + Router2 router; + etl::message_producer producer(ROUTER3); + + Message1 message1(producer); + Message2 message2(producer); + Message3 message3(producer); + Message4 message4(producer); + + // CHECK(!producer.is_null_router()); + CHECK(producer.is_producer()); + CHECK(!producer.is_consumer()); + + CHECK_EQUAL(0, router.sender_id); + + // Send from the producer. + router.receive(message1); + //etl::send_message(router, message1); + CHECK_EQUAL(1, router.message1_count); + CHECK_EQUAL(0, router.message2_count); + CHECK_EQUAL(0, router.message4_count); + CHECK_EQUAL(0, router.message_unknown_count); + CHECK_EQUAL(ROUTER3, router.sender_id); + + etl::send_message(router, message2); + CHECK_EQUAL(1, router.message1_count); + CHECK_EQUAL(1, router.message2_count); + CHECK_EQUAL(0, router.message4_count); + CHECK_EQUAL(0, router.message_unknown_count); + CHECK_EQUAL(ROUTER3, router.sender_id); + + etl::send_message(router, message3); + CHECK_EQUAL(1, router.message1_count); + CHECK_EQUAL(1, router.message2_count); + CHECK_EQUAL(0, router.message4_count); + CHECK_EQUAL(1, router.message_unknown_count); + CHECK_EQUAL(0, router.sender_id); + + etl::send_message(router, message4); + CHECK_EQUAL(1, router.message1_count); + CHECK_EQUAL(1, router.message2_count); + CHECK_EQUAL(1, router.message4_count); + CHECK_EQUAL(1, router.message_unknown_count); + CHECK_EQUAL(ROUTER3, router.sender_id); + + // Send to the producer. + etl::send_message(producer, message1); + CHECK_EQUAL(1, router.message1_count); + CHECK_EQUAL(1, router.message2_count); + CHECK_EQUAL(1, router.message4_count); + CHECK_EQUAL(1, router.message_unknown_count); + + etl::send_message(producer, message2); + CHECK_EQUAL(1, router.message1_count); + CHECK_EQUAL(1, router.message2_count); + CHECK_EQUAL(1, router.message4_count); + CHECK_EQUAL(1, router.message_unknown_count); + + etl::send_message(producer, message3); + CHECK_EQUAL(1, router.message1_count); + CHECK_EQUAL(1, router.message2_count); + CHECK_EQUAL(1, router.message4_count); + CHECK_EQUAL(1, router.message_unknown_count); + + etl::send_message(producer, message4); + CHECK_EQUAL(1, router.message1_count); + CHECK_EQUAL(1, router.message2_count); + CHECK_EQUAL(1, router.message4_count); + CHECK_EQUAL(1, router.message_unknown_count); + } + + //************************************************************************* + TEST(message_router_accepts) + { + Router2 r2; + + etl::null_message_router null_router; + + Message1 message1(null_router); + Message2 message2(null_router); + Message3 message3(null_router); + Message4 message4(null_router); + + CHECK(r2.accepts(message1)); + CHECK(r2.accepts(message1.get_message_id())); + + CHECK(r2.accepts(message2)); + CHECK(r2.accepts(message2.get_message_id())); + + CHECK(!r2.accepts(message3)); + CHECK(!r2.accepts(message3.get_message_id())); + + CHECK(r2.accepts(message4)); + CHECK(r2.accepts(message4.get_message_id())); + + CHECK(r2.accepts(message5)); + CHECK(r2.accepts(message5.get_message_id())); + } + + //************************************************************************* + TEST(message_router_accepts_successors) + { + Router1 r1; // M1, M2, M3, M4, M5 + Router2 r2; // M1, M2, M4, M5 + + r2.set_successor(r1); + + etl::null_message_router null_router; + + Message1 message1(null_router); + Message2 message2(null_router); + Message3 message3(null_router); + Message4 message4(null_router); + + CHECK(r2.accepts(message1)); + CHECK(r2.accepts(message1.get_message_id())); + + CHECK(r2.accepts(message2)); + CHECK(r2.accepts(message2.get_message_id())); + + CHECK(r2.accepts(message3)); + CHECK(r2.accepts(message3.get_message_id())); + + CHECK(r2.accepts(message4)); + CHECK(r2.accepts(message4.get_message_id())); + + CHECK(r2.accepts(message5)); + CHECK(r2.accepts(message5.get_message_id())); + } + +#if ETL_HAS_VIRTUAL_MESSAGES + //************************************************************************* + TEST(message_router_queue) + { + Router1 r1; + Router2 r2; + + typedef Router2::message_packet Packet; + typedef etl::queue Queue; + + Queue queue; + + etl::imessage* im; + + Message1 message1(r1); + Message2 message2(r1); + Message3 message3(r1); + Message4 message4(r1); + + // Queue some messages in the message packet queue. + im = &message1; + queue.emplace(*im); + + im = &message2; + queue.emplace(*im); + + // The router2 queue doesn't accept Message3 types. + im = &message3; + CHECK_THROW(queue.emplace(*im), etl::unhandled_message_exception); + + im = &message4; + queue.emplace(*im); + + im = &message4; + queue.emplace(*im); + + etl::imessage& imr1 = queue.front().get(); + r2.receive(imr1); + CHECK_EQUAL(1, r2.message1_count); + CHECK_EQUAL(0, r2.message2_count); + CHECK_EQUAL(0, r2.message4_count); + CHECK_EQUAL(0, r2.message_unknown_count); + CHECK_EQUAL(1, r1.callback_count); + queue.pop(); + + etl::imessage& imr2 = queue.front().get(); + r2.receive(imr2); + CHECK_EQUAL(1, r2.message1_count); + CHECK_EQUAL(1, r2.message2_count); + CHECK_EQUAL(0, r2.message4_count); + CHECK_EQUAL(0, r2.message_unknown_count); + CHECK_EQUAL(2, r1.callback_count); + queue.pop(); + + const etl::imessage& imr3 = queue.front().get(); + r2.receive(imr3); + CHECK_EQUAL(1, r2.message1_count); + CHECK_EQUAL(1, r2.message2_count); + CHECK_EQUAL(1, r2.message4_count); + CHECK_EQUAL(0, r2.message_unknown_count); + CHECK_EQUAL(3, r1.callback_count); + queue.pop(); + + const Queue& crqueue = queue; + const etl::imessage& imr4 = crqueue.front().get(); + r2.receive(imr4); + CHECK_EQUAL(1, r2.message1_count); + CHECK_EQUAL(1, r2.message2_count); + CHECK_EQUAL(2, r2.message4_count); + CHECK_EQUAL(0, r2.message_unknown_count); + CHECK_EQUAL(4, r1.callback_count); + queue.pop(); + } +#endif + + //************************************************************************* + TEST(message_router_successor) + { + Router1 r1; + Router2 r2(r1); + + etl::null_message_router null_router; + + Message1 message1(r2); + Message2 message2(r2); + Message3 message3(r2); + Message4 message4(r2); + + etl::send_message(r2, message1); + CHECK_EQUAL(1, r2.message1_count); + CHECK_EQUAL(0, r2.message2_count); + CHECK_EQUAL(0, r2.message4_count); + CHECK_EQUAL(0, r2.message_unknown_count); + + CHECK_EQUAL(0, r1.message1_count); + CHECK_EQUAL(0, r1.message2_count); + CHECK_EQUAL(0, r1.message3_count); + CHECK_EQUAL(0, r1.message4_count); + CHECK_EQUAL(0, r1.message_unknown_count); + + etl::send_message(r2, message2); + CHECK_EQUAL(1, r2.message1_count); + CHECK_EQUAL(1, r2.message2_count); + CHECK_EQUAL(0, r2.message4_count); + CHECK_EQUAL(0, r2.message_unknown_count); + + CHECK_EQUAL(0, r1.message1_count); + CHECK_EQUAL(0, r1.message2_count); + CHECK_EQUAL(0, r1.message3_count); + CHECK_EQUAL(0, r1.message4_count); + CHECK_EQUAL(0, r1.message_unknown_count); + + r2.receive(message3); + CHECK_EQUAL(1, r2.message1_count); + CHECK_EQUAL(1, r2.message2_count); + CHECK_EQUAL(0, r2.message4_count); + CHECK_EQUAL(0, r2.message_unknown_count); + + CHECK_EQUAL(0, r1.message1_count); + CHECK_EQUAL(0, r1.message2_count); + CHECK_EQUAL(1, r1.message3_count); + CHECK_EQUAL(0, r1.message4_count); + CHECK_EQUAL(0, r1.message_unknown_count); + + etl::send_message(r2, message4); + CHECK_EQUAL(1, r2.message1_count); + CHECK_EQUAL(1, r2.message2_count); + CHECK_EQUAL(1, r2.message4_count); + CHECK_EQUAL(0, r2.message_unknown_count); + + CHECK_EQUAL(0, r1.message1_count); + CHECK_EQUAL(0, r1.message2_count); + CHECK_EQUAL(1, r1.message3_count); + CHECK_EQUAL(0, r1.message4_count); + CHECK_EQUAL(0, r1.message_unknown_count); + } + + //************************************************************************* + TEST(message_router_with_overloaded_receive) + { + Router3 router; + + Message1 message1(router); + Message2 message2(router); + Message3 message3(router); + + router.receive(message1); + CHECK_TRUE(router.message1_received); + + router.receive(message2); + CHECK_TRUE(router.message2_received); + + router.receive(message3); + CHECK_TRUE(router.message3_received); + + CHECK_FALSE(router.unknown_message_received); + } + } +} diff --git a/test/test_observer_with_type_list.cpp b/test/test_observer_with_type_list.cpp new file mode 100644 index 00000000..e0b61f54 --- /dev/null +++ b/test/test_observer_with_type_list.cpp @@ -0,0 +1,583 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "unit_test_framework.h" + +#include "etl/observer.h" +#include "etl/type_list.h" + +#if ETL_USING_CPP11 && !defined(ETL_VISITOR_FORCE_CPP03_IMPLEMENTATION) + +namespace +{ + //***************************************************************************** + // Notification1 + //***************************************************************************** + struct Notification1 + { + }; + + //***************************************************************************** + // Notification2 + //***************************************************************************** + struct Notification2 + { + }; + + //***************************************************************************** + // Notification3 + //***************************************************************************** + struct Notification3 + { + }; + + //***************************************************************************** + // Generic notification. + //***************************************************************************** + template + struct Notification + { + }; + + //***************************************************************************** + // The observer base type. + // Declare what notifications you want to observe and how they are passed to 'notification'. + // The Notification1 is passed by value. + // The Notification2 is passed by reference. + // The Notification3 is passed by const reference. + //***************************************************************************** + using NotificationTypes = etl::type_list; + using ObserverType = etl::observer; + + //***************************************************************************** + // The observer base type that does not take a notification type. + //***************************************************************************** + typedef etl::observer ObserverVoidIntType; +} + +//***************************************************************************** +// The concrete observable 1 class. +//***************************************************************************** +class Observable1 : public etl::observable +{ +public: + + Notification1 data1; + Notification2 data2; + Notification1& data3 = data1; + + //********************************* + // Notify all of the observers. + //********************************* + void send_notifications() + { + notify_observers(data3); + notify_observers(data2); + } +}; + +//***************************************************************************** +// The concrete observable 2 class. +//***************************************************************************** +class Observable2 : public etl::observable +{ +public: + + Notification3 data3; + + //********************************* + // Notify all of the observers. + //********************************* + void send_notifications() + { + notify_observers(data3); + } +}; + +//***************************************************************************** +// The concrete observable 3 class. +//***************************************************************************** +class ObservableVoidInt : public etl::observable +{ +public: + + //********************************* + // Notify all of the observers. + //********************************* + void send_notifications() + { + notify_observers(); + } + + //********************************* + // Notify all of the observers. + //********************************* + void send_notifications(int n) + { + notify_observers(n); + } +}; + +//***************************************************************************** +// The first observer type. +// If any one of the overloads is missing or a parameter declaration is incorrect +// then the class will be 'abstract' and will not compile. +//***************************************************************************** +class Observer1 : public ObserverType +{ +public: + + Observer1() + : data1_count(0) + , data2_count(0) + , data3_count(0) + { + } + + //******************************************* + // Notification1 is passed by value. + //******************************************* + void notification(Notification1 /*data1*/) + { + ++data1_count; + } + + //******************************************* + // Notification2 is passed by reference. + //******************************************* + void notification(Notification2& /*data2*/) + { + ++data2_count; + } + + //******************************************* + // Notification3 is passed by const reference. + //******************************************* + void notification(const Notification3& /*data3*/) + { + ++data3_count; + } + + int data1_count; + int data2_count; + int data3_count; +}; + +//***************************************************************************** +// The second observer type. +// If any one of the overloads is missing or a parameter declaration is incorrect +// then the class will be 'abstract' and will not compile. +//***************************************************************************** +class Observer2 : public ObserverType +{ +public: + + Observer2() + : data1_count(0) + , data2_count(0) + , data3_count(0) + { + } + + //******************************************* + // Notification1 is passed by value. + //******************************************* + void notification(Notification1 /*data1*/) + { + ++data1_count; + } + + //******************************************* + // Notification2 is passed by reference. + //******************************************* + void notification(Notification2& /*data2*/) + { + ++data2_count; + } + + //******************************************* + // Notification3 is passed by const reference. + //******************************************* + void notification(const Notification3& /*data3*/) + { + ++data3_count; + } + + int data1_count; + int data2_count; + int data3_count; +}; + +//***************************************************************************** +// The third observer type. +// If any one of the overloads is missing or a parameter declaration is incorrect +// then the class will be 'abstract' and will not compile. +//***************************************************************************** +class ObserverVoidInt : public ObserverVoidIntType +{ +public: + + ObserverVoidInt() + : data1_count(0) + , data2_count(0) + { + } + + //******************************************* + // Notification1 + //******************************************* + void notification() override + { + ++data1_count; + } + + //******************************************* + // Notification2 + //******************************************* + void notification(int) override + { + ++data2_count; + } + + int data1_count; + int data2_count; +}; + +namespace +{ + SUITE(test_observer) + { + //************************************************************************* + TEST(test_2_observables_2_observers_3_notifications) + { + // The observable objects. + Observable1 observable1; + Observable2 observable2; + + // The observer objects. + Observer1 observer1; + Observer2 observer2; + + observable1.add_observer(observer1); + + // Send the notifications. + observable1.send_notifications(); // Updates data1 & data2. + + CHECK_EQUAL(1, observer1.data1_count); + CHECK_EQUAL(1, observer1.data2_count); + CHECK_EQUAL(0, observer1.data3_count); + + CHECK_EQUAL(0, observer2.data1_count); + CHECK_EQUAL(0, observer2.data2_count); + CHECK_EQUAL(0, observer2.data3_count); + + observable2.send_notifications(); // Updates data3. observeable2 has no observers yet. + + CHECK_EQUAL(1, observer1.data1_count); + CHECK_EQUAL(1, observer1.data2_count); + CHECK_EQUAL(0, observer1.data3_count); + + CHECK_EQUAL(0, observer2.data1_count); + CHECK_EQUAL(0, observer2.data2_count); + CHECK_EQUAL(0, observer2.data3_count); + + // Add an observer to both. + observable1.add_observer(observer2); + observable2.add_observer(observer2); + + // Send the notifications. + observable1.send_notifications(); // Updates data1 & data2. + + CHECK_EQUAL(2, observer1.data1_count); + CHECK_EQUAL(2, observer1.data2_count); + CHECK_EQUAL(0, observer1.data3_count); + + CHECK_EQUAL(1, observer2.data1_count); + CHECK_EQUAL(1, observer2.data2_count); + CHECK_EQUAL(0, observer2.data3_count); + + observable2.send_notifications(); // Updates data3. + + CHECK_EQUAL(2, observer1.data1_count); + CHECK_EQUAL(2, observer1.data2_count); + CHECK_EQUAL(0, observer1.data3_count); + + CHECK_EQUAL(1, observer2.data1_count); + CHECK_EQUAL(1, observer2.data2_count); + CHECK_EQUAL(1, observer2.data3_count); + + observable1.remove_observer(observer1); + + // Send the notifications. + observable1.send_notifications(); // Updates data1 & data2. + + CHECK_EQUAL(2, observer1.data1_count); + CHECK_EQUAL(2, observer1.data2_count); + CHECK_EQUAL(0, observer1.data3_count); + + CHECK_EQUAL(2, observer2.data1_count); + CHECK_EQUAL(2, observer2.data2_count); + CHECK_EQUAL(1, observer2.data3_count); + + observable2.send_notifications(); // Updates data3. + + CHECK_EQUAL(2, observer1.data1_count); + CHECK_EQUAL(2, observer1.data2_count); + CHECK_EQUAL(0, observer1.data3_count); + + CHECK_EQUAL(2, observer2.data1_count); + CHECK_EQUAL(2, observer2.data2_count); + CHECK_EQUAL(2, observer2.data3_count); + } + + //************************************************************************* + TEST(test_observable_2_observers_enable_disable) + { + // The observable objects. + Observable1 observable1; + + // The observer objects. + Observer1 observer1; + Observer2 observer2; + + observable1.add_observer(observer1); + observable1.add_observer(observer2); + + // Send the notifications. + observable1.send_notifications(); + + CHECK_EQUAL(1, observer1.data1_count); + CHECK_EQUAL(1, observer2.data1_count); + + // Disable observer1. Send the notifications. + observable1.disable_observer(observer1); + observable1.send_notifications(); + + CHECK_EQUAL(1, observer1.data1_count); + CHECK_EQUAL(2, observer2.data1_count); + + // Disable observer2. Send the notifications. + observable1.enable_observer(observer2, false); + observable1.send_notifications(); + + CHECK_EQUAL(1, observer1.data1_count); + CHECK_EQUAL(2, observer2.data1_count); + + // Enable observer1. Send the notifications. + observable1.enable_observer(observer1); + observable1.send_notifications(); + + CHECK_EQUAL(2, observer1.data1_count); + CHECK_EQUAL(2, observer2.data1_count); + + // Enable observer2. Send the notifications. + observable1.enable_observer(observer2, true); + observable1.send_notifications(); + + CHECK_EQUAL(3, observer1.data1_count); + CHECK_EQUAL(3, observer2.data1_count); + } + + //************************************************************************* + TEST(test_8_notifications) + { + typedef etl::observer, Notification<2>, Notification<3>, Notification<4>, Notification<5>, Notification<6>, Notification<7>, Notification<8> > Observer; + + class Observable : public etl::observable + { + }; + + // This test just needs to compile without errors. + CHECK(true); + } + + //************************************************************************* + TEST(test_7_notifications) + { + typedef etl::observer, Notification<2>, Notification<3>, Notification<4>, Notification<5>, Notification<6>, Notification<7> > Observer; + + class Observable : public etl::observable + { + }; + + // This test just needs to compile without errors. + CHECK(true); + } + + //************************************************************************* + TEST(test_6_notifications) + { + typedef etl::observer, Notification<2>, Notification<3>, Notification<4>, Notification<5>, Notification<6> > Observer; + + class Observable : public etl::observable + { + }; + + // This test just needs to compile without errors. + CHECK(true); + } + + //************************************************************************* + TEST(test_5_notifications) + { + typedef etl::observer, Notification<2>, Notification<3>, Notification<4>, Notification<5> > Observer; + + class Observable : public etl::observable + { + }; + + // This test just needs to compile without errors. + CHECK(true); + } + + //************************************************************************* + TEST(test_4_notifications) + { + typedef etl::observer, Notification<2>, Notification<3>, Notification<4> > Observer; + + class Observable : public etl::observable + { + }; + + // This test just needs to compile without errors. + CHECK(true); + } + + //************************************************************************* + TEST(test_3_notifications) + { + typedef etl::observer, Notification<2>, Notification<3> > Observer; + + class Observable : public etl::observable + { + }; + + // This test just needs to compile without errors. + CHECK(true); + } + + //************************************************************************* + TEST(test_2_notifications) + { + typedef etl::observer, Notification<2> > Observer; + + class Observable : public etl::observable + { + }; + + // This test just needs to compile without errors. + CHECK(true); + } + + //************************************************************************* + TEST(test_1_notification) + { + typedef etl::observer > Observer; + + class Observable : public etl::observable + { + }; + + // This test just needs to compile without errors. + CHECK(true); + } + + //************************************************************************* + TEST(test_observer_list) + { + class Observer : public etl::observer + { + void notification(Notification1) {} + }; + + class Observable : public etl::observable + { + }; + + Observable observable; + + Observer observer1; + Observer observer2; + Observer observer3; + Observer observer4; + Observer observer5; + + observable.add_observer(observer1); + CHECK_EQUAL(1UL, observable.number_of_observers()); + + observable.add_observer(observer2); + CHECK_EQUAL(2UL, observable.number_of_observers()); + + observable.add_observer(observer3); + CHECK_EQUAL(3UL, observable.number_of_observers()); + + observable.add_observer(observer2); + CHECK_EQUAL(3UL, observable.number_of_observers()); + + observable.add_observer(observer4); + CHECK_EQUAL(4UL, observable.number_of_observers()); + + CHECK_THROW(observable.add_observer(observer5), etl::observer_list_full); + + CHECK(observable.remove_observer(observer3)); + CHECK_EQUAL(3UL, observable.number_of_observers()); + + // Try again. + CHECK(!observable.remove_observer(observer3)); + CHECK_EQUAL(3UL, observable.number_of_observers()); + + observable.clear_observers(); + CHECK_EQUAL(0UL, observable.number_of_observers()); + } + + //************************************************************************* + TEST(test_void_int_observable) + { + // The observable objects. + ObservableVoidInt observable; + + // The observer objects. + ObserverVoidInt observer; + + observable.add_observer(observer); + + // Send the notifications. + observable.send_notifications(); + CHECK_EQUAL(1U, observer.data1_count); + CHECK_EQUAL(0U, observer.data2_count); + + observable.send_notifications(1); + CHECK_EQUAL(1U, observer.data1_count); + CHECK_EQUAL(1U, observer.data2_count); + } + } +} + + +#endif + diff --git a/test/test_visitor_with_type_list.cpp b/test/test_visitor_with_type_list.cpp new file mode 100644 index 00000000..04660ee9 --- /dev/null +++ b/test/test_visitor_with_type_list.cpp @@ -0,0 +1,761 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "unit_test_framework.h" + +#include "etl/visitor.h" + +#if ETL_USING_CPP11 && !defined(ETL_VISITOR_FORCE_CPP03_IMPLEMENTATION) + +//***************************************************************************** +// Pre-declare the data types. +//***************************************************************************** +class Square; +class Circle; +class Triangle; + +//***************************************************************************** +// What classes do you want the visitors to handle? +// Square will be passed by reference. +// Circle will be passed by reference. +// Triangle will be passed by const reference. +//***************************************************************************** +using DrawTypes = etl::type_list; +using DrawVisitorType = etl::visitor; + +//***************************************************************************** +// What classes do you want the visitors to handle? +// Square will be passed by reference. +// Triangle will be passed by const reference. +//***************************************************************************** +using LogTypes = etl::type_list; +using LogVisitorType = etl::visitor; + +//***************************************************************************** +// Base shape. +//***************************************************************************** +using VisitorTypes = etl::type_list; + +class ShapeBase : public etl::visitable +{ +}; + +//***************************************************************************** +// Square accepts draw & log visitors. +//***************************************************************************** +class Square : public ShapeBase +{ +public: + + void accept(DrawVisitorType& visitor) + { + visitor.visit(*this); + } + + void accept(LogVisitorType& visitor) + { + visitor.visit(*this); + } +}; + +//***************************************************************************** +// Circle only accepts draw visitors. +//***************************************************************************** +class Circle : public ShapeBase +{ +public: + + void accept(DrawVisitorType& visitor) + { + visitor.visit(*this); + } + + void accept(LogVisitorType&) + { + } +}; + +//***************************************************************************** +// Triangle accepts draw & log visitors. +//***************************************************************************** +class Triangle : public ShapeBase +{ +public: + + void accept(DrawVisitorType& visitor) + { + visitor.visit(*this); + } + + void accept(LogVisitorType& visitor) + { + visitor.visit(*this); + } +}; + + +//***************************************************************************** +// Generic other shapes. +//***************************************************************************** +template +class Shape : public etl::visitable +{ +public: + + void accept(TVisitor& visitor) + { + visitor.visit(*this); + } +}; + +//***************************************************************************** +class DrawVisitor : public DrawVisitorType +{ +public: + + DrawVisitor() + : square_called(false), + circle_called(false), + triangle_called(false) + { + } + + void visit(Square&) + { + square_called = true; + } + + void visit(Circle&) + { + circle_called = true; + } + + void visit(const Triangle&) + { + triangle_called = true; + } + + bool square_called; + bool circle_called; + bool triangle_called; +}; + +//***************************************************************************** +class LogVisitor : public LogVisitorType +{ +public: + + LogVisitor() + : square_called(false), + circle_called(false), + triangle_called(false) + { + } + + void visit(Square&) + { + square_called = true; + } + + // SHOULD NEVER BE CALLED. + void visit(Circle&) + { + circle_called = true; + } + + void visit(const Triangle&) + { + triangle_called = true; + } + + bool square_called; + bool circle_called; + bool triangle_called; +}; + +namespace +{ + SUITE(test_visitor) + { + //************************************************************************* + TEST(test_two_visitors_three_visitables) + { + DrawVisitor draw_visitor; + LogVisitor log_visitor; + + Square square; + Circle circle; + Triangle triangle; + + ShapeBase* pShapeBase; + + CHECK_EQUAL(false, draw_visitor.square_called); + CHECK_EQUAL(false, draw_visitor.circle_called); + CHECK_EQUAL(false, draw_visitor.triangle_called); + CHECK_EQUAL(false, log_visitor.square_called); + CHECK_EQUAL(false, log_visitor.circle_called); + CHECK_EQUAL(false, log_visitor.triangle_called); + + square.accept(draw_visitor); + square.accept(log_visitor); + + CHECK_EQUAL(true, draw_visitor.square_called); + CHECK_EQUAL(false, draw_visitor.circle_called); + CHECK_EQUAL(false, draw_visitor.triangle_called); + CHECK_EQUAL(true, log_visitor.square_called); + CHECK_EQUAL(false, log_visitor.circle_called); + CHECK_EQUAL(false, log_visitor.triangle_called); + + circle.accept(draw_visitor); + + CHECK_EQUAL(true, draw_visitor.square_called); + CHECK_EQUAL(true, draw_visitor.circle_called); + CHECK_EQUAL(false, draw_visitor.triangle_called); + CHECK_EQUAL(true, log_visitor.square_called); + CHECK_EQUAL(false, log_visitor.circle_called); + CHECK_EQUAL(false, log_visitor.triangle_called); + + pShapeBase = ▵ + pShapeBase->accept(draw_visitor); + pShapeBase->accept(log_visitor); + + CHECK_EQUAL(true, draw_visitor.square_called); + CHECK_EQUAL(true, draw_visitor.circle_called); + CHECK_EQUAL(true, draw_visitor.triangle_called); + CHECK_EQUAL(true, log_visitor.square_called); + CHECK_EQUAL(false, log_visitor.circle_called); + CHECK_EQUAL(true, log_visitor.triangle_called); + } + + //************************************************************************* + TEST(test_1_visitor) + { + class AShape; + class ShapeVisitor1 : public etl::visitor + { + void visit(AShape&) {} + }; + + class AShape : public etl::visitable + { + public: + + void accept(ShapeVisitor1&) {} + }; + + // This test just needs to compile without errors. + CHECK(true); + } + + //************************************************************************* + TEST(test_2_visitor) + { + class AShape; + class ShapeVisitor1 : public etl::visitor + { + void visit(AShape&) {} + }; + + class ShapeVisitor2 : public etl::visitor + { + void visit(AShape&) {} + }; + + class AShape : public etl::visitable + { + public: + + void accept(ShapeVisitor1&) {} + void accept(ShapeVisitor2&) {} + }; + + // This test just needs to compile without errors. + CHECK(true); + } + + //************************************************************************* + TEST(test_3_visitor) + { + class AShape; + class ShapeVisitor1 : public etl::visitor + { + void visit(AShape&) {} + }; + + class ShapeVisitor2 : public etl::visitor + { + void visit(AShape&) {} + }; + + class ShapeVisitor3 : public etl::visitor + { + void visit(AShape&) {} + }; + + class AShape : public etl::visitable + { + public: + + void accept(ShapeVisitor1&) {} + void accept(ShapeVisitor2&) {} + void accept(ShapeVisitor3&) {} + }; + + // This test just needs to compile without errors. + CHECK(true); + } + + //************************************************************************* + TEST(test_4_visitor) + { + class AShape; + class ShapeVisitor1 : public etl::visitor + { + void visit(AShape&) {} + }; + + class ShapeVisitor2 : public etl::visitor + { + void visit(AShape&) {} + }; + + class ShapeVisitor3 : public etl::visitor + { + void visit(AShape&) {} + }; + + class ShapeVisitor4 : public etl::visitor + { + void visit(AShape&) {} + }; + + using ShapeVisitorTypes = etl::type_list; + + class AShape : public etl::visitable + { + public: + + void accept(ShapeVisitor1&) {} + void accept(ShapeVisitor2&) {} + void accept(ShapeVisitor3&) {} + void accept(ShapeVisitor4&) {} + }; + + // This test just needs to compile without errors. + CHECK(true); + } + + //************************************************************************* + TEST(test_1_visitable) + { + class ShapeVisitor : public etl::visitor > + { + public: + + void visit(Shape<1, ShapeVisitor>) {} + }; + + // This test just needs to compile without errors. + CHECK(true); + } + + //************************************************************************* + TEST(test_2_visitable) + { + class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor> > + { + public: + + void visit(Shape<1, ShapeVisitor>) {} + void visit(Shape<2, ShapeVisitor>) {} + }; + + // This test just needs to compile without errors. + CHECK(true); + } + + //************************************************************************* + TEST(test_3_visitable) + { + class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor>, Shape<3, ShapeVisitor> > + { + public: + + void visit(Shape<1, ShapeVisitor>) {} + void visit(Shape<2, ShapeVisitor>) {} + void visit(Shape<3, ShapeVisitor>) {} + }; + + // This test just needs to compile without errors. + CHECK(true); + } + + //************************************************************************* + TEST(test_4_visitable) + { + class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor>, Shape<3, ShapeVisitor>, Shape<4, ShapeVisitor> > + { + public: + + void visit(Shape<1, ShapeVisitor>) {} + void visit(Shape<2, ShapeVisitor>) {} + void visit(Shape<3, ShapeVisitor>) {} + void visit(Shape<4, ShapeVisitor>) {} + }; + + // This test just needs to compile without errors. + CHECK(true); + } + + //************************************************************************* + TEST(test_5_visitable) + { + class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor>, Shape<3, ShapeVisitor>, Shape<4, ShapeVisitor>, + Shape<5, ShapeVisitor> > + { + public: + + void visit(Shape<1, ShapeVisitor>) {} + void visit(Shape<2, ShapeVisitor>) {} + void visit(Shape<3, ShapeVisitor>) {} + void visit(Shape<4, ShapeVisitor>) {} + void visit(Shape<5, ShapeVisitor>) {} + }; + + // This test just needs to compile without errors. + CHECK(true); + } + + //************************************************************************* + TEST(test_6_visitable) + { + class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor>, Shape<3, ShapeVisitor>, Shape<4, ShapeVisitor>, + Shape<5, ShapeVisitor>, Shape<6, ShapeVisitor> > + { + public: + + void visit(Shape<1, ShapeVisitor>) {} + void visit(Shape<2, ShapeVisitor>) {} + void visit(Shape<3, ShapeVisitor>) {} + void visit(Shape<4, ShapeVisitor>) {} + void visit(Shape<5, ShapeVisitor>) {} + void visit(Shape<6, ShapeVisitor>) {} + }; + + // This test just needs to compile without errors. + CHECK(true); + } + + //************************************************************************* + TEST(test_7_visitable) + { + class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor>, Shape<3, ShapeVisitor>, Shape<4, ShapeVisitor>, + Shape<5, ShapeVisitor>, Shape<6, ShapeVisitor>, Shape<7, ShapeVisitor> > + { + public: + + void visit(Shape<1, ShapeVisitor>) {} + void visit(Shape<2, ShapeVisitor>) {} + void visit(Shape<3, ShapeVisitor>) {} + void visit(Shape<4, ShapeVisitor>) {} + void visit(Shape<5, ShapeVisitor>) {} + void visit(Shape<6, ShapeVisitor>) {} + void visit(Shape<7, ShapeVisitor>) {} + }; + + // This test just needs to compile without errors. + CHECK(true); + } + + //************************************************************************* + TEST(test_8_visitable) + { + class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor>, Shape<3, ShapeVisitor>, Shape<4, ShapeVisitor>, + Shape<5, ShapeVisitor>, Shape<6, ShapeVisitor>, Shape<7, ShapeVisitor>, Shape<8, ShapeVisitor> > + { + public: + + void visit(Shape<1, ShapeVisitor>) {} + void visit(Shape<2, ShapeVisitor>) {} + void visit(Shape<3, ShapeVisitor>) {} + void visit(Shape<4, ShapeVisitor>) {} + void visit(Shape<5, ShapeVisitor>) {} + void visit(Shape<6, ShapeVisitor>) {} + void visit(Shape<7, ShapeVisitor>) {} + void visit(Shape<8, ShapeVisitor>) {} + }; + + // This test just needs to compile without errors. + CHECK(true); + } + + //************************************************************************* + TEST(test_9_visitable) + { + class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor>, Shape<3, ShapeVisitor>, Shape<4, ShapeVisitor>, + Shape<5, ShapeVisitor>, Shape<6, ShapeVisitor>, Shape<7, ShapeVisitor>, Shape<8, ShapeVisitor>, + Shape<9, ShapeVisitor> > + { + public: + + void visit(Shape<1, ShapeVisitor>) {} + void visit(Shape<2, ShapeVisitor>) {} + void visit(Shape<3, ShapeVisitor>) {} + void visit(Shape<4, ShapeVisitor>) {} + void visit(Shape<5, ShapeVisitor>) {} + void visit(Shape<6, ShapeVisitor>) {} + void visit(Shape<7, ShapeVisitor>) {} + void visit(Shape<8, ShapeVisitor>) {} + void visit(Shape<9, ShapeVisitor>) {} + }; + + // This test just needs to compile without errors. + CHECK(true); + } + + //************************************************************************* + TEST(test_10_visitable) + { + class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor>, Shape<3, ShapeVisitor>, Shape<4, ShapeVisitor>, + Shape<5, ShapeVisitor>, Shape<6, ShapeVisitor>, Shape<7, ShapeVisitor>, Shape<8, ShapeVisitor>, + Shape<9, ShapeVisitor>, Shape<10, ShapeVisitor> > + { + public: + + void visit(Shape<1, ShapeVisitor>) {} + void visit(Shape<2, ShapeVisitor>) {} + void visit(Shape<3, ShapeVisitor>) {} + void visit(Shape<4, ShapeVisitor>) {} + void visit(Shape<5, ShapeVisitor>) {} + void visit(Shape<6, ShapeVisitor>) {} + void visit(Shape<7, ShapeVisitor>) {} + void visit(Shape<8, ShapeVisitor>) {} + void visit(Shape<9, ShapeVisitor>) {} + void visit(Shape<10, ShapeVisitor>) {} + }; + + // This test just needs to compile without errors. + CHECK(true); + } + + + //************************************************************************* + TEST(test_11_visitable) + { + class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor>, Shape<3, ShapeVisitor>, Shape<4, ShapeVisitor>, + Shape<5, ShapeVisitor>, Shape<6, ShapeVisitor>, Shape<7, ShapeVisitor>, Shape<8, ShapeVisitor>, + Shape<9, ShapeVisitor>, Shape<10, ShapeVisitor>, Shape<11, ShapeVisitor> > + { + public: + + void visit(Shape<1, ShapeVisitor>) {} + void visit(Shape<2, ShapeVisitor>) {} + void visit(Shape<3, ShapeVisitor>) {} + void visit(Shape<4, ShapeVisitor>) {} + void visit(Shape<5, ShapeVisitor>) {} + void visit(Shape<6, ShapeVisitor>) {} + void visit(Shape<7, ShapeVisitor>) {} + void visit(Shape<8, ShapeVisitor>) {} + void visit(Shape<9, ShapeVisitor>) {} + void visit(Shape<10, ShapeVisitor>) {} + void visit(Shape<11, ShapeVisitor>) {} + }; + + // This test just needs to compile without errors. + CHECK(true); + } + + //************************************************************************* + TEST(test_12_visitable) + { + class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor>, Shape<3, ShapeVisitor>, Shape<4, ShapeVisitor>, + Shape<5, ShapeVisitor>, Shape<6, ShapeVisitor>, Shape<7, ShapeVisitor>, Shape<8, ShapeVisitor>, + Shape<9, ShapeVisitor>, Shape<10, ShapeVisitor>, Shape<11, ShapeVisitor>, Shape<12, ShapeVisitor> > + { + public: + + void visit(Shape<1, ShapeVisitor>) {} + void visit(Shape<2, ShapeVisitor>) {} + void visit(Shape<3, ShapeVisitor>) {} + void visit(Shape<4, ShapeVisitor>) {} + void visit(Shape<5, ShapeVisitor>) {} + void visit(Shape<6, ShapeVisitor>) {} + void visit(Shape<7, ShapeVisitor>) {} + void visit(Shape<8, ShapeVisitor>) {} + void visit(Shape<9, ShapeVisitor>) {} + void visit(Shape<10, ShapeVisitor>) {} + void visit(Shape<11, ShapeVisitor>) {} + void visit(Shape<12, ShapeVisitor>) {} + }; + + // This test just needs to compile without errors. + CHECK(true); + } + + //************************************************************************* + TEST(test_13_visitable) + { + class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor>, Shape<3, ShapeVisitor>, Shape<4, ShapeVisitor>, + Shape<5, ShapeVisitor>, Shape<6, ShapeVisitor>, Shape<7, ShapeVisitor>, Shape<8, ShapeVisitor>, + Shape<9, ShapeVisitor>, Shape<10, ShapeVisitor>, Shape<11, ShapeVisitor>, Shape<12, ShapeVisitor>, + Shape<13, ShapeVisitor> > + { + public: + + void visit(Shape<1, ShapeVisitor>) {} + void visit(Shape<2, ShapeVisitor>) {} + void visit(Shape<3, ShapeVisitor>) {} + void visit(Shape<4, ShapeVisitor>) {} + void visit(Shape<5, ShapeVisitor>) {} + void visit(Shape<6, ShapeVisitor>) {} + void visit(Shape<7, ShapeVisitor>) {} + void visit(Shape<8, ShapeVisitor>) {} + void visit(Shape<9, ShapeVisitor>) {} + void visit(Shape<10, ShapeVisitor>) {} + void visit(Shape<11, ShapeVisitor>) {} + void visit(Shape<12, ShapeVisitor>) {} + void visit(Shape<13, ShapeVisitor>) {} + }; + + // This test just needs to compile without errors. + CHECK(true); + } + + //************************************************************************* + TEST(test_14_visitable) + { + class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor>, Shape<3, ShapeVisitor>, Shape<4, ShapeVisitor>, + Shape<5, ShapeVisitor>, Shape<6, ShapeVisitor>, Shape<7, ShapeVisitor>, Shape<8, ShapeVisitor>, + Shape<9, ShapeVisitor>, Shape<10, ShapeVisitor>, Shape<11, ShapeVisitor>, Shape<12, ShapeVisitor>, + Shape<13, ShapeVisitor>, Shape<14, ShapeVisitor> > + { + public: + + void visit(Shape<1, ShapeVisitor>) {} + void visit(Shape<2, ShapeVisitor>) {} + void visit(Shape<3, ShapeVisitor>) {} + void visit(Shape<4, ShapeVisitor>) {} + void visit(Shape<5, ShapeVisitor>) {} + void visit(Shape<6, ShapeVisitor>) {} + void visit(Shape<7, ShapeVisitor>) {} + void visit(Shape<8, ShapeVisitor>) {} + void visit(Shape<9, ShapeVisitor>) {} + void visit(Shape<10, ShapeVisitor>) {} + void visit(Shape<11, ShapeVisitor>) {} + void visit(Shape<12, ShapeVisitor>) {} + void visit(Shape<13, ShapeVisitor>) {} + void visit(Shape<14, ShapeVisitor>) {} + }; + + // This test just needs to compile without errors. + CHECK(true); + } + + //************************************************************************* + TEST(test_15_visitable) + { + class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor>, Shape<3, ShapeVisitor>, Shape<4, ShapeVisitor>, + Shape<5, ShapeVisitor>, Shape<6, ShapeVisitor>, Shape<7, ShapeVisitor>, Shape<8, ShapeVisitor>, + Shape<9, ShapeVisitor>, Shape<10, ShapeVisitor>, Shape<11, ShapeVisitor>, Shape<12, ShapeVisitor>, + Shape<13, ShapeVisitor>, Shape<14, ShapeVisitor>, Shape<15, ShapeVisitor> > + { + public: + + void visit(Shape<1, ShapeVisitor>) {} + void visit(Shape<2, ShapeVisitor>) {} + void visit(Shape<3, ShapeVisitor>) {} + void visit(Shape<4, ShapeVisitor>) {} + void visit(Shape<5, ShapeVisitor>) {} + void visit(Shape<6, ShapeVisitor>) {} + void visit(Shape<7, ShapeVisitor>) {} + void visit(Shape<8, ShapeVisitor>) {} + void visit(Shape<9, ShapeVisitor>) {} + void visit(Shape<10, ShapeVisitor>) {} + void visit(Shape<11, ShapeVisitor>) {} + void visit(Shape<12, ShapeVisitor>) {} + void visit(Shape<13, ShapeVisitor>) {} + void visit(Shape<14, ShapeVisitor>) {} + void visit(Shape<15, ShapeVisitor>) {} + }; + + // This test just needs to compile without errors. + CHECK(true); + } + + //************************************************************************* + TEST(test_16_visitable) + { + class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor>, Shape<3, ShapeVisitor>, Shape<4, ShapeVisitor>, + Shape<5, ShapeVisitor>, Shape<6, ShapeVisitor>, Shape<7, ShapeVisitor>, Shape<8, ShapeVisitor>, + Shape<9, ShapeVisitor>, Shape<10, ShapeVisitor>, Shape<11, ShapeVisitor>, Shape<12, ShapeVisitor>, + Shape<13, ShapeVisitor>, Shape<14, ShapeVisitor>, Shape<15, ShapeVisitor>, Shape<16, ShapeVisitor> > + { + public: + + void visit(Shape<1, ShapeVisitor>) {} + void visit(Shape<2, ShapeVisitor>) {} + void visit(Shape<3, ShapeVisitor>) {} + void visit(Shape<4, ShapeVisitor>) {} + void visit(Shape<5, ShapeVisitor>) {} + void visit(Shape<6, ShapeVisitor>) {} + void visit(Shape<7, ShapeVisitor>) {} + void visit(Shape<8, ShapeVisitor>) {} + void visit(Shape<9, ShapeVisitor>) {} + void visit(Shape<10, ShapeVisitor>) {} + void visit(Shape<11, ShapeVisitor>) {} + void visit(Shape<12, ShapeVisitor>) {} + void visit(Shape<13, ShapeVisitor>) {} + void visit(Shape<14, ShapeVisitor>) {} + void visit(Shape<15, ShapeVisitor>) {} + void visit(Shape<16, ShapeVisitor>) {} + }; + + // This test just needs to compile without errors. + CHECK(true); + } + + //************************************************************************* + struct NotVisitor {}; + + TEST(test_is_visitor) + { +#if ETL_USING_CPP17 + CHECK_TRUE(etl::is_visitor_v); + CHECK_TRUE(etl::is_visitor_v); + CHECK_FALSE(etl::is_visitor_v); +#else + CHECK_TRUE(etl::is_visitor::value); + CHECK_TRUE(etl::is_visitor::value); + CHECK_FALSE(etl::is_visitor::value); +#endif + } + } +} + +#endif + diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 6396b761..09056bad 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -10357,9 +10357,11 @@ + + @@ -11433,6 +11435,7 @@ + From 92e33bb974b2c8d2bbd5caf16659a9efe3c571e8 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 24 Dec 2025 20:02:06 +0000 Subject: [PATCH 099/298] Added member type_list type to tuple --- include/etl/tuple.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/etl/tuple.h b/include/etl/tuple.h index c4a9440b..2dd4971e 100644 --- a/include/etl/tuple.h +++ b/include/etl/tuple.h @@ -45,6 +45,7 @@ SOFTWARE. #include "type_traits.h" #include "utility.h" #include "functional.h" +#include "type_list.h" #include "private/tuple_element.h" #include "private/tuple_size.h" @@ -131,6 +132,7 @@ namespace etl using value_type = void; ///< The type contained by this tuple. using this_type = tuple<>; ///< The type of this tuple. using base_type = void; ///< The type of the base tuple. + using type_list = etl::type_list<>; ///< The type list for this tuple. using index_sequence_type = etl::make_index_sequence<0>; ///< The index_sequence type for this tuple. //********************************* @@ -233,6 +235,7 @@ namespace etl using value_type = THead; ///< The type contained by this tuple. using this_type = tuple; ///< The type of this tuple. using base_type = tuple; ///< The type of the base tuple. + using type_list = etl::type_list; ///< The type list for this tuple. using index_sequence_type = etl::make_index_sequence()>; ///< The index_sequence type for this tuple. //********************************* From 8320b35d4720a9613198fd51d61719cba582091d Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 24 Dec 2025 20:20:13 +0000 Subject: [PATCH 100/298] Work in progress --- include/etl/message_router.h | 153 ++++++++++++++++++++++++++++++++++- test/CMakeLists.txt | 3 + test/test_tuple.cpp | 10 +++ 3 files changed, 164 insertions(+), 2 deletions(-) diff --git a/include/etl/message_router.h b/include/etl/message_router.h index e08c8344..02942c8d 100644 --- a/include/etl/message_router.h +++ b/include/etl/message_router.h @@ -550,9 +550,158 @@ namespace etl } } }; +#elif ETL_USING_CPP14 && !defined(ETL_MESSAGE_ROUTER_FORCE_CPP03_IMPLEMENTATION) + //************************************************************************************************* + // Unified C++11/14 variadic implementation (no fold expressions). + //************************************************************************************************* + template + class message_router : public imessage_router + { + public: + typedef etl::message_packet message_packet; +#if ETL_USING_CPP11 + using type_list = etl::type_list; +#endif + + // Constructors (inherit public base ones) + message_router() + : imessage_router(etl::imessage_router::MESSAGE_ROUTER) + { + } + + message_router(etl::imessage_router& successor_) + : imessage_router(etl::imessage_router::MESSAGE_ROUTER, successor_) + { + } + + message_router(etl::message_router_id_t id_) + : imessage_router(id_) + { + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) + : imessage_router(id_, successor_) + { + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + using etl::imessage_router::receive; + + // Route by runtime message_id with pack expansion via initializer list. + void receive(const etl::imessage& msg) ETL_OVERRIDE + { + const etl::message_id_t id = msg.get_message_id(); + bool handled = false; + +#include "etl/private/diagnostic_array_bounds_push.h" + // Expand across TMessageTypes... and attempt cast/dispatch on matching IDs. + int dummy[] = {0, (handled = handled || try_receive_one(id, msg), 0)...}; + (void)dummy; +#include "etl/private/diagnostic_pop.h" + + if (!handled) + { + if (has_successor()) + { + get_successor().receive(msg); + } + else + { + static_cast(this)->on_receive_unknown(msg); + } + } + } + + // Overload for concrete message types; forwards to on_receive or successor. + template + typename etl::enable_if::value, void>::type + receive(const TMessage& msg) + { +#include "etl/private/diagnostic_array_bounds_push.h" + if (is_in_message_set()) + { + static_cast(this)->on_receive(msg); + } + else + { + if (has_successor()) + { + get_successor().receive(msg); + } + else + { + static_cast(this)->on_receive_unknown(msg); + } + } +#include "etl/private/diagnostic_pop.h" + } + + using imessage_router::accepts; + + bool accepts(etl::message_id_t id) const ETL_OVERRIDE + { + bool accepted = false; + int dummy[] = {0, (accepted = accepted || accepts_one(id), 0)...}; + (void)dummy; + if (!accepted) + { + if (has_successor()) + { + return get_successor().accepts(id); + } + } + return accepted; + } + + ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE { return false; } + bool is_producer() const ETL_OVERRIDE { return true; } + bool is_consumer() const ETL_OVERRIDE { return true; } + + private: + // Helper: is T in the message set? + template + static ETL_CONSTEXPR bool is_in_message_set() + { + return etl::is_one_of::value; + } + + // Try to handle one type by ID match and cast. + template + bool try_receive_one(etl::message_id_t id, const etl::imessage& msg) + { + if (TMessage::ID == id) + { + static_cast(this)->on_receive(static_cast(msg)); + return true; + } + return false; + } + + // Accepts one type by ID + template + bool accepts_one(etl::message_id_t id) const + { + return TMessage::ID == id; + } + }; + + // Convenience bridge: allow message_router> + template + class message_router> + : public message_router + { + public: + typedef message_router base_type; +#if ETL_USING_CPP11 + using type_list = etl::type_list; +#endif + + using base_type::base_type; // inherit constructors + }; #else //************************************************************************************************* -// For C++14 and below. +// For C++03. //************************************************************************************************* //*************************************************************************** // The definition for all 16 message types. @@ -2955,7 +3104,7 @@ namespace etl }; #endif -#if ETL_USING_CPP11 && !defined(ETL_MESSAGE_ROUTER_FORCE_CPP03_IMPLEMENTATION) +#if ETL_USING_CPP17 && !defined(ETL_MESSAGE_ROUTER_FORCE_CPP03_IMPLEMENTATION) template class message_router> : public message_router diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 899ae047..31b7776d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -234,6 +234,7 @@ add_executable(etl_tests test_message_bus.cpp test_message_packet.cpp test_message_router.cpp + test_message_router_with_type_list.cpp test_message_router_registry.cpp test_message_timer.cpp test_message_timer_atomic.cpp @@ -252,6 +253,7 @@ add_executable(etl_tests test_nth_type.cpp test_numeric.cpp test_observer.cpp + test_observer_with_type_list.cpp test_optional.cpp test_overload.cpp test_packet.cpp @@ -370,6 +372,7 @@ add_executable(etl_tests test_vector_pointer.cpp test_vector_pointer_external_buffer.cpp test_visitor.cpp + test_visitor_with_type_list.cpp test_xor_checksum.cpp test_xor_rotate_checksum.cpp ) diff --git a/test/test_tuple.cpp b/test/test_tuple.cpp index 01a4ca1f..ec02bdaf 100644 --- a/test/test_tuple.cpp +++ b/test/test_tuple.cpp @@ -31,6 +31,7 @@ SOFTWARE. #include "data.h" #include "etl/tuple.h" +#include "etl/type_list.h" #include #include @@ -103,6 +104,15 @@ namespace CHECK_TRUE((std::is_same>::value)); } + //************************************************************************* + TEST(test_tuple_type_list) + { + using Tuple = etl::tuple; + using TupleTypes = etl::type_list; + + CHECK_TRUE((std::is_same::value)); + } + //************************************************************************* TEST(test_default_constructor) { From 947e89a6e979ee6590fa5c58e49e5376ac6998ad Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 26 Jan 2026 17:55:50 +0000 Subject: [PATCH 101/298] Copy changes from other source --- include/etl/message_packet.h | 140 ++++++++++++++ include/etl/message_router.h | 355 +++++++++++++---------------------- include/etl/type_list.h | 6 + 3 files changed, 273 insertions(+), 228 deletions(-) diff --git a/include/etl/message_packet.h b/include/etl/message_packet.h index 8215eeb0..aa449cb8 100644 --- a/include/etl/message_packet.h +++ b/include/etl/message_packet.h @@ -59,6 +59,7 @@ SOFTWARE. #include "largest.h" #include "alignment.h" #include "utility.h" +#include "type_list.h" #include @@ -85,6 +86,8 @@ namespace etl public: + using message_types = etl::type_list; + //******************************************** #include "private/diagnostic_uninitialized_push.h" message_packet() @@ -380,6 +383,18 @@ namespace etl bool valid; }; + //*************************************************************************** + // The definition for all message types. + //*************************************************************************** + template + class message_packet> : public etl::message_packet + { + public: + + using base_type = etl::message_packet; + using base_type::base_type; // Inherit all ctors + }; + #else //*************************************************************************** @@ -393,6 +408,10 @@ namespace etl { public: +#if ETL_USING_CPP11 + using message_types = etl::type_list; +#endif + //******************************************** #include "private/diagnostic_uninitialized_push.h" message_packet() @@ -717,6 +736,10 @@ namespace etl { public: +#if ETL_USING_CPP11 + using message_types = etl::type_list; +#endif + //******************************************** #include "private/diagnostic_uninitialized_push.h" message_packet() @@ -1039,6 +1062,10 @@ namespace etl { public: +#if ETL_USING_CPP11 + using message_types = etl::type_list; +#endif + //******************************************** #include "private/diagnostic_uninitialized_push.h" message_packet() @@ -1358,6 +1385,10 @@ namespace etl { public: +#if ETL_USING_CPP11 + using message_types = etl::type_list; +#endif + //******************************************** #include "private/diagnostic_uninitialized_push.h" message_packet() @@ -1673,6 +1704,10 @@ namespace etl { public: +#if ETL_USING_CPP11 + using message_types = etl::type_list; +#endif + //******************************************** #include "private/diagnostic_uninitialized_push.h" message_packet() @@ -1982,6 +2017,10 @@ namespace etl { public: +#if ETL_USING_CPP11 + using message_types = etl::type_list; +#endif + //******************************************** #include "private/diagnostic_uninitialized_push.h" message_packet() @@ -2288,6 +2327,10 @@ namespace etl { public: +#if ETL_USING_CPP11 + using message_types = etl::type_list; +#endif + //******************************************** #include "private/diagnostic_uninitialized_push.h" message_packet() @@ -2591,6 +2634,10 @@ namespace etl { public: +#if ETL_USING_CPP11 + using message_types = etl::type_list; +#endif + //******************************************** #include "private/diagnostic_uninitialized_push.h" message_packet() @@ -2890,6 +2937,10 @@ namespace etl { public: +#if ETL_USING_CPP11 + using message_types = etl::type_list; +#endif + //******************************************** #include "private/diagnostic_uninitialized_push.h" message_packet() @@ -3183,6 +3234,10 @@ namespace etl { public: +#if ETL_USING_CPP11 + using message_types = etl::type_list; +#endif + //******************************************** #include "private/diagnostic_uninitialized_push.h" message_packet() @@ -3473,6 +3528,10 @@ namespace etl { public: +#if ETL_USING_CPP11 + using message_types = etl::type_list; +#endif + //******************************************** #include "private/diagnostic_uninitialized_push.h" message_packet() @@ -3760,6 +3819,10 @@ namespace etl { public: +#if ETL_USING_CPP11 + using message_types = etl::type_list; +#endif + //******************************************** #include "private/diagnostic_uninitialized_push.h" message_packet() @@ -4043,6 +4106,10 @@ namespace etl { public: +#if ETL_USING_CPP11 + using message_types = etl::type_list; +#endif + //******************************************** #include "private/diagnostic_uninitialized_push.h" message_packet() @@ -4320,6 +4387,10 @@ namespace etl { public: +#if ETL_USING_CPP11 + using message_types = etl::type_list; +#endif + //******************************************** #include "private/diagnostic_uninitialized_push.h" message_packet() @@ -4594,6 +4665,10 @@ namespace etl { public: +#if ETL_USING_CPP11 + using message_types = etl::type_list; +#endif + //******************************************** #include "private/diagnostic_uninitialized_push.h" message_packet() @@ -4865,6 +4940,14 @@ namespace etl { public: + ETL_STATIC_ASSERT(!etl::is_type_list::value, + "T1 must not be an etl::type_list. " + "Use etl::message_packet> only with the C++17 variadic overload."); + +#if ETL_USING_CPP11 + using message_types = etl::type_list; +#endif + //******************************************** #include "private/diagnostic_uninitialized_push.h" message_packet() @@ -5124,6 +5207,63 @@ namespace etl typename etl::aligned_storage::type data; bool valid; }; + + //*************************************************************************** + // Specialisation for 0 message types. + //*************************************************************************** + template <> + class message_packet + { + public: + +#if ETL_USING_CPP11 + using message_types = etl::type_list<>; +#endif + + message_packet() + : valid(false) + { + } + + static ETL_CONSTEXPR bool accepts(etl::message_id_t) + { + return false; + } + + static ETL_CONSTEXPR bool accepts(const etl::imessage&) + { + return false; + } + + template + static ETL_CONSTEXPR bool accepts() + { + ETL_UNUSED(Id); + return false; + } + + template + static ETL_CONSTEXPR typename etl::enable_if::value, bool>::type accepts() + { + return false; + } + + bool is_valid() const + { + return valid; + } + + enum + { + SIZE = 0U, + ALIGNMENT = 1U + }; + + private: + + bool valid; + }; #endif } diff --git a/include/etl/message_router.h b/include/etl/message_router.h index 02942c8d..42fc65f8 100644 --- a/include/etl/message_router.h +++ b/include/etl/message_router.h @@ -412,7 +412,7 @@ namespace etl public: using message_packet = etl::message_packet; - using type_list = etl::type_list; + using message_types = etl::type_list; //********************************************** message_router() @@ -550,158 +550,21 @@ namespace etl } } }; -#elif ETL_USING_CPP14 && !defined(ETL_MESSAGE_ROUTER_FORCE_CPP03_IMPLEMENTATION) - //************************************************************************************************* - // Unified C++11/14 variadic implementation (no fold expressions). - //************************************************************************************************* + + //*************************************************************************** + // The definition for all message types defined by a type_list. + //*************************************************************************** template - class message_router : public imessage_router + class message_router> : public message_router { - public: - typedef etl::message_packet message_packet; -#if ETL_USING_CPP11 - using type_list = etl::type_list; -#endif + public: - // Constructors (inherit public base ones) - message_router() - : imessage_router(etl::imessage_router::MESSAGE_ROUTER) - { - } - - message_router(etl::imessage_router& successor_) - : imessage_router(etl::imessage_router::MESSAGE_ROUTER, successor_) - { - } - - message_router(etl::message_router_id_t id_) - : imessage_router(id_) - { - ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); - } - - message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) - : imessage_router(id_, successor_) - { - ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); - } - - using etl::imessage_router::receive; - - // Route by runtime message_id with pack expansion via initializer list. - void receive(const etl::imessage& msg) ETL_OVERRIDE - { - const etl::message_id_t id = msg.get_message_id(); - bool handled = false; - -#include "etl/private/diagnostic_array_bounds_push.h" - // Expand across TMessageTypes... and attempt cast/dispatch on matching IDs. - int dummy[] = {0, (handled = handled || try_receive_one(id, msg), 0)...}; - (void)dummy; -#include "etl/private/diagnostic_pop.h" - - if (!handled) - { - if (has_successor()) - { - get_successor().receive(msg); - } - else - { - static_cast(this)->on_receive_unknown(msg); - } - } - } - - // Overload for concrete message types; forwards to on_receive or successor. - template - typename etl::enable_if::value, void>::type - receive(const TMessage& msg) - { -#include "etl/private/diagnostic_array_bounds_push.h" - if (is_in_message_set()) - { - static_cast(this)->on_receive(msg); - } - else - { - if (has_successor()) - { - get_successor().receive(msg); - } - else - { - static_cast(this)->on_receive_unknown(msg); - } - } -#include "etl/private/diagnostic_pop.h" - } - - using imessage_router::accepts; - - bool accepts(etl::message_id_t id) const ETL_OVERRIDE - { - bool accepted = false; - int dummy[] = {0, (accepted = accepted || accepts_one(id), 0)...}; - (void)dummy; - if (!accepted) - { - if (has_successor()) - { - return get_successor().accepts(id); - } - } - return accepted; - } - - ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE { return false; } - bool is_producer() const ETL_OVERRIDE { return true; } - bool is_consumer() const ETL_OVERRIDE { return true; } - - private: - // Helper: is T in the message set? - template - static ETL_CONSTEXPR bool is_in_message_set() - { - return etl::is_one_of::value; - } - - // Try to handle one type by ID match and cast. - template - bool try_receive_one(etl::message_id_t id, const etl::imessage& msg) - { - if (TMessage::ID == id) - { - static_cast(this)->on_receive(static_cast(msg)); - return true; - } - return false; - } - - // Accepts one type by ID - template - bool accepts_one(etl::message_id_t id) const - { - return TMessage::ID == id; - } + using message_router::message_router; }; - // Convenience bridge: allow message_router> - template - class message_router> - : public message_router - { - public: - typedef message_router base_type; -#if ETL_USING_CPP11 - using type_list = etl::type_list; -#endif - - using base_type::base_type; // inherit constructors - }; -#else + #else //************************************************************************************************* -// For C++03. +// For C++14 and below. //************************************************************************************************* //*************************************************************************** // The definition for all 16 message types. @@ -715,10 +578,10 @@ namespace etl { public: - typedef etl::message_packet message_packet; + typedef etl::message_packet message_packet; #if ETL_USING_CPP11 - using type_list = etl::type_list; + using message_types = etl::type_list; #endif //********************************************** @@ -873,7 +736,7 @@ namespace etl typedef etl::message_packet message_packet; #if ETL_USING_CPP11 - using type_list = etl::type_list; + using message_types = etl::type_list; #endif //********************************************** @@ -1028,7 +891,7 @@ namespace etl typedef etl::message_packet message_packet; #if ETL_USING_CPP11 - using type_list = etl::type_list; + using message_types = etl::type_list; #endif //********************************************** @@ -1182,7 +1045,7 @@ namespace etl typedef etl::message_packet message_packet; #if ETL_USING_CPP11 - using type_list = etl::type_list; + using message_types = etl::type_list; #endif //********************************************** @@ -1334,7 +1197,7 @@ namespace etl typedef etl::message_packet message_packet; #if ETL_USING_CPP11 - using type_list = etl::type_list; + using message_types = etl::type_list; #endif //********************************************** @@ -1485,7 +1348,7 @@ namespace etl typedef etl::message_packet message_packet; #if ETL_USING_CPP11 - using type_list = etl::type_list; + using message_types = etl::type_list; #endif //********************************************** @@ -1635,7 +1498,7 @@ namespace etl typedef etl::message_packet message_packet; #if ETL_USING_CPP11 - using type_list = etl::type_list; + using message_types = etl::type_list; #endif //********************************************** @@ -1784,7 +1647,7 @@ namespace etl typedef etl::message_packet message_packet; #if ETL_USING_CPP11 - using type_list = etl::type_list; + using message_types = etl::type_list; #endif //********************************************** @@ -1931,7 +1794,7 @@ namespace etl typedef etl::message_packet message_packet; #if ETL_USING_CPP11 - using type_list = etl::type_list; + using message_types = etl::type_list; #endif //********************************************** @@ -2077,7 +1940,7 @@ namespace etl typedef etl::message_packet message_packet; #if ETL_USING_CPP11 - using type_list = etl::type_list; + using message_types = etl::type_list; #endif //********************************************** @@ -2221,7 +2084,7 @@ namespace etl typedef etl::message_packet message_packet; #if ETL_USING_CPP11 - using type_list = etl::type_list; + using message_types = etl::type_list; #endif //********************************************** @@ -2364,7 +2227,7 @@ namespace etl typedef etl::message_packet message_packet; #if ETL_USING_CPP11 - using type_list = etl::type_list; + using message_types = etl::type_list; #endif //********************************************** @@ -2505,7 +2368,7 @@ namespace etl typedef etl::message_packet message_packet; #if ETL_USING_CPP11 - using type_list = etl::type_list; + using message_types = etl::type_list; #endif //********************************************** @@ -2645,7 +2508,7 @@ namespace etl typedef etl::message_packet message_packet; #if ETL_USING_CPP11 - using type_list = etl::type_list; + using message_types = etl::type_list; #endif //********************************************** @@ -2784,7 +2647,7 @@ namespace etl typedef etl::message_packet message_packet; #if ETL_USING_CPP11 - using type_list = etl::type_list; + using message_types = etl::type_list; #endif //********************************************** @@ -2919,10 +2782,10 @@ namespace etl { public: - typedef etl::message_packet< T1> message_packet; + typedef etl::message_packet message_packet; #if ETL_USING_CPP11 - using type_list = etl::type_list; + using message_types = etl::type_list; #endif //********************************************** @@ -3046,75 +2909,111 @@ namespace etl } }; - // Helper: select type at index I from a `type_list`, or `void` if out of range. - template - struct message_router_type_or_void + //*************************************************************************** + // Specialisation for 0 message types. + //*************************************************************************** + template + class message_router + : public imessage_router { - typedef typename etl::conditional<(I < etl::type_list_size::value), - etl::type_list_type_at_index, - etl::type_identity>::type::type type; - }; - - // For C++14 and below, map the `type_list` to up to 16 message type parameters (fill with `void`). - template - class message_router, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void> - : public message_router>::type, - typename etl::message_router_type_or_void<1, etl::type_list>::type, - typename etl::message_router_type_or_void<2, etl::type_list>::type, - typename etl::message_router_type_or_void<3, etl::type_list>::type, - typename etl::message_router_type_or_void<4, etl::type_list>::type, - typename etl::message_router_type_or_void<5, etl::type_list>::type, - typename etl::message_router_type_or_void<6, etl::type_list>::type, - typename etl::message_router_type_or_void<7, etl::type_list>::type, - typename etl::message_router_type_or_void<8, etl::type_list>::type, - typename etl::message_router_type_or_void<9, etl::type_list>::type, - typename etl::message_router_type_or_void<10, etl::type_list>::type, - typename etl::message_router_type_or_void<11, etl::type_list>::type, - typename etl::message_router_type_or_void<12, etl::type_list>::type, - typename etl::message_router_type_or_void<13, etl::type_list>::type, - typename etl::message_router_type_or_void<14, etl::type_list>::type, - typename etl::message_router_type_or_void<15, etl::type_list>::type> - { - // Enforce the maximum number of message types supported by the C++14 implementation. - static_assert(sizeof...(TMessageTypes) <= 16, "etl::message_router supports up to 16 message types for C++14"); - public: - using base = message_router>::type, - typename etl::message_router_type_or_void<1, etl::type_list>::type, - typename etl::message_router_type_or_void<2, etl::type_list>::type, - typename etl::message_router_type_or_void<3, etl::type_list>::type, - typename etl::message_router_type_or_void<4, etl::type_list>::type, - typename etl::message_router_type_or_void<5, etl::type_list>::type, - typename etl::message_router_type_or_void<6, etl::type_list>::type, - typename etl::message_router_type_or_void<7, etl::type_list>::type, - typename etl::message_router_type_or_void<8, etl::type_list>::type, - typename etl::message_router_type_or_void<9, etl::type_list>::type, - typename etl::message_router_type_or_void<10, etl::type_list>::type, - typename etl::message_router_type_or_void<11, etl::type_list>::type, - typename etl::message_router_type_or_void<12, etl::type_list>::type, - typename etl::message_router_type_or_void<13, etl::type_list>::type, - typename etl::message_router_type_or_void<14, etl::type_list>::type, - typename etl::message_router_type_or_void<15, etl::type_list>::type>; - using base::base; // Inherit constructors - using typename base::message_packet; - using type_list = etl::type_list; - }; + typedef etl::message_packet message_packet; + +#if ETL_USING_CPP11 + using message_types = etl::type_list<>; #endif -#if ETL_USING_CPP17 && !defined(ETL_MESSAGE_ROUTER_FORCE_CPP03_IMPLEMENTATION) - template - class message_router> - : public message_router - { - public: + //********************************************** + message_router(etl::message_router_id_t id_) + : imessage_router(id_) + { + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } - using this_type = message_router>; - using base_type = message_router; - using type_list = etl::type_list; - using base_type::base_type; + //********************************************** + message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) + : imessage_router(id_, successor_) + { + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + //********************************************** + message_router() + : imessage_router(etl::imessage_router::MESSAGE_ROUTER) + { + } + + //********************************************** + message_router(etl::imessage_router& successor_) + : imessage_router(etl::imessage_router::MESSAGE_ROUTER, successor_) + { + } + + //********************************************** + using etl::imessage_router::receive; + + void receive(const etl::imessage& msg) ETL_OVERRIDE + { + const size_t id = msg.get_message_id(); + +#include "etl/private/diagnostic_array_bounds_push.h" + switch (id) + { + default: + { + if (has_successor()) + { + get_successor().receive(msg); + } + else + { + static_cast(this)->on_receive_unknown(msg); + } + break; + } + } +#include "etl/private/diagnostic_pop.h" + } + + //********************************************** + using imessage_router::accepts; + + bool accepts(etl::message_id_t id) const ETL_OVERRIDE + { + switch (id) + { + default: + { + if (has_successor()) + { + return get_successor().accepts(id); + } + else + { + return false; + } + } + } + } + + //******************************************** + ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE + { + return false; + } + + //******************************************** + bool is_producer() const ETL_OVERRIDE + { + return true; + } + + //******************************************** + bool is_consumer() const ETL_OVERRIDE + { + return true; + } }; #endif } diff --git a/include/etl/type_list.h b/include/etl/type_list.h index 84e241ec..2d0dcdac 100644 --- a/include/etl/type_list.h +++ b/include/etl/type_list.h @@ -53,6 +53,12 @@ namespace etl template struct type_list; + template + struct is_type_list : etl::false_type {}; + + template + struct is_type_list> : etl::true_type {}; + //*************************************************************************** /// The empty type list. //*************************************************************************** From 49d7fa80bc3924c45cca8618d79e9f82f3a1faee Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 27 Jan 2026 19:28:40 +0000 Subject: [PATCH 102/298] Removed unused tests --- test/test_message_router_with_type_list.cpp | 741 ------------------- test/test_observer_with_type_list.cpp | 583 --------------- test/test_visitor_with_type_list.cpp | 761 -------------------- 3 files changed, 2085 deletions(-) delete mode 100644 test/test_message_router_with_type_list.cpp delete mode 100644 test/test_observer_with_type_list.cpp delete mode 100644 test/test_visitor_with_type_list.cpp diff --git a/test/test_message_router_with_type_list.cpp b/test/test_message_router_with_type_list.cpp deleted file mode 100644 index b997f59f..00000000 --- a/test/test_message_router_with_type_list.cpp +++ /dev/null @@ -1,741 +0,0 @@ -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -https://www.etlcpp.com - -Copyright(c) 2017 John Wellbelove - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions : - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -******************************************************************************/ - -#include "unit_test_framework.h" - -#include "etl/message_router.h" -#include "etl/queue.h" -#include "etl/largest.h" - -//*************************************************************************** -// The set of messages. -//*************************************************************************** -namespace -{ - enum - { - MESSAGE0, - MESSAGE1, - MESSAGE2, - MESSAGE3, - MESSAGE4, - MESSAGE5 - }; - - enum - { - ROUTER1, - ROUTER2, - ROUTER3 - }; - - //*********************************** - struct NotInterface - { - virtual ~NotInterface() {} - virtual int VirtualFunction() const = 0; - }; - - ////*********************************** - // Uncomment to demonstrate static assert - //struct Message0 : public etl::message - //{ - //}; - - //*********************************** - struct Message1 : public etl::message - { - Message1(etl::imessage_router& callback_) - : callback(callback_) - { - } - - etl::imessage_router& callback; - }; - - //*********************************** - struct Message2 : public etl::message - { - Message2(etl::imessage_router& callback_) - : callback(callback_) - { - } - - etl::imessage_router& callback; - }; - - //*********************************** - struct Message3 : public etl::message - { - Message3(etl::imessage_router& callback_) - : callback(callback_) - { - } - - etl::imessage_router& callback; - int value[10]; - }; - - //*********************************** - struct Message4 : public etl::message - { - Message4(etl::imessage_router& callback_) - : callback(callback_) - { - } - - etl::imessage_router& callback; - }; - - //*********************************** - struct Message5 : public etl::message - { - }; - - Message5 message5; - - using Router1Messages = etl::type_list; - using Router2Messages = etl::type_list; - using Router3Messages = etl::type_list; - - //*************************************************************************** - // Router that handles messages 1, 2, 3, 4 and 5 and returns nothing. - //*************************************************************************** - class Router1 : public etl::message_router - { - public: - - Router1() - : message_router(ROUTER1), - message1_count(0), - message2_count(0), - message3_count(0), - message4_count(0), - message_unknown_count(0), - callback_count(0) - { - - } - - void on_receive(const Message1& msg) - { - ++message1_count; - etl::send_message(msg.callback, message5); - //CHECK_EQUAL(1, msg.VirtualFunction()); - } - - void on_receive(const Message2& msg) - { - ++message2_count; - etl::send_message(msg.callback, message5); - } - - void on_receive(const Message3& msg) - { - ++message3_count; - etl::send_message(msg.callback, message5); - } - - void on_receive(const Message4& msg) - { - ++message4_count; - etl::send_message(msg.callback, message5); - } - - void on_receive(const Message5&) - { - ++callback_count; - } - - void on_receive_unknown(const etl::imessage&) - { - ++message_unknown_count; - } - - int message1_count; - int message2_count; - int message3_count; - int message4_count; - int message_unknown_count; - int callback_count; - }; - - //*************************************************************************** - // Router that handles messages 1, 2, 4 and 5 and returns nothing. - //*************************************************************************** - class Router2 : public etl::message_router - { - public: - - Router2() - : message_router(ROUTER2), - message1_count(0), - message2_count(0), - message4_count(0), - message_unknown_count(0), - callback_count(0), - sender_id(0) - { - - } - - Router2(etl::imessage_router& successor_) - : message_router(ROUTER2, successor_), - message1_count(0), - message2_count(0), - message4_count(0), - message_unknown_count(0), - callback_count(0), - sender_id(0) - { - - } - - void on_receive(const Message1& msg) - { - ++message1_count; - sender_id = msg.callback.get_message_router_id(); - etl::send_message(msg.callback, message5); - //CHECK_EQUAL(1, msg.VirtualFunction()); - } - - void on_receive(const Message2& msg) - { - ++message2_count; - sender_id = msg.callback.get_message_router_id(); - etl::send_message(msg.callback, message5); - } - - void on_receive(const Message4& msg) - { - ++message4_count; - sender_id = msg.callback.get_message_router_id(); - etl::send_message(msg.callback, message5); - } - - void on_receive(const Message5&) - { - ++callback_count; - } - - void on_receive_unknown(const etl::imessage&) - { - ++message_unknown_count; - sender_id = 0; - } - - int message1_count; - int message2_count; - int message4_count; - int message_unknown_count; - int callback_count; - int sender_id; - }; - - //*************************************************************************** - // Router that handles messages 1, 2, 3. - // 'receive' is overridden. - //*************************************************************************** - class Router3 : public etl::message_router - { - public: - - using base = etl::message_router; - - Router3() - : message_router(ROUTER3) - , message1_received(false) - , message2_received(false) - , message3_received(false) - , unknown_message_received(false) - { - } - - void receive(const etl::imessage& msg) override - { - switch (msg.get_message_id()) - { - case MESSAGE1: - { - message1_received = true; - break; - } - - case MESSAGE2: - { - message2_received = true; - break; - } - - case MESSAGE3: - { - message3_received = true; - break; - } - - default: - { - unknown_message_received = true; - break; - } - } - } - - void on_receive(const Message1&) - { - } - - void on_receive(const Message2&) - { - } - - void on_receive(const Message3&) - { - } - - void on_receive_unknown(const etl::imessage&) - { - } - - bool message1_received; - bool message2_received; - bool message3_received; - bool unknown_message_received; - }; - - etl::imessage_router* p_router; - - SUITE(test_message_router_with_type_list) - { - //************************************************************************* - TEST(message_router) - { - Router1 r1; - Router2 r2; - - p_router = &r1; - - Message1 message1(r2); - Message2 message2(r2); - Message3 message3(r2); - Message4 message4(r2); - - // CHECK(!r1.is_null_router()); - CHECK(r1.is_producer()); - CHECK(r1.is_consumer()); - - p_router->receive(message1); - CHECK_EQUAL(1, r1.message1_count); - CHECK_EQUAL(0, r1.message2_count); - CHECK_EQUAL(0, r1.message3_count); - CHECK_EQUAL(0, r1.message4_count); - CHECK_EQUAL(0, r1.message_unknown_count); - CHECK_EQUAL(1, r2.callback_count); - - p_router->receive(message2); - CHECK_EQUAL(1, r1.message1_count); - CHECK_EQUAL(1, r1.message2_count); - CHECK_EQUAL(0, r1.message3_count); - CHECK_EQUAL(0, r1.message4_count); - CHECK_EQUAL(0, r1.message_unknown_count); - CHECK_EQUAL(2, r2.callback_count); - - p_router->receive(message3); - CHECK_EQUAL(1, r1.message1_count); - CHECK_EQUAL(1, r1.message2_count); - CHECK_EQUAL(1, r1.message3_count); - CHECK_EQUAL(0, r1.message4_count); - CHECK_EQUAL(0, r1.message_unknown_count); - CHECK_EQUAL(3, r2.callback_count); - - p_router->receive(message4); - CHECK_EQUAL(1, r1.message1_count); - CHECK_EQUAL(1, r1.message2_count); - CHECK_EQUAL(1, r1.message3_count); - CHECK_EQUAL(1, r1.message4_count); - CHECK_EQUAL(0, r1.message_unknown_count); - CHECK_EQUAL(4, r2.callback_count); - } - - //************************************************************************* - TEST(message_null_router) - { - Router2 router; - etl::null_message_router null_router; - - Message1 message1(null_router); - Message2 message2(null_router); - Message3 message3(null_router); - Message4 message4(null_router); - - // CHECK(null_router.is_null_router()); - CHECK(!null_router.is_producer()); - CHECK(!null_router.is_consumer()); - - // Send from the null router. - etl::send_message(router, message1); - CHECK_EQUAL(1, router.message1_count); - CHECK_EQUAL(0, router.message2_count); - CHECK_EQUAL(0, router.message4_count); - CHECK_EQUAL(0, router.message_unknown_count); - - etl::send_message(router, message2); - CHECK_EQUAL(1, router.message1_count); - CHECK_EQUAL(1, router.message2_count); - CHECK_EQUAL(0, router.message4_count); - CHECK_EQUAL(0, router.message_unknown_count); - - etl::send_message(router, message3); - CHECK_EQUAL(1, router.message1_count); - CHECK_EQUAL(1, router.message2_count); - CHECK_EQUAL(0, router.message4_count); - CHECK_EQUAL(1, router.message_unknown_count); - - etl::send_message(router, message4); - CHECK_EQUAL(1, router.message1_count); - CHECK_EQUAL(1, router.message2_count); - CHECK_EQUAL(1, router.message4_count); - CHECK_EQUAL(1, router.message_unknown_count); - - // Send to the null router. - etl::send_message(null_router, message1); - CHECK_EQUAL(1, router.message1_count); - CHECK_EQUAL(1, router.message2_count); - CHECK_EQUAL(1, router.message4_count); - CHECK_EQUAL(1, router.message_unknown_count); - - etl::send_message(null_router, message2); - CHECK_EQUAL(1, router.message1_count); - CHECK_EQUAL(1, router.message2_count); - CHECK_EQUAL(1, router.message4_count); - CHECK_EQUAL(1, router.message_unknown_count); - - etl::send_message(null_router, message3); - CHECK_EQUAL(1, router.message1_count); - CHECK_EQUAL(1, router.message2_count); - CHECK_EQUAL(1, router.message4_count); - CHECK_EQUAL(1, router.message_unknown_count); - - etl::send_message(null_router, message4); - CHECK_EQUAL(1, router.message1_count); - CHECK_EQUAL(1, router.message2_count); - CHECK_EQUAL(1, router.message4_count); - CHECK_EQUAL(1, router.message_unknown_count); - } - - //************************************************************************* - TEST(message_producer) - { - Router2 router; - etl::message_producer producer(ROUTER3); - - Message1 message1(producer); - Message2 message2(producer); - Message3 message3(producer); - Message4 message4(producer); - - // CHECK(!producer.is_null_router()); - CHECK(producer.is_producer()); - CHECK(!producer.is_consumer()); - - CHECK_EQUAL(0, router.sender_id); - - // Send from the producer. - router.receive(message1); - //etl::send_message(router, message1); - CHECK_EQUAL(1, router.message1_count); - CHECK_EQUAL(0, router.message2_count); - CHECK_EQUAL(0, router.message4_count); - CHECK_EQUAL(0, router.message_unknown_count); - CHECK_EQUAL(ROUTER3, router.sender_id); - - etl::send_message(router, message2); - CHECK_EQUAL(1, router.message1_count); - CHECK_EQUAL(1, router.message2_count); - CHECK_EQUAL(0, router.message4_count); - CHECK_EQUAL(0, router.message_unknown_count); - CHECK_EQUAL(ROUTER3, router.sender_id); - - etl::send_message(router, message3); - CHECK_EQUAL(1, router.message1_count); - CHECK_EQUAL(1, router.message2_count); - CHECK_EQUAL(0, router.message4_count); - CHECK_EQUAL(1, router.message_unknown_count); - CHECK_EQUAL(0, router.sender_id); - - etl::send_message(router, message4); - CHECK_EQUAL(1, router.message1_count); - CHECK_EQUAL(1, router.message2_count); - CHECK_EQUAL(1, router.message4_count); - CHECK_EQUAL(1, router.message_unknown_count); - CHECK_EQUAL(ROUTER3, router.sender_id); - - // Send to the producer. - etl::send_message(producer, message1); - CHECK_EQUAL(1, router.message1_count); - CHECK_EQUAL(1, router.message2_count); - CHECK_EQUAL(1, router.message4_count); - CHECK_EQUAL(1, router.message_unknown_count); - - etl::send_message(producer, message2); - CHECK_EQUAL(1, router.message1_count); - CHECK_EQUAL(1, router.message2_count); - CHECK_EQUAL(1, router.message4_count); - CHECK_EQUAL(1, router.message_unknown_count); - - etl::send_message(producer, message3); - CHECK_EQUAL(1, router.message1_count); - CHECK_EQUAL(1, router.message2_count); - CHECK_EQUAL(1, router.message4_count); - CHECK_EQUAL(1, router.message_unknown_count); - - etl::send_message(producer, message4); - CHECK_EQUAL(1, router.message1_count); - CHECK_EQUAL(1, router.message2_count); - CHECK_EQUAL(1, router.message4_count); - CHECK_EQUAL(1, router.message_unknown_count); - } - - //************************************************************************* - TEST(message_router_accepts) - { - Router2 r2; - - etl::null_message_router null_router; - - Message1 message1(null_router); - Message2 message2(null_router); - Message3 message3(null_router); - Message4 message4(null_router); - - CHECK(r2.accepts(message1)); - CHECK(r2.accepts(message1.get_message_id())); - - CHECK(r2.accepts(message2)); - CHECK(r2.accepts(message2.get_message_id())); - - CHECK(!r2.accepts(message3)); - CHECK(!r2.accepts(message3.get_message_id())); - - CHECK(r2.accepts(message4)); - CHECK(r2.accepts(message4.get_message_id())); - - CHECK(r2.accepts(message5)); - CHECK(r2.accepts(message5.get_message_id())); - } - - //************************************************************************* - TEST(message_router_accepts_successors) - { - Router1 r1; // M1, M2, M3, M4, M5 - Router2 r2; // M1, M2, M4, M5 - - r2.set_successor(r1); - - etl::null_message_router null_router; - - Message1 message1(null_router); - Message2 message2(null_router); - Message3 message3(null_router); - Message4 message4(null_router); - - CHECK(r2.accepts(message1)); - CHECK(r2.accepts(message1.get_message_id())); - - CHECK(r2.accepts(message2)); - CHECK(r2.accepts(message2.get_message_id())); - - CHECK(r2.accepts(message3)); - CHECK(r2.accepts(message3.get_message_id())); - - CHECK(r2.accepts(message4)); - CHECK(r2.accepts(message4.get_message_id())); - - CHECK(r2.accepts(message5)); - CHECK(r2.accepts(message5.get_message_id())); - } - -#if ETL_HAS_VIRTUAL_MESSAGES - //************************************************************************* - TEST(message_router_queue) - { - Router1 r1; - Router2 r2; - - typedef Router2::message_packet Packet; - typedef etl::queue Queue; - - Queue queue; - - etl::imessage* im; - - Message1 message1(r1); - Message2 message2(r1); - Message3 message3(r1); - Message4 message4(r1); - - // Queue some messages in the message packet queue. - im = &message1; - queue.emplace(*im); - - im = &message2; - queue.emplace(*im); - - // The router2 queue doesn't accept Message3 types. - im = &message3; - CHECK_THROW(queue.emplace(*im), etl::unhandled_message_exception); - - im = &message4; - queue.emplace(*im); - - im = &message4; - queue.emplace(*im); - - etl::imessage& imr1 = queue.front().get(); - r2.receive(imr1); - CHECK_EQUAL(1, r2.message1_count); - CHECK_EQUAL(0, r2.message2_count); - CHECK_EQUAL(0, r2.message4_count); - CHECK_EQUAL(0, r2.message_unknown_count); - CHECK_EQUAL(1, r1.callback_count); - queue.pop(); - - etl::imessage& imr2 = queue.front().get(); - r2.receive(imr2); - CHECK_EQUAL(1, r2.message1_count); - CHECK_EQUAL(1, r2.message2_count); - CHECK_EQUAL(0, r2.message4_count); - CHECK_EQUAL(0, r2.message_unknown_count); - CHECK_EQUAL(2, r1.callback_count); - queue.pop(); - - const etl::imessage& imr3 = queue.front().get(); - r2.receive(imr3); - CHECK_EQUAL(1, r2.message1_count); - CHECK_EQUAL(1, r2.message2_count); - CHECK_EQUAL(1, r2.message4_count); - CHECK_EQUAL(0, r2.message_unknown_count); - CHECK_EQUAL(3, r1.callback_count); - queue.pop(); - - const Queue& crqueue = queue; - const etl::imessage& imr4 = crqueue.front().get(); - r2.receive(imr4); - CHECK_EQUAL(1, r2.message1_count); - CHECK_EQUAL(1, r2.message2_count); - CHECK_EQUAL(2, r2.message4_count); - CHECK_EQUAL(0, r2.message_unknown_count); - CHECK_EQUAL(4, r1.callback_count); - queue.pop(); - } -#endif - - //************************************************************************* - TEST(message_router_successor) - { - Router1 r1; - Router2 r2(r1); - - etl::null_message_router null_router; - - Message1 message1(r2); - Message2 message2(r2); - Message3 message3(r2); - Message4 message4(r2); - - etl::send_message(r2, message1); - CHECK_EQUAL(1, r2.message1_count); - CHECK_EQUAL(0, r2.message2_count); - CHECK_EQUAL(0, r2.message4_count); - CHECK_EQUAL(0, r2.message_unknown_count); - - CHECK_EQUAL(0, r1.message1_count); - CHECK_EQUAL(0, r1.message2_count); - CHECK_EQUAL(0, r1.message3_count); - CHECK_EQUAL(0, r1.message4_count); - CHECK_EQUAL(0, r1.message_unknown_count); - - etl::send_message(r2, message2); - CHECK_EQUAL(1, r2.message1_count); - CHECK_EQUAL(1, r2.message2_count); - CHECK_EQUAL(0, r2.message4_count); - CHECK_EQUAL(0, r2.message_unknown_count); - - CHECK_EQUAL(0, r1.message1_count); - CHECK_EQUAL(0, r1.message2_count); - CHECK_EQUAL(0, r1.message3_count); - CHECK_EQUAL(0, r1.message4_count); - CHECK_EQUAL(0, r1.message_unknown_count); - - r2.receive(message3); - CHECK_EQUAL(1, r2.message1_count); - CHECK_EQUAL(1, r2.message2_count); - CHECK_EQUAL(0, r2.message4_count); - CHECK_EQUAL(0, r2.message_unknown_count); - - CHECK_EQUAL(0, r1.message1_count); - CHECK_EQUAL(0, r1.message2_count); - CHECK_EQUAL(1, r1.message3_count); - CHECK_EQUAL(0, r1.message4_count); - CHECK_EQUAL(0, r1.message_unknown_count); - - etl::send_message(r2, message4); - CHECK_EQUAL(1, r2.message1_count); - CHECK_EQUAL(1, r2.message2_count); - CHECK_EQUAL(1, r2.message4_count); - CHECK_EQUAL(0, r2.message_unknown_count); - - CHECK_EQUAL(0, r1.message1_count); - CHECK_EQUAL(0, r1.message2_count); - CHECK_EQUAL(1, r1.message3_count); - CHECK_EQUAL(0, r1.message4_count); - CHECK_EQUAL(0, r1.message_unknown_count); - } - - //************************************************************************* - TEST(message_router_with_overloaded_receive) - { - Router3 router; - - Message1 message1(router); - Message2 message2(router); - Message3 message3(router); - - router.receive(message1); - CHECK_TRUE(router.message1_received); - - router.receive(message2); - CHECK_TRUE(router.message2_received); - - router.receive(message3); - CHECK_TRUE(router.message3_received); - - CHECK_FALSE(router.unknown_message_received); - } - } -} diff --git a/test/test_observer_with_type_list.cpp b/test/test_observer_with_type_list.cpp deleted file mode 100644 index e0b61f54..00000000 --- a/test/test_observer_with_type_list.cpp +++ /dev/null @@ -1,583 +0,0 @@ -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -https://www.etlcpp.com - -Copyright(c) 2025 John Wellbelove - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions : - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -******************************************************************************/ - -#include "unit_test_framework.h" - -#include "etl/observer.h" -#include "etl/type_list.h" - -#if ETL_USING_CPP11 && !defined(ETL_VISITOR_FORCE_CPP03_IMPLEMENTATION) - -namespace -{ - //***************************************************************************** - // Notification1 - //***************************************************************************** - struct Notification1 - { - }; - - //***************************************************************************** - // Notification2 - //***************************************************************************** - struct Notification2 - { - }; - - //***************************************************************************** - // Notification3 - //***************************************************************************** - struct Notification3 - { - }; - - //***************************************************************************** - // Generic notification. - //***************************************************************************** - template - struct Notification - { - }; - - //***************************************************************************** - // The observer base type. - // Declare what notifications you want to observe and how they are passed to 'notification'. - // The Notification1 is passed by value. - // The Notification2 is passed by reference. - // The Notification3 is passed by const reference. - //***************************************************************************** - using NotificationTypes = etl::type_list; - using ObserverType = etl::observer; - - //***************************************************************************** - // The observer base type that does not take a notification type. - //***************************************************************************** - typedef etl::observer ObserverVoidIntType; -} - -//***************************************************************************** -// The concrete observable 1 class. -//***************************************************************************** -class Observable1 : public etl::observable -{ -public: - - Notification1 data1; - Notification2 data2; - Notification1& data3 = data1; - - //********************************* - // Notify all of the observers. - //********************************* - void send_notifications() - { - notify_observers(data3); - notify_observers(data2); - } -}; - -//***************************************************************************** -// The concrete observable 2 class. -//***************************************************************************** -class Observable2 : public etl::observable -{ -public: - - Notification3 data3; - - //********************************* - // Notify all of the observers. - //********************************* - void send_notifications() - { - notify_observers(data3); - } -}; - -//***************************************************************************** -// The concrete observable 3 class. -//***************************************************************************** -class ObservableVoidInt : public etl::observable -{ -public: - - //********************************* - // Notify all of the observers. - //********************************* - void send_notifications() - { - notify_observers(); - } - - //********************************* - // Notify all of the observers. - //********************************* - void send_notifications(int n) - { - notify_observers(n); - } -}; - -//***************************************************************************** -// The first observer type. -// If any one of the overloads is missing or a parameter declaration is incorrect -// then the class will be 'abstract' and will not compile. -//***************************************************************************** -class Observer1 : public ObserverType -{ -public: - - Observer1() - : data1_count(0) - , data2_count(0) - , data3_count(0) - { - } - - //******************************************* - // Notification1 is passed by value. - //******************************************* - void notification(Notification1 /*data1*/) - { - ++data1_count; - } - - //******************************************* - // Notification2 is passed by reference. - //******************************************* - void notification(Notification2& /*data2*/) - { - ++data2_count; - } - - //******************************************* - // Notification3 is passed by const reference. - //******************************************* - void notification(const Notification3& /*data3*/) - { - ++data3_count; - } - - int data1_count; - int data2_count; - int data3_count; -}; - -//***************************************************************************** -// The second observer type. -// If any one of the overloads is missing or a parameter declaration is incorrect -// then the class will be 'abstract' and will not compile. -//***************************************************************************** -class Observer2 : public ObserverType -{ -public: - - Observer2() - : data1_count(0) - , data2_count(0) - , data3_count(0) - { - } - - //******************************************* - // Notification1 is passed by value. - //******************************************* - void notification(Notification1 /*data1*/) - { - ++data1_count; - } - - //******************************************* - // Notification2 is passed by reference. - //******************************************* - void notification(Notification2& /*data2*/) - { - ++data2_count; - } - - //******************************************* - // Notification3 is passed by const reference. - //******************************************* - void notification(const Notification3& /*data3*/) - { - ++data3_count; - } - - int data1_count; - int data2_count; - int data3_count; -}; - -//***************************************************************************** -// The third observer type. -// If any one of the overloads is missing or a parameter declaration is incorrect -// then the class will be 'abstract' and will not compile. -//***************************************************************************** -class ObserverVoidInt : public ObserverVoidIntType -{ -public: - - ObserverVoidInt() - : data1_count(0) - , data2_count(0) - { - } - - //******************************************* - // Notification1 - //******************************************* - void notification() override - { - ++data1_count; - } - - //******************************************* - // Notification2 - //******************************************* - void notification(int) override - { - ++data2_count; - } - - int data1_count; - int data2_count; -}; - -namespace -{ - SUITE(test_observer) - { - //************************************************************************* - TEST(test_2_observables_2_observers_3_notifications) - { - // The observable objects. - Observable1 observable1; - Observable2 observable2; - - // The observer objects. - Observer1 observer1; - Observer2 observer2; - - observable1.add_observer(observer1); - - // Send the notifications. - observable1.send_notifications(); // Updates data1 & data2. - - CHECK_EQUAL(1, observer1.data1_count); - CHECK_EQUAL(1, observer1.data2_count); - CHECK_EQUAL(0, observer1.data3_count); - - CHECK_EQUAL(0, observer2.data1_count); - CHECK_EQUAL(0, observer2.data2_count); - CHECK_EQUAL(0, observer2.data3_count); - - observable2.send_notifications(); // Updates data3. observeable2 has no observers yet. - - CHECK_EQUAL(1, observer1.data1_count); - CHECK_EQUAL(1, observer1.data2_count); - CHECK_EQUAL(0, observer1.data3_count); - - CHECK_EQUAL(0, observer2.data1_count); - CHECK_EQUAL(0, observer2.data2_count); - CHECK_EQUAL(0, observer2.data3_count); - - // Add an observer to both. - observable1.add_observer(observer2); - observable2.add_observer(observer2); - - // Send the notifications. - observable1.send_notifications(); // Updates data1 & data2. - - CHECK_EQUAL(2, observer1.data1_count); - CHECK_EQUAL(2, observer1.data2_count); - CHECK_EQUAL(0, observer1.data3_count); - - CHECK_EQUAL(1, observer2.data1_count); - CHECK_EQUAL(1, observer2.data2_count); - CHECK_EQUAL(0, observer2.data3_count); - - observable2.send_notifications(); // Updates data3. - - CHECK_EQUAL(2, observer1.data1_count); - CHECK_EQUAL(2, observer1.data2_count); - CHECK_EQUAL(0, observer1.data3_count); - - CHECK_EQUAL(1, observer2.data1_count); - CHECK_EQUAL(1, observer2.data2_count); - CHECK_EQUAL(1, observer2.data3_count); - - observable1.remove_observer(observer1); - - // Send the notifications. - observable1.send_notifications(); // Updates data1 & data2. - - CHECK_EQUAL(2, observer1.data1_count); - CHECK_EQUAL(2, observer1.data2_count); - CHECK_EQUAL(0, observer1.data3_count); - - CHECK_EQUAL(2, observer2.data1_count); - CHECK_EQUAL(2, observer2.data2_count); - CHECK_EQUAL(1, observer2.data3_count); - - observable2.send_notifications(); // Updates data3. - - CHECK_EQUAL(2, observer1.data1_count); - CHECK_EQUAL(2, observer1.data2_count); - CHECK_EQUAL(0, observer1.data3_count); - - CHECK_EQUAL(2, observer2.data1_count); - CHECK_EQUAL(2, observer2.data2_count); - CHECK_EQUAL(2, observer2.data3_count); - } - - //************************************************************************* - TEST(test_observable_2_observers_enable_disable) - { - // The observable objects. - Observable1 observable1; - - // The observer objects. - Observer1 observer1; - Observer2 observer2; - - observable1.add_observer(observer1); - observable1.add_observer(observer2); - - // Send the notifications. - observable1.send_notifications(); - - CHECK_EQUAL(1, observer1.data1_count); - CHECK_EQUAL(1, observer2.data1_count); - - // Disable observer1. Send the notifications. - observable1.disable_observer(observer1); - observable1.send_notifications(); - - CHECK_EQUAL(1, observer1.data1_count); - CHECK_EQUAL(2, observer2.data1_count); - - // Disable observer2. Send the notifications. - observable1.enable_observer(observer2, false); - observable1.send_notifications(); - - CHECK_EQUAL(1, observer1.data1_count); - CHECK_EQUAL(2, observer2.data1_count); - - // Enable observer1. Send the notifications. - observable1.enable_observer(observer1); - observable1.send_notifications(); - - CHECK_EQUAL(2, observer1.data1_count); - CHECK_EQUAL(2, observer2.data1_count); - - // Enable observer2. Send the notifications. - observable1.enable_observer(observer2, true); - observable1.send_notifications(); - - CHECK_EQUAL(3, observer1.data1_count); - CHECK_EQUAL(3, observer2.data1_count); - } - - //************************************************************************* - TEST(test_8_notifications) - { - typedef etl::observer, Notification<2>, Notification<3>, Notification<4>, Notification<5>, Notification<6>, Notification<7>, Notification<8> > Observer; - - class Observable : public etl::observable - { - }; - - // This test just needs to compile without errors. - CHECK(true); - } - - //************************************************************************* - TEST(test_7_notifications) - { - typedef etl::observer, Notification<2>, Notification<3>, Notification<4>, Notification<5>, Notification<6>, Notification<7> > Observer; - - class Observable : public etl::observable - { - }; - - // This test just needs to compile without errors. - CHECK(true); - } - - //************************************************************************* - TEST(test_6_notifications) - { - typedef etl::observer, Notification<2>, Notification<3>, Notification<4>, Notification<5>, Notification<6> > Observer; - - class Observable : public etl::observable - { - }; - - // This test just needs to compile without errors. - CHECK(true); - } - - //************************************************************************* - TEST(test_5_notifications) - { - typedef etl::observer, Notification<2>, Notification<3>, Notification<4>, Notification<5> > Observer; - - class Observable : public etl::observable - { - }; - - // This test just needs to compile without errors. - CHECK(true); - } - - //************************************************************************* - TEST(test_4_notifications) - { - typedef etl::observer, Notification<2>, Notification<3>, Notification<4> > Observer; - - class Observable : public etl::observable - { - }; - - // This test just needs to compile without errors. - CHECK(true); - } - - //************************************************************************* - TEST(test_3_notifications) - { - typedef etl::observer, Notification<2>, Notification<3> > Observer; - - class Observable : public etl::observable - { - }; - - // This test just needs to compile without errors. - CHECK(true); - } - - //************************************************************************* - TEST(test_2_notifications) - { - typedef etl::observer, Notification<2> > Observer; - - class Observable : public etl::observable - { - }; - - // This test just needs to compile without errors. - CHECK(true); - } - - //************************************************************************* - TEST(test_1_notification) - { - typedef etl::observer > Observer; - - class Observable : public etl::observable - { - }; - - // This test just needs to compile without errors. - CHECK(true); - } - - //************************************************************************* - TEST(test_observer_list) - { - class Observer : public etl::observer - { - void notification(Notification1) {} - }; - - class Observable : public etl::observable - { - }; - - Observable observable; - - Observer observer1; - Observer observer2; - Observer observer3; - Observer observer4; - Observer observer5; - - observable.add_observer(observer1); - CHECK_EQUAL(1UL, observable.number_of_observers()); - - observable.add_observer(observer2); - CHECK_EQUAL(2UL, observable.number_of_observers()); - - observable.add_observer(observer3); - CHECK_EQUAL(3UL, observable.number_of_observers()); - - observable.add_observer(observer2); - CHECK_EQUAL(3UL, observable.number_of_observers()); - - observable.add_observer(observer4); - CHECK_EQUAL(4UL, observable.number_of_observers()); - - CHECK_THROW(observable.add_observer(observer5), etl::observer_list_full); - - CHECK(observable.remove_observer(observer3)); - CHECK_EQUAL(3UL, observable.number_of_observers()); - - // Try again. - CHECK(!observable.remove_observer(observer3)); - CHECK_EQUAL(3UL, observable.number_of_observers()); - - observable.clear_observers(); - CHECK_EQUAL(0UL, observable.number_of_observers()); - } - - //************************************************************************* - TEST(test_void_int_observable) - { - // The observable objects. - ObservableVoidInt observable; - - // The observer objects. - ObserverVoidInt observer; - - observable.add_observer(observer); - - // Send the notifications. - observable.send_notifications(); - CHECK_EQUAL(1U, observer.data1_count); - CHECK_EQUAL(0U, observer.data2_count); - - observable.send_notifications(1); - CHECK_EQUAL(1U, observer.data1_count); - CHECK_EQUAL(1U, observer.data2_count); - } - } -} - - -#endif - diff --git a/test/test_visitor_with_type_list.cpp b/test/test_visitor_with_type_list.cpp deleted file mode 100644 index 04660ee9..00000000 --- a/test/test_visitor_with_type_list.cpp +++ /dev/null @@ -1,761 +0,0 @@ -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -https://www.etlcpp.com - -Copyright(c) 2025 John Wellbelove - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions : - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -******************************************************************************/ - -#include "unit_test_framework.h" - -#include "etl/visitor.h" - -#if ETL_USING_CPP11 && !defined(ETL_VISITOR_FORCE_CPP03_IMPLEMENTATION) - -//***************************************************************************** -// Pre-declare the data types. -//***************************************************************************** -class Square; -class Circle; -class Triangle; - -//***************************************************************************** -// What classes do you want the visitors to handle? -// Square will be passed by reference. -// Circle will be passed by reference. -// Triangle will be passed by const reference. -//***************************************************************************** -using DrawTypes = etl::type_list; -using DrawVisitorType = etl::visitor; - -//***************************************************************************** -// What classes do you want the visitors to handle? -// Square will be passed by reference. -// Triangle will be passed by const reference. -//***************************************************************************** -using LogTypes = etl::type_list; -using LogVisitorType = etl::visitor; - -//***************************************************************************** -// Base shape. -//***************************************************************************** -using VisitorTypes = etl::type_list; - -class ShapeBase : public etl::visitable -{ -}; - -//***************************************************************************** -// Square accepts draw & log visitors. -//***************************************************************************** -class Square : public ShapeBase -{ -public: - - void accept(DrawVisitorType& visitor) - { - visitor.visit(*this); - } - - void accept(LogVisitorType& visitor) - { - visitor.visit(*this); - } -}; - -//***************************************************************************** -// Circle only accepts draw visitors. -//***************************************************************************** -class Circle : public ShapeBase -{ -public: - - void accept(DrawVisitorType& visitor) - { - visitor.visit(*this); - } - - void accept(LogVisitorType&) - { - } -}; - -//***************************************************************************** -// Triangle accepts draw & log visitors. -//***************************************************************************** -class Triangle : public ShapeBase -{ -public: - - void accept(DrawVisitorType& visitor) - { - visitor.visit(*this); - } - - void accept(LogVisitorType& visitor) - { - visitor.visit(*this); - } -}; - - -//***************************************************************************** -// Generic other shapes. -//***************************************************************************** -template -class Shape : public etl::visitable -{ -public: - - void accept(TVisitor& visitor) - { - visitor.visit(*this); - } -}; - -//***************************************************************************** -class DrawVisitor : public DrawVisitorType -{ -public: - - DrawVisitor() - : square_called(false), - circle_called(false), - triangle_called(false) - { - } - - void visit(Square&) - { - square_called = true; - } - - void visit(Circle&) - { - circle_called = true; - } - - void visit(const Triangle&) - { - triangle_called = true; - } - - bool square_called; - bool circle_called; - bool triangle_called; -}; - -//***************************************************************************** -class LogVisitor : public LogVisitorType -{ -public: - - LogVisitor() - : square_called(false), - circle_called(false), - triangle_called(false) - { - } - - void visit(Square&) - { - square_called = true; - } - - // SHOULD NEVER BE CALLED. - void visit(Circle&) - { - circle_called = true; - } - - void visit(const Triangle&) - { - triangle_called = true; - } - - bool square_called; - bool circle_called; - bool triangle_called; -}; - -namespace -{ - SUITE(test_visitor) - { - //************************************************************************* - TEST(test_two_visitors_three_visitables) - { - DrawVisitor draw_visitor; - LogVisitor log_visitor; - - Square square; - Circle circle; - Triangle triangle; - - ShapeBase* pShapeBase; - - CHECK_EQUAL(false, draw_visitor.square_called); - CHECK_EQUAL(false, draw_visitor.circle_called); - CHECK_EQUAL(false, draw_visitor.triangle_called); - CHECK_EQUAL(false, log_visitor.square_called); - CHECK_EQUAL(false, log_visitor.circle_called); - CHECK_EQUAL(false, log_visitor.triangle_called); - - square.accept(draw_visitor); - square.accept(log_visitor); - - CHECK_EQUAL(true, draw_visitor.square_called); - CHECK_EQUAL(false, draw_visitor.circle_called); - CHECK_EQUAL(false, draw_visitor.triangle_called); - CHECK_EQUAL(true, log_visitor.square_called); - CHECK_EQUAL(false, log_visitor.circle_called); - CHECK_EQUAL(false, log_visitor.triangle_called); - - circle.accept(draw_visitor); - - CHECK_EQUAL(true, draw_visitor.square_called); - CHECK_EQUAL(true, draw_visitor.circle_called); - CHECK_EQUAL(false, draw_visitor.triangle_called); - CHECK_EQUAL(true, log_visitor.square_called); - CHECK_EQUAL(false, log_visitor.circle_called); - CHECK_EQUAL(false, log_visitor.triangle_called); - - pShapeBase = ▵ - pShapeBase->accept(draw_visitor); - pShapeBase->accept(log_visitor); - - CHECK_EQUAL(true, draw_visitor.square_called); - CHECK_EQUAL(true, draw_visitor.circle_called); - CHECK_EQUAL(true, draw_visitor.triangle_called); - CHECK_EQUAL(true, log_visitor.square_called); - CHECK_EQUAL(false, log_visitor.circle_called); - CHECK_EQUAL(true, log_visitor.triangle_called); - } - - //************************************************************************* - TEST(test_1_visitor) - { - class AShape; - class ShapeVisitor1 : public etl::visitor - { - void visit(AShape&) {} - }; - - class AShape : public etl::visitable - { - public: - - void accept(ShapeVisitor1&) {} - }; - - // This test just needs to compile without errors. - CHECK(true); - } - - //************************************************************************* - TEST(test_2_visitor) - { - class AShape; - class ShapeVisitor1 : public etl::visitor - { - void visit(AShape&) {} - }; - - class ShapeVisitor2 : public etl::visitor - { - void visit(AShape&) {} - }; - - class AShape : public etl::visitable - { - public: - - void accept(ShapeVisitor1&) {} - void accept(ShapeVisitor2&) {} - }; - - // This test just needs to compile without errors. - CHECK(true); - } - - //************************************************************************* - TEST(test_3_visitor) - { - class AShape; - class ShapeVisitor1 : public etl::visitor - { - void visit(AShape&) {} - }; - - class ShapeVisitor2 : public etl::visitor - { - void visit(AShape&) {} - }; - - class ShapeVisitor3 : public etl::visitor - { - void visit(AShape&) {} - }; - - class AShape : public etl::visitable - { - public: - - void accept(ShapeVisitor1&) {} - void accept(ShapeVisitor2&) {} - void accept(ShapeVisitor3&) {} - }; - - // This test just needs to compile without errors. - CHECK(true); - } - - //************************************************************************* - TEST(test_4_visitor) - { - class AShape; - class ShapeVisitor1 : public etl::visitor - { - void visit(AShape&) {} - }; - - class ShapeVisitor2 : public etl::visitor - { - void visit(AShape&) {} - }; - - class ShapeVisitor3 : public etl::visitor - { - void visit(AShape&) {} - }; - - class ShapeVisitor4 : public etl::visitor - { - void visit(AShape&) {} - }; - - using ShapeVisitorTypes = etl::type_list; - - class AShape : public etl::visitable - { - public: - - void accept(ShapeVisitor1&) {} - void accept(ShapeVisitor2&) {} - void accept(ShapeVisitor3&) {} - void accept(ShapeVisitor4&) {} - }; - - // This test just needs to compile without errors. - CHECK(true); - } - - //************************************************************************* - TEST(test_1_visitable) - { - class ShapeVisitor : public etl::visitor > - { - public: - - void visit(Shape<1, ShapeVisitor>) {} - }; - - // This test just needs to compile without errors. - CHECK(true); - } - - //************************************************************************* - TEST(test_2_visitable) - { - class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor> > - { - public: - - void visit(Shape<1, ShapeVisitor>) {} - void visit(Shape<2, ShapeVisitor>) {} - }; - - // This test just needs to compile without errors. - CHECK(true); - } - - //************************************************************************* - TEST(test_3_visitable) - { - class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor>, Shape<3, ShapeVisitor> > - { - public: - - void visit(Shape<1, ShapeVisitor>) {} - void visit(Shape<2, ShapeVisitor>) {} - void visit(Shape<3, ShapeVisitor>) {} - }; - - // This test just needs to compile without errors. - CHECK(true); - } - - //************************************************************************* - TEST(test_4_visitable) - { - class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor>, Shape<3, ShapeVisitor>, Shape<4, ShapeVisitor> > - { - public: - - void visit(Shape<1, ShapeVisitor>) {} - void visit(Shape<2, ShapeVisitor>) {} - void visit(Shape<3, ShapeVisitor>) {} - void visit(Shape<4, ShapeVisitor>) {} - }; - - // This test just needs to compile without errors. - CHECK(true); - } - - //************************************************************************* - TEST(test_5_visitable) - { - class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor>, Shape<3, ShapeVisitor>, Shape<4, ShapeVisitor>, - Shape<5, ShapeVisitor> > - { - public: - - void visit(Shape<1, ShapeVisitor>) {} - void visit(Shape<2, ShapeVisitor>) {} - void visit(Shape<3, ShapeVisitor>) {} - void visit(Shape<4, ShapeVisitor>) {} - void visit(Shape<5, ShapeVisitor>) {} - }; - - // This test just needs to compile without errors. - CHECK(true); - } - - //************************************************************************* - TEST(test_6_visitable) - { - class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor>, Shape<3, ShapeVisitor>, Shape<4, ShapeVisitor>, - Shape<5, ShapeVisitor>, Shape<6, ShapeVisitor> > - { - public: - - void visit(Shape<1, ShapeVisitor>) {} - void visit(Shape<2, ShapeVisitor>) {} - void visit(Shape<3, ShapeVisitor>) {} - void visit(Shape<4, ShapeVisitor>) {} - void visit(Shape<5, ShapeVisitor>) {} - void visit(Shape<6, ShapeVisitor>) {} - }; - - // This test just needs to compile without errors. - CHECK(true); - } - - //************************************************************************* - TEST(test_7_visitable) - { - class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor>, Shape<3, ShapeVisitor>, Shape<4, ShapeVisitor>, - Shape<5, ShapeVisitor>, Shape<6, ShapeVisitor>, Shape<7, ShapeVisitor> > - { - public: - - void visit(Shape<1, ShapeVisitor>) {} - void visit(Shape<2, ShapeVisitor>) {} - void visit(Shape<3, ShapeVisitor>) {} - void visit(Shape<4, ShapeVisitor>) {} - void visit(Shape<5, ShapeVisitor>) {} - void visit(Shape<6, ShapeVisitor>) {} - void visit(Shape<7, ShapeVisitor>) {} - }; - - // This test just needs to compile without errors. - CHECK(true); - } - - //************************************************************************* - TEST(test_8_visitable) - { - class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor>, Shape<3, ShapeVisitor>, Shape<4, ShapeVisitor>, - Shape<5, ShapeVisitor>, Shape<6, ShapeVisitor>, Shape<7, ShapeVisitor>, Shape<8, ShapeVisitor> > - { - public: - - void visit(Shape<1, ShapeVisitor>) {} - void visit(Shape<2, ShapeVisitor>) {} - void visit(Shape<3, ShapeVisitor>) {} - void visit(Shape<4, ShapeVisitor>) {} - void visit(Shape<5, ShapeVisitor>) {} - void visit(Shape<6, ShapeVisitor>) {} - void visit(Shape<7, ShapeVisitor>) {} - void visit(Shape<8, ShapeVisitor>) {} - }; - - // This test just needs to compile without errors. - CHECK(true); - } - - //************************************************************************* - TEST(test_9_visitable) - { - class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor>, Shape<3, ShapeVisitor>, Shape<4, ShapeVisitor>, - Shape<5, ShapeVisitor>, Shape<6, ShapeVisitor>, Shape<7, ShapeVisitor>, Shape<8, ShapeVisitor>, - Shape<9, ShapeVisitor> > - { - public: - - void visit(Shape<1, ShapeVisitor>) {} - void visit(Shape<2, ShapeVisitor>) {} - void visit(Shape<3, ShapeVisitor>) {} - void visit(Shape<4, ShapeVisitor>) {} - void visit(Shape<5, ShapeVisitor>) {} - void visit(Shape<6, ShapeVisitor>) {} - void visit(Shape<7, ShapeVisitor>) {} - void visit(Shape<8, ShapeVisitor>) {} - void visit(Shape<9, ShapeVisitor>) {} - }; - - // This test just needs to compile without errors. - CHECK(true); - } - - //************************************************************************* - TEST(test_10_visitable) - { - class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor>, Shape<3, ShapeVisitor>, Shape<4, ShapeVisitor>, - Shape<5, ShapeVisitor>, Shape<6, ShapeVisitor>, Shape<7, ShapeVisitor>, Shape<8, ShapeVisitor>, - Shape<9, ShapeVisitor>, Shape<10, ShapeVisitor> > - { - public: - - void visit(Shape<1, ShapeVisitor>) {} - void visit(Shape<2, ShapeVisitor>) {} - void visit(Shape<3, ShapeVisitor>) {} - void visit(Shape<4, ShapeVisitor>) {} - void visit(Shape<5, ShapeVisitor>) {} - void visit(Shape<6, ShapeVisitor>) {} - void visit(Shape<7, ShapeVisitor>) {} - void visit(Shape<8, ShapeVisitor>) {} - void visit(Shape<9, ShapeVisitor>) {} - void visit(Shape<10, ShapeVisitor>) {} - }; - - // This test just needs to compile without errors. - CHECK(true); - } - - - //************************************************************************* - TEST(test_11_visitable) - { - class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor>, Shape<3, ShapeVisitor>, Shape<4, ShapeVisitor>, - Shape<5, ShapeVisitor>, Shape<6, ShapeVisitor>, Shape<7, ShapeVisitor>, Shape<8, ShapeVisitor>, - Shape<9, ShapeVisitor>, Shape<10, ShapeVisitor>, Shape<11, ShapeVisitor> > - { - public: - - void visit(Shape<1, ShapeVisitor>) {} - void visit(Shape<2, ShapeVisitor>) {} - void visit(Shape<3, ShapeVisitor>) {} - void visit(Shape<4, ShapeVisitor>) {} - void visit(Shape<5, ShapeVisitor>) {} - void visit(Shape<6, ShapeVisitor>) {} - void visit(Shape<7, ShapeVisitor>) {} - void visit(Shape<8, ShapeVisitor>) {} - void visit(Shape<9, ShapeVisitor>) {} - void visit(Shape<10, ShapeVisitor>) {} - void visit(Shape<11, ShapeVisitor>) {} - }; - - // This test just needs to compile without errors. - CHECK(true); - } - - //************************************************************************* - TEST(test_12_visitable) - { - class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor>, Shape<3, ShapeVisitor>, Shape<4, ShapeVisitor>, - Shape<5, ShapeVisitor>, Shape<6, ShapeVisitor>, Shape<7, ShapeVisitor>, Shape<8, ShapeVisitor>, - Shape<9, ShapeVisitor>, Shape<10, ShapeVisitor>, Shape<11, ShapeVisitor>, Shape<12, ShapeVisitor> > - { - public: - - void visit(Shape<1, ShapeVisitor>) {} - void visit(Shape<2, ShapeVisitor>) {} - void visit(Shape<3, ShapeVisitor>) {} - void visit(Shape<4, ShapeVisitor>) {} - void visit(Shape<5, ShapeVisitor>) {} - void visit(Shape<6, ShapeVisitor>) {} - void visit(Shape<7, ShapeVisitor>) {} - void visit(Shape<8, ShapeVisitor>) {} - void visit(Shape<9, ShapeVisitor>) {} - void visit(Shape<10, ShapeVisitor>) {} - void visit(Shape<11, ShapeVisitor>) {} - void visit(Shape<12, ShapeVisitor>) {} - }; - - // This test just needs to compile without errors. - CHECK(true); - } - - //************************************************************************* - TEST(test_13_visitable) - { - class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor>, Shape<3, ShapeVisitor>, Shape<4, ShapeVisitor>, - Shape<5, ShapeVisitor>, Shape<6, ShapeVisitor>, Shape<7, ShapeVisitor>, Shape<8, ShapeVisitor>, - Shape<9, ShapeVisitor>, Shape<10, ShapeVisitor>, Shape<11, ShapeVisitor>, Shape<12, ShapeVisitor>, - Shape<13, ShapeVisitor> > - { - public: - - void visit(Shape<1, ShapeVisitor>) {} - void visit(Shape<2, ShapeVisitor>) {} - void visit(Shape<3, ShapeVisitor>) {} - void visit(Shape<4, ShapeVisitor>) {} - void visit(Shape<5, ShapeVisitor>) {} - void visit(Shape<6, ShapeVisitor>) {} - void visit(Shape<7, ShapeVisitor>) {} - void visit(Shape<8, ShapeVisitor>) {} - void visit(Shape<9, ShapeVisitor>) {} - void visit(Shape<10, ShapeVisitor>) {} - void visit(Shape<11, ShapeVisitor>) {} - void visit(Shape<12, ShapeVisitor>) {} - void visit(Shape<13, ShapeVisitor>) {} - }; - - // This test just needs to compile without errors. - CHECK(true); - } - - //************************************************************************* - TEST(test_14_visitable) - { - class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor>, Shape<3, ShapeVisitor>, Shape<4, ShapeVisitor>, - Shape<5, ShapeVisitor>, Shape<6, ShapeVisitor>, Shape<7, ShapeVisitor>, Shape<8, ShapeVisitor>, - Shape<9, ShapeVisitor>, Shape<10, ShapeVisitor>, Shape<11, ShapeVisitor>, Shape<12, ShapeVisitor>, - Shape<13, ShapeVisitor>, Shape<14, ShapeVisitor> > - { - public: - - void visit(Shape<1, ShapeVisitor>) {} - void visit(Shape<2, ShapeVisitor>) {} - void visit(Shape<3, ShapeVisitor>) {} - void visit(Shape<4, ShapeVisitor>) {} - void visit(Shape<5, ShapeVisitor>) {} - void visit(Shape<6, ShapeVisitor>) {} - void visit(Shape<7, ShapeVisitor>) {} - void visit(Shape<8, ShapeVisitor>) {} - void visit(Shape<9, ShapeVisitor>) {} - void visit(Shape<10, ShapeVisitor>) {} - void visit(Shape<11, ShapeVisitor>) {} - void visit(Shape<12, ShapeVisitor>) {} - void visit(Shape<13, ShapeVisitor>) {} - void visit(Shape<14, ShapeVisitor>) {} - }; - - // This test just needs to compile without errors. - CHECK(true); - } - - //************************************************************************* - TEST(test_15_visitable) - { - class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor>, Shape<3, ShapeVisitor>, Shape<4, ShapeVisitor>, - Shape<5, ShapeVisitor>, Shape<6, ShapeVisitor>, Shape<7, ShapeVisitor>, Shape<8, ShapeVisitor>, - Shape<9, ShapeVisitor>, Shape<10, ShapeVisitor>, Shape<11, ShapeVisitor>, Shape<12, ShapeVisitor>, - Shape<13, ShapeVisitor>, Shape<14, ShapeVisitor>, Shape<15, ShapeVisitor> > - { - public: - - void visit(Shape<1, ShapeVisitor>) {} - void visit(Shape<2, ShapeVisitor>) {} - void visit(Shape<3, ShapeVisitor>) {} - void visit(Shape<4, ShapeVisitor>) {} - void visit(Shape<5, ShapeVisitor>) {} - void visit(Shape<6, ShapeVisitor>) {} - void visit(Shape<7, ShapeVisitor>) {} - void visit(Shape<8, ShapeVisitor>) {} - void visit(Shape<9, ShapeVisitor>) {} - void visit(Shape<10, ShapeVisitor>) {} - void visit(Shape<11, ShapeVisitor>) {} - void visit(Shape<12, ShapeVisitor>) {} - void visit(Shape<13, ShapeVisitor>) {} - void visit(Shape<14, ShapeVisitor>) {} - void visit(Shape<15, ShapeVisitor>) {} - }; - - // This test just needs to compile without errors. - CHECK(true); - } - - //************************************************************************* - TEST(test_16_visitable) - { - class ShapeVisitor : public etl::visitor , Shape<2, ShapeVisitor>, Shape<3, ShapeVisitor>, Shape<4, ShapeVisitor>, - Shape<5, ShapeVisitor>, Shape<6, ShapeVisitor>, Shape<7, ShapeVisitor>, Shape<8, ShapeVisitor>, - Shape<9, ShapeVisitor>, Shape<10, ShapeVisitor>, Shape<11, ShapeVisitor>, Shape<12, ShapeVisitor>, - Shape<13, ShapeVisitor>, Shape<14, ShapeVisitor>, Shape<15, ShapeVisitor>, Shape<16, ShapeVisitor> > - { - public: - - void visit(Shape<1, ShapeVisitor>) {} - void visit(Shape<2, ShapeVisitor>) {} - void visit(Shape<3, ShapeVisitor>) {} - void visit(Shape<4, ShapeVisitor>) {} - void visit(Shape<5, ShapeVisitor>) {} - void visit(Shape<6, ShapeVisitor>) {} - void visit(Shape<7, ShapeVisitor>) {} - void visit(Shape<8, ShapeVisitor>) {} - void visit(Shape<9, ShapeVisitor>) {} - void visit(Shape<10, ShapeVisitor>) {} - void visit(Shape<11, ShapeVisitor>) {} - void visit(Shape<12, ShapeVisitor>) {} - void visit(Shape<13, ShapeVisitor>) {} - void visit(Shape<14, ShapeVisitor>) {} - void visit(Shape<15, ShapeVisitor>) {} - void visit(Shape<16, ShapeVisitor>) {} - }; - - // This test just needs to compile without errors. - CHECK(true); - } - - //************************************************************************* - struct NotVisitor {}; - - TEST(test_is_visitor) - { -#if ETL_USING_CPP17 - CHECK_TRUE(etl::is_visitor_v); - CHECK_TRUE(etl::is_visitor_v); - CHECK_FALSE(etl::is_visitor_v); -#else - CHECK_TRUE(etl::is_visitor::value); - CHECK_TRUE(etl::is_visitor::value); - CHECK_FALSE(etl::is_visitor::value); -#endif - } - } -} - -#endif - From d7dc1281ae194cd21db2a3ca415226994b8e7239 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 28 Jan 2026 17:20:01 +0000 Subject: [PATCH 103/298] Fix iter_swap namespace --- include/etl/algorithm.h | 2 +- include/etl/private/ivectorpointer.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/etl/algorithm.h b/include/etl/algorithm.h index 88b8f7b6..a5879e2c 100644 --- a/include/etl/algorithm.h +++ b/include/etl/algorithm.h @@ -186,7 +186,7 @@ namespace etl { while (first1 != last1) { - iter_swap(first1, first2); + etl::iter_swap(first1, first2); ++first1; ++first2; } diff --git a/include/etl/private/ivectorpointer.h b/include/etl/private/ivectorpointer.h index f9f6dd7e..597fc8ab 100644 --- a/include/etl/private/ivectorpointer.h +++ b/include/etl/private/ivectorpointer.h @@ -483,7 +483,7 @@ namespace etl ivector& smaller = other.size() > this->size() ? *this : other; ivector& larger = other.size() > this->size() ? other : *this; - ETL_OR_STD::swap_ranges(smaller.begin(), smaller.end(), larger.begin()); + etl::swap_ranges(smaller.begin(), smaller.end(), larger.begin()); typename ivector::iterator larger_itr = etl::next(larger.begin(), smaller.size()); @@ -931,7 +931,7 @@ namespace etl ivector& smaller = other.size() > this->size() ? *this : other; ivector& larger = other.size() > this->size() ? other : *this; - ETL_OR_STD::swap_ranges(smaller.begin(), smaller.end(), larger.begin()); + etl::swap_ranges(smaller.begin(), smaller.end(), larger.begin()); typename ivector::iterator larger_itr = etl::next(larger.begin(), smaller.size()); From 69b741adb82fe73192a62b0080b714227e443cdb Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 28 Jan 2026 17:22:37 +0000 Subject: [PATCH 104/298] Add type_list functionality to etl::variant using etl::variant_from_type_list --- include/etl/private/variant_variadic.h | 35 ++++++----- test/test_variant_variadic.cpp | 87 ++++++++++++++------------ 2 files changed, 64 insertions(+), 58 deletions(-) diff --git a/include/etl/private/variant_variadic.h b/include/etl/private/variant_variadic.h index ddcdd33c..afbf7243 100644 --- a/include/etl/private/variant_variadic.h +++ b/include/etl/private/variant_variadic.h @@ -253,7 +253,7 @@ namespace etl template struct variant_alternative> { - using type = etl::nth_type_t::type_list>; + using type = etl::nth_type_t; }; template @@ -1218,26 +1218,13 @@ namespace etl size_t type_id; }; - //*************************************************************************** - /// Delcare a variant using an etl::type_list. - //*************************************************************************** - template - class variant> : public etl::variant - { - public: - - using base_type = etl::variant; - using type_list = typename base_type::type_list; - using base_type::base_type; // Inherit all ctors - }; - //*************************************************************************** /// Checks if the variant v holds the alternative T. //*************************************************************************** template ETL_CONSTEXPR14 bool holds_alternative(const etl::variant& v) ETL_NOEXCEPT { - constexpr size_t Index = etl::type_list_index_of_type::type_list, T>::value; + constexpr size_t Index = etl::type_list_index_of_type, T>::value; return (Index == variant_npos) ? false : (v.index() == Index); } @@ -1268,7 +1255,7 @@ namespace etl get(etl::variant& v) { #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11) - static_assert(Index < etl::type_list_size::type_list>::value, "Index out of range"); + static_assert(Index < etl::type_list_size>::value, "Index out of range"); #endif ETL_ASSERT(Index == v.index(), ETL_ERROR(etl::variant_incorrect_type_exception)); @@ -1441,7 +1428,7 @@ namespace etl template struct variant_size> - : etl::integral_constant::type_list>::value> + : etl::integral_constant>::value> { }; @@ -1867,5 +1854,19 @@ namespace etl } } #endif + + //*************************************************************************** + /// Helper to turn etl::type_list into etl::variant + template + struct variant_from_type_list; + + template + struct variant_from_type_list> + { + using type = etl::variant; + }; + + template + using variant_from_type_list_t = typename variant_from_type_list::type; } #endif diff --git a/test/test_variant_variadic.cpp b/test/test_variant_variadic.cpp index 6e91fa34..bf684bcd 100644 --- a/test/test_variant_variadic.cpp +++ b/test/test_variant_variadic.cpp @@ -427,10 +427,10 @@ namespace { TEST(test_alignment) { - typedef etl::variant test_variant_a; - typedef etl::variant test_variant_b; - typedef etl::variant test_variant_c; - typedef etl::variant test_variant_d; + using test_variant_a = etl::variant; + using test_variant_b = etl::variant; + using test_variant_c = etl::variant; + using test_variant_d = etl::variant; static test_variant_a a(char('1')); static test_variant_b b(short(2)); @@ -443,6 +443,48 @@ namespace CHECK((uintptr_t(&etl::get(d)) % uintptr_t(etl::alignment_of::value)) == 0); } + //************************************************************************* + TEST(test_variant_from_type_list) + { + struct DefaultConstructible + { + DefaultConstructible() + : value(1) + { + } + + int value = 0; + }; + + using type_list = etl::type_list; + using test_variant_t = etl::variant_from_type_list_t; + using normal_variant_t = etl::variant; + + CHECK_NO_THROW(test_variant_t variant_etl); + + test_variant_t variant_etl; + + // Are the type lists the same? + CHECK_TRUE((std::is_same::value)); + + // Are the variants the same? + CHECK_TRUE((std::is_same::value)); + + CHECK_TRUE(etl::holds_alternative(variant_etl)); + CHECK_FALSE(etl::holds_alternative(variant_etl)); + CHECK_FALSE(etl::holds_alternative(variant_etl)); + CHECK_EQUAL(1, etl::get<0U>(variant_etl).value); + + CHECK_TRUE(etl::holds_alternative<0U>(variant_etl)); + CHECK_FALSE(etl::holds_alternative<1U>(variant_etl)); + CHECK_FALSE(etl::holds_alternative<2U>(variant_etl)); + + CHECK_TRUE(etl::holds_alternative(0U, variant_etl)); + CHECK_FALSE(etl::holds_alternative(1U, variant_etl)); + CHECK_FALSE(etl::holds_alternative(2U, variant_etl)); + CHECK_FALSE(etl::holds_alternative(99U, variant_etl)); + } + //************************************************************************* TEST(test_constructor_default) { @@ -479,43 +521,6 @@ namespace CHECK_FALSE(etl::holds_alternative(99U, variant_etl)); } - //************************************************************************* - TEST(test_constructor_default_variant_from_type_list) - { - struct DefaultConstructible - { - DefaultConstructible() - : value(1) - { - } - - int value = 0; - }; - - using variant_types = etl::type_list; - using test_variant_t = etl::variant; - - CHECK_NO_THROW(test_variant_t variant_etl); - - test_variant_t variant_etl; - - CHECK_TRUE((std::is_same::value)); - - CHECK_TRUE(etl::holds_alternative(variant_etl)); - CHECK_FALSE(etl::holds_alternative(variant_etl)); - CHECK_FALSE(etl::holds_alternative(variant_etl)); - CHECK_EQUAL(1, etl::get<0U>(variant_etl).value); - - CHECK_TRUE(etl::holds_alternative<0U>(variant_etl)); - CHECK_FALSE(etl::holds_alternative<1U>(variant_etl)); - CHECK_FALSE(etl::holds_alternative<2U>(variant_etl)); - - CHECK_TRUE(etl::holds_alternative(0U, variant_etl)); - CHECK_FALSE(etl::holds_alternative(1U, variant_etl)); - CHECK_FALSE(etl::holds_alternative(2U, variant_etl)); - CHECK_FALSE(etl::holds_alternative(99U, variant_etl)); - } - //************************************************************************* TEST(test_constructor_value) { From 746761124c3080c47fc24654f1164336f3e67547 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 28 Jan 2026 17:24:45 +0000 Subject: [PATCH 105/298] Add type_list functionality to etl::message_packet using etl::message_packet_from_type_list --- include/etl/message_packet.h | 80 ++++++------------------------------ test/test_message_packet.cpp | 15 ++++++- 2 files changed, 26 insertions(+), 69 deletions(-) diff --git a/include/etl/message_packet.h b/include/etl/message_packet.h index aa449cb8..d729c940 100644 --- a/include/etl/message_packet.h +++ b/include/etl/message_packet.h @@ -384,17 +384,19 @@ namespace etl }; //*************************************************************************** - // The definition for all message types. - //*************************************************************************** - template - class message_packet> : public etl::message_packet - { - public: + /// Helper to turn etl::type_list into etl::message_packet + template + struct message_packet_from_type_list; - using base_type = etl::message_packet; - using base_type::base_type; // Inherit all ctors + template + struct message_packet_from_type_list> + { + using type = etl::message_packet; }; + template + using message_packet_from_type_list_t = typename message_packet_from_type_list::type; + #else //*************************************************************************** @@ -4940,9 +4942,8 @@ namespace etl { public: - ETL_STATIC_ASSERT(!etl::is_type_list::value, - "T1 must not be an etl::type_list. " - "Use etl::message_packet> only with the C++17 variadic overload."); + //ETL_STATIC_ASSERT(!etl::is_type_list::value, + // "message_packet does not accept an etl::type_list before C++17, or when ETL_MESSAGE_PACKET_FORCE_CPP03_IMPLEMENTATION is defined"); #if ETL_USING_CPP11 using message_types = etl::type_list; @@ -5207,63 +5208,6 @@ namespace etl typename etl::aligned_storage::type data; bool valid; }; - - //*************************************************************************** - // Specialisation for 0 message types. - //*************************************************************************** - template <> - class message_packet - { - public: - -#if ETL_USING_CPP11 - using message_types = etl::type_list<>; -#endif - - message_packet() - : valid(false) - { - } - - static ETL_CONSTEXPR bool accepts(etl::message_id_t) - { - return false; - } - - static ETL_CONSTEXPR bool accepts(const etl::imessage&) - { - return false; - } - - template - static ETL_CONSTEXPR bool accepts() - { - ETL_UNUSED(Id); - return false; - } - - template - static ETL_CONSTEXPR typename etl::enable_if::value, bool>::type accepts() - { - return false; - } - - bool is_valid() const - { - return valid; - } - - enum - { - SIZE = 0U, - ALIGNMENT = 1U - }; - - private: - - bool valid; - }; #endif } diff --git a/test/test_message_packet.cpp b/test/test_message_packet.cpp index 206d9f8c..3492a898 100644 --- a/test/test_message_packet.cpp +++ b/test/test_message_packet.cpp @@ -29,7 +29,6 @@ SOFTWARE. #include "unit_test_framework.h" #include "etl/platform.h" - #include "etl/message_packet.h" #include @@ -202,6 +201,11 @@ namespace using Packet = etl::message_packet; +#if ETL_USING_CPP17 && !defined(ETL_MESSAGE_PACKET_FORCE_CPP03_IMPLEMENTATION) + using MessageTypes = etl::type_list; + using PacketFromMessageTypes = etl::message_packet_from_type_list_t; +#endif + struct Object { void Push(const etl::message_packet& p) @@ -224,12 +228,21 @@ namespace Packet packet1(message1); Packet packet2(message2); +#if ETL_USING_CPP17 && !defined(ETL_MESSAGE_PACKET_FORCE_CPP03_IMPLEMENTATION) + PacketFromMessageTypes packet3(message3); +#else Packet packet3(message3); +#endif // Should cause a static assert. //Packet packet4(message4); //Packet packet4((Message4())); + CHECK_TRUE((std::is_same, typename Packet::message_types>::value)); +#if ETL_USING_CPP17 && !defined(ETL_MESSAGE_PACKET_FORCE_CPP03_IMPLEMENTATION) + CHECK_TRUE((std::is_same, typename PacketFromMessageTypes::message_types>::value)); +#endif + CHECK_EQUAL(MESSAGE1, packet1.get().get_message_id()); CHECK_EQUAL(MESSAGE2, packet2.get().get_message_id()); CHECK_EQUAL(MESSAGE3, packet3.get().get_message_id()); From 124309947150c765bf452b81809e2b8929d72bc2 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 28 Jan 2026 17:25:08 +0000 Subject: [PATCH 106/298] Add type_list functionality to etl::message_router using etl::message_router_from_type_list --- include/etl/message_router.h | 17 ++++++++++------- test/test_message_router.cpp | 12 +++++++++--- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/include/etl/message_router.h b/include/etl/message_router.h index 42fc65f8..7073f38c 100644 --- a/include/etl/message_router.h +++ b/include/etl/message_router.h @@ -552,16 +552,19 @@ namespace etl }; //*************************************************************************** - // The definition for all message types defined by a type_list. - //*************************************************************************** - template - class message_router> : public message_router - { - public: + /// Helper to turn etl::type_list into etl::tuple + template + struct message_router_from_type_list; - using message_router::message_router; + template + struct message_router_from_type_list> + { + using type = etl::message_router; }; + template + using message_router_from_type_list_t = typename message_router_from_type_list::type; + #else //************************************************************************************************* // For C++14 and below. diff --git a/test/test_message_router.cpp b/test/test_message_router.cpp index e7d94ac1..53da2b6b 100644 --- a/test/test_message_router.cpp +++ b/test/test_message_router.cpp @@ -121,8 +121,15 @@ namespace //*************************************************************************** // Router that handles messages 1, 2, 3, 4 and 5 and returns nothing. + // Created from a type list. //*************************************************************************** +#if ETL_USING_CPP17 && !defined(ETL_MESSAGE_ROUTER_FORCE_CPP03_IMPLEMENTATION) + using Router1Messages = etl::type_list; + + class Router1 : public etl::message_router_from_type_list_t +#else class Router1 : public etl::message_router +#endif { public: @@ -135,7 +142,6 @@ namespace message_unknown_count(0), callback_count(0) { - } void on_receive(const Message1& msg) @@ -341,7 +347,7 @@ namespace Message3 message3(r2); Message4 message4(r2); - // CHECK(!r1.is_null_router()); + CHECK(!r1.is_null_router()); CHECK(r1.is_producer()); CHECK(r1.is_consumer()); @@ -389,7 +395,7 @@ namespace Message3 message3(null_router); Message4 message4(null_router); - // CHECK(null_router.is_null_router()); + CHECK(null_router.is_null_router()); CHECK(!null_router.is_producer()); CHECK(!null_router.is_consumer()); From a669d1f46ea0c1bf330343622a01d3be8bb64d69 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 28 Jan 2026 17:26:20 +0000 Subject: [PATCH 107/298] Add type_list functionality to etl::observer using etl::observer_from_type_list --- include/etl/observer.h | 35 +++++++++-------------------------- test/test_observer.cpp | 8 ++++---- 2 files changed, 13 insertions(+), 30 deletions(-) diff --git a/include/etl/observer.h b/include/etl/observer.h index d7a75776..26f88478 100644 --- a/include/etl/observer.h +++ b/include/etl/observer.h @@ -326,8 +326,6 @@ namespace etl virtual ~observer() = default; virtual void notification(T1) = 0; - - using type_list = etl::type_list; }; //***************************************************************** @@ -344,36 +342,21 @@ namespace etl virtual ~observer() = default; virtual void notification() = 0; - - using type_list = etl::type_list<>; }; - //***************************************************************** - /// The observer class for N types. - /// Configured from a type list. - ///\ingroup observer - //***************************************************************** + //*************************************************************************** + /// Helper to turn etl::type_list into etl::observer + template + struct observer_from_type_list; + template - class observer> : public observer + struct observer_from_type_list> { - public: - - using observer::notification; - using type_list = etl::type_list; + using type = etl::observer; }; - //***************************************************************** - /// The specialised observer class for etl::type_list. - ///\ingroup observer - //**************************************************************** - template - class observer> : public observer - { - public: - - using observer::observer; - using observer::notification; - }; + template + using observer_from_type_list_t = typename observer_from_type_list::type; #else diff --git a/test/test_observer.cpp b/test/test_observer.cpp index 5ae52139..f8eb72ae 100644 --- a/test/test_observer.cpp +++ b/test/test_observer.cpp @@ -78,8 +78,8 @@ namespace // The Notification2 is passed by reference. // The Notification3 is passed by const reference. //***************************************************************************** - using NotificationList = etl::type_list; - using ObserverTypeFromTypeList = etl::observer; + using NotificationList = etl::type_list; + using ObserverFromTypeList = etl::observer_from_type_list_t; #endif //***************************************************************************** @@ -131,7 +131,7 @@ public: //***************************************************************************** // The concrete observable 3 class. //***************************************************************************** -class Observable3 : public etl::observable +class Observable3 : public etl::observable { public: @@ -270,7 +270,7 @@ public: // If any one of the overloads is missing or a parameter declaration is incorrect // then the class will be 'abstract' and will not compile. //***************************************************************************** -class Observer3 : public ObserverTypeFromTypeList +class Observer3 : public ObserverFromTypeList { public: From a4e4527669ed1bae445802f197ecc9cd5bfcb7b5 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 28 Jan 2026 17:26:57 +0000 Subject: [PATCH 108/298] Add type_list functionality to etl::tuple using etl::tuple_from_type_list --- include/etl/tuple.h | 16 +++++++++++++++- test/test_tuple.cpp | 11 +++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/include/etl/tuple.h b/include/etl/tuple.h index 2dd4971e..dbdbdaa2 100644 --- a/include/etl/tuple.h +++ b/include/etl/tuple.h @@ -132,7 +132,7 @@ namespace etl using value_type = void; ///< The type contained by this tuple. using this_type = tuple<>; ///< The type of this tuple. using base_type = void; ///< The type of the base tuple. - using type_list = etl::type_list<>; ///< The type list for this tuple. + using type_list = etl::type_list<>; ///< The type list for this tuple. using index_sequence_type = etl::make_index_sequence<0>; ///< The index_sequence type for this tuple. //********************************* @@ -1276,6 +1276,20 @@ namespace etl { lhs.swap(rhs); } + + //*************************************************************************** + /// Helper to turn etl::type_list into etl::tuple + template + struct tuple_from_type_list; + + template + struct tuple_from_type_list> + { + using type = etl::tuple; + }; + + template + using tuple_from_type_list_t = typename tuple_from_type_list::type; } namespace std diff --git a/test/test_tuple.cpp b/test/test_tuple.cpp index ec02bdaf..d84940d9 100644 --- a/test/test_tuple.cpp +++ b/test/test_tuple.cpp @@ -104,6 +104,17 @@ namespace CHECK_TRUE((std::is_same>::value)); } + //************************************************************************* + TEST(test_tuple_from_type_list) + { + using TypeList = etl::type_list; + using TupleFromTypeList = etl::tuple_from_type_list_t; + using Tuple = etl::tuple; + + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + } + //************************************************************************* TEST(test_tuple_type_list) { From a61980660f81f51795eb8df4966a136f7825a2e8 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 28 Jan 2026 17:33:32 +0000 Subject: [PATCH 109/298] Allow etl::make_index_sequence to be created from an etl::type_list --- include/etl/utility.h | 25 ++++++++++++++++++++++++- test/test_utility.cpp | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/include/etl/utility.h b/include/etl/utility.h index c3ea993d..46dc6003 100644 --- a/include/etl/utility.h +++ b/include/etl/utility.h @@ -565,8 +565,31 @@ namespace etl template using make_index_sequence = typename private_integer_sequence::make_index_sequence>::type; + //*********************************** + // Helper to support both parameter packs and etl::type_list + // Forward declare etl::type_list to allow use without including type_list.h template - using make_index_sequence_for = typename private_integer_sequence::make_index_sequence>::type; + struct type_list; + + namespace private_make_index_sequence_for + { + // Generic pack form + template + struct impl + { + using type = typename private_integer_sequence::make_index_sequence>::type; + }; + + // etl::type_list form + template + struct impl> : impl + { + }; + } + + // Accepts either a parameter pack of types or a single etl::type_list + template + using make_index_sequence_for = typename private_make_index_sequence_for::impl::type; //*********************************** template diff --git a/test/test_utility.cpp b/test/test_utility.cpp index 1757a499..2339587d 100644 --- a/test/test_utility.cpp +++ b/test/test_utility.cpp @@ -863,5 +863,39 @@ namespace CHECK_TRUE(E::B == (etl::nontype_t::value)); } #endif + + //********************************* + TEST(test_make_index_sequence_for_pack_matches_expected) + { + struct T1 {}; + struct T2 {}; + struct T3 {}; + + using seq12 = etl::make_index_sequence_for; + using seq123 = etl::make_index_sequence_for; + using expect12 = etl::index_sequence<0U, 1U>; + using expect123 = etl::index_sequence<0U, 1U, 2U>; + + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + } + + //********************************* + TEST(test_make_index_sequence_for_type_list_matches_expected) + { + struct T1 {}; + struct T2 {}; + struct T3 {}; + + using list12 = etl::type_list; + using list123 = etl::type_list; + using seq12 = etl::make_index_sequence_for; + using seq123 = etl::make_index_sequence_for; + using expect12 = etl::index_sequence<0U, 1U>; + using expect123 = etl::index_sequence<0U, 1U, 2U>; + + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + } } } From bde8747be8b67f294390b0addfb1714c997570c0 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 28 Jan 2026 17:42:25 +0000 Subject: [PATCH 110/298] Add type_list functionality to etl::visitor using etl::visitor_from_type_list --- include/etl/visitor.h | 23 ++++++++++------------- test/etl_profile.h | 1 + test/test_visitor.cpp | 13 +++++++++++++ 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/include/etl/visitor.h b/include/etl/visitor.h index 941af701..1d917c0a 100644 --- a/include/etl/visitor.h +++ b/include/etl/visitor.h @@ -84,23 +84,20 @@ namespace etl virtual void accept(T1&) = 0; }; - //***************************************************************** - /// The visitable class for an etl::type_list. - /// Expands the type_list into the existing variadic visitable. - ///\ingroup visitor - //***************************************************************** + //*************************************************************************** + /// Helper to turn etl::type_list into etl::visitable + template + struct visitable_from_type_list; + template - class visitable> : public visitable + struct visitable_from_type_list> { - ETL_STATIC_ASSERT(sizeof...(TTypes) != 0, "etl::type_list must not be empty"); - - public: - - using type_list = etl::type_list; - - using visitable::accept; + using type = etl::visitable; }; + template + using visitable_from_type_list_t = typename visitable_from_type_list::type; + #else //***************************************************************** diff --git a/test/etl_profile.h b/test/etl_profile.h index b6089a40..16d73d1b 100644 --- a/test/etl_profile.h +++ b/test/etl_profile.h @@ -110,6 +110,7 @@ SOFTWARE. #define ETL_FLAT_SET_FORCE_CPP03_IMPLEMENTATION #define ETL_FLAT_MULTISET_FORCE_CPP03_IMPLEMENTATION #define ETL_VARIANT_POOL_FORCE_CPP03_IMPLEMENTATION + #define ETL_VISITOR_FORCE_CPP03_IMPLEMENTATION #endif #if defined(ETL_FORCE_TEST_CPP11) diff --git a/test/test_visitor.cpp b/test/test_visitor.cpp index 4ea72356..db881e78 100644 --- a/test/test_visitor.cpp +++ b/test/test_visitor.cpp @@ -746,6 +746,19 @@ namespace CHECK_FALSE(etl::is_visitor::value); #endif } + +#if !defined(ETL_VISITOR_FORCE_CPP03_IMPLEMENTATION) + //************************************************************************* + TEST(test_visitable_from_type_list) + { + using Visitable1 = etl::visitable; + + using TypeList = etl::type_list; + using Visitable2 = etl::visitable_from_type_list_t; + + CHECK_TRUE((std::is_same::value)); + } +#endif } } From 21f68eb7b91938a301849da1b998e726a01ee141 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 28 Jan 2026 17:42:43 +0000 Subject: [PATCH 111/298] Fix iter_swap namespace --- include/etl/vector.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/etl/vector.h b/include/etl/vector.h index 92caf40c..db6d7d99 100644 --- a/include/etl/vector.h +++ b/include/etl/vector.h @@ -963,7 +963,7 @@ namespace etl ivector& smaller = other.size() > this->size() ? *this : other; ivector& larger = other.size() > this->size() ? other : *this; - ETL_OR_STD::swap_ranges(smaller.begin(), smaller.end(), larger.begin()); + etl::swap_ranges(smaller.begin(), smaller.end(), larger.begin()); typename ivector::iterator larger_itr = etl::next(larger.begin(), smaller.size()); From fed1274324aed6f11bf13830900c57b032878003 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 28 Jan 2026 17:45:11 +0000 Subject: [PATCH 112/298] Allow creation of a message_packet with no message types --- include/etl/message_packet.h | 170 +++++++++++++++++++++++++++++++++++ test/test_message_packet.cpp | 12 +-- 2 files changed, 174 insertions(+), 8 deletions(-) diff --git a/include/etl/message_packet.h b/include/etl/message_packet.h index d729c940..a1565f40 100644 --- a/include/etl/message_packet.h +++ b/include/etl/message_packet.h @@ -383,6 +383,119 @@ namespace etl bool valid; }; + //*************************************************************************** + // The definition for no message types. + //*************************************************************************** + template <> + class message_packet<> + { + + private: + + //template + //static constexpr bool IsMessagePacket = etl::is_same_v< etl::remove_const_t>, etl::message_packet>; + + template + static constexpr bool IsInMessageList = false; + + template + static constexpr bool IsIMessage = etl::is_same_v>, etl::imessage>; + + public: + + using message_types = etl::type_list<>; + + //******************************************** +#include "private/diagnostic_uninitialized_push.h" + message_packet() + { + } +#include "private/diagnostic_pop.h" + + //********************************************** + message_packet(const message_packet& other) + { + } + +#if ETL_USING_CPP11 + //********************************************** + message_packet(message_packet&& other) + { + } +#endif + + //********************************************** + void copy(const message_packet& other) + { + } + + //********************************************** + void copy(message_packet&& other) + { + } + + //********************************************** +#include "private/diagnostic_uninitialized_push.h" + message_packet& operator =(const message_packet& rhs) + { + return *this; + } +#include "private/diagnostic_pop.h" + + //********************************************** +#include "private/diagnostic_uninitialized_push.h" + message_packet& operator =(message_packet&& rhs) + { + return *this; + } +#include "private/diagnostic_pop.h" + + //******************************************** + ~message_packet() + { + } + + //******************************************** + bool is_valid() const + { + return false; + } + + //********************************************** + static ETL_CONSTEXPR bool accepts(etl::message_id_t id) + { + return false; + } + + //********************************************** + static ETL_CONSTEXPR bool accepts(const etl::imessage& msg) + { + return false; + } + + //********************************************** + template + static ETL_CONSTEXPR bool accepts() + { + return false; + } + + //********************************************** + template + static ETL_CONSTEXPR + typename etl::enable_if::value, bool>::type + accepts() + { + false; + } + + enum + { + SIZE = 0, + ALIGNMENT = 1 + }; + }; + //*************************************************************************** /// Helper to turn etl::type_list into etl::message_packet template @@ -5208,6 +5321,63 @@ namespace etl typename etl::aligned_storage::type data; bool valid; }; + + //*************************************************************************** + // Specialisation for 0 message types. + //*************************************************************************** + template <> + class message_packet + { + public: + +#if ETL_USING_CPP11 + using message_types = etl::type_list<>; +#endif + + message_packet() + : valid(false) + { + } + + static ETL_CONSTEXPR bool accepts(etl::message_id_t) + { + return false; + } + + static ETL_CONSTEXPR bool accepts(const etl::imessage&) + { + return false; + } + + template + static ETL_CONSTEXPR bool accepts() + { + ETL_UNUSED(Id); + return false; + } + + template + static ETL_CONSTEXPR typename etl::enable_if::value, bool>::type accepts() + { + return false; + } + + bool is_valid() const + { + return valid; + } + + enum + { + SIZE = 0U, + ALIGNMENT = 1U + }; + + private: + + bool valid; + }; #endif } diff --git a/test/test_message_packet.cpp b/test/test_message_packet.cpp index 3492a898..e77a3f5b 100644 --- a/test/test_message_packet.cpp +++ b/test/test_message_packet.cpp @@ -199,12 +199,12 @@ namespace { }; + using NullPacket = etl::message_packet<>; + using Packet = etl::message_packet; -#if ETL_USING_CPP17 && !defined(ETL_MESSAGE_PACKET_FORCE_CPP03_IMPLEMENTATION) using MessageTypes = etl::type_list; using PacketFromMessageTypes = etl::message_packet_from_type_list_t; -#endif struct Object { @@ -228,20 +228,16 @@ namespace Packet packet1(message1); Packet packet2(message2); -#if ETL_USING_CPP17 && !defined(ETL_MESSAGE_PACKET_FORCE_CPP03_IMPLEMENTATION) PacketFromMessageTypes packet3(message3); -#else - Packet packet3(message3); -#endif + NullPacket null_packet; // Should cause a static assert. //Packet packet4(message4); //Packet packet4((Message4())); CHECK_TRUE((std::is_same, typename Packet::message_types>::value)); -#if ETL_USING_CPP17 && !defined(ETL_MESSAGE_PACKET_FORCE_CPP03_IMPLEMENTATION) CHECK_TRUE((std::is_same, typename PacketFromMessageTypes::message_types>::value)); -#endif + CHECK_TRUE((std::is_same, typename NullPacket::message_types>::value)); CHECK_EQUAL(MESSAGE1, packet1.get().get_message_id()); CHECK_EQUAL(MESSAGE2, packet2.get().get_message_id()); From a4ee9d01aa5ec6dd02f1f2a35750268347206678 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 28 Jan 2026 17:45:29 +0000 Subject: [PATCH 113/298] Allow creation of a message_router with no message types --- include/etl/message_router.h | 114 +++++++++++++++++++++++++++++++++++ test/test_message_router.cpp | 96 +++++++++++++++++++++++++++-- 2 files changed, 206 insertions(+), 4 deletions(-) diff --git a/include/etl/message_router.h b/include/etl/message_router.h index 7073f38c..70a1607a 100644 --- a/include/etl/message_router.h +++ b/include/etl/message_router.h @@ -418,18 +418,28 @@ namespace etl message_router() : imessage_router(etl::imessage_router::MESSAGE_ROUTER) { + // CRTP validation: Derived must inherit from this exact specialization. + ETL_STATIC_ASSERT((etl::is_base_of, TDerived>::value), + "Mismatch in derived type: TDerived does not inherit from etl::message_router"); } //********************************************** message_router(etl::imessage_router& successor_) : imessage_router(etl::imessage_router::MESSAGE_ROUTER, successor_) { + // CRTP validation: Derived must inherit from this exact specialization. + ETL_STATIC_ASSERT((etl::is_base_of, TDerived>::value), + "Mismatch in derived type: TDerived does not inherit from etl::message_router"); } //********************************************** message_router(etl::message_router_id_t id_) : imessage_router(id_) { + // CRTP validation: Derived must inherit from this exact specialization. + ETL_STATIC_ASSERT((etl::is_base_of, TDerived>::value), + "Mismatch in derived type: TDerived does not inherit from etl::message_router"); + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); } @@ -437,6 +447,10 @@ namespace etl message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) : imessage_router(id_, successor_) { + // CRTP validation: Derived must inherit from this exact specialization. + ETL_STATIC_ASSERT((etl::is_base_of, TDerived>::value), + "Mismatch in derived type: TDerived does not inherit from etl::message_router"); + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); } @@ -551,6 +565,106 @@ namespace etl } }; + //*************************************************************************** + // The definition for all message types. + //*************************************************************************** + template + class message_router : public imessage_router + { + public: + + using message_packet = etl::message_packet<>; + using message_types = etl::type_list<>; + + //********************************************** + message_router() + : imessage_router(etl::imessage_router::MESSAGE_ROUTER) + { + // CRTP validation: Derived must inherit from this exact specialization. + ETL_STATIC_ASSERT((etl::is_base_of, TDerived>::value), + "Mismatch in derived type: TDerived does not inherit from etl::message_router"); + } + + //********************************************** + message_router(etl::imessage_router& successor_) + : imessage_router(etl::imessage_router::MESSAGE_ROUTER, successor_) + { + // CRTP validation: Derived must inherit from this exact specialization. + ETL_STATIC_ASSERT((etl::is_base_of, TDerived>::value), + "Mismatch in derived type: TDerived does not inherit from etl::message_router"); + } + + //********************************************** + message_router(etl::message_router_id_t id_) + : imessage_router(id_) + { + // CRTP validation: Derived must inherit from this exact specialization. + ETL_STATIC_ASSERT((etl::is_base_of, TDerived>::value), + "Mismatch in derived type: TDerived does not inherit from etl::message_router"); + + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + //********************************************** + message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) + : imessage_router(id_, successor_) + { + // CRTP validation: Derived must inherit from this exact specialization. + ETL_STATIC_ASSERT((etl::is_base_of, TDerived>::value), + "Mismatch in derived type: TDerived does not inherit from etl::message_router"); + + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + //********************************************** + using etl::imessage_router::receive; + + void receive(const etl::imessage& msg) ETL_OVERRIDE + { + if (has_successor()) + { + get_successor().receive(msg); + } + } + + template ::value, int>::type = 0> + void receive(const TMessage& msg) + { +#include "etl/private/diagnostic_array_bounds_push.h" + if (has_successor()) + { + get_successor().receive(msg); + } +#include "etl/private/diagnostic_pop.h" + } + + //********************************************** + using imessage_router::accepts; + + bool accepts(etl::message_id_t id) const ETL_OVERRIDE + { + return false; + } + + //******************************************** + ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE + { + return false; + } + + //******************************************** + bool is_producer() const ETL_OVERRIDE + { + return true; + } + + //******************************************** + bool is_consumer() const ETL_OVERRIDE + { + return true; + } + }; + //*************************************************************************** /// Helper to turn etl::type_list into etl::tuple template diff --git a/test/test_message_router.cpp b/test/test_message_router.cpp index 53da2b6b..2413d067 100644 --- a/test/test_message_router.cpp +++ b/test/test_message_router.cpp @@ -49,6 +49,7 @@ namespace enum { + ROUTER0, ROUTER1, ROUTER2, ROUTER3 @@ -119,17 +120,26 @@ namespace Message5 message5; + //*************************************************************************** + // Router that handles no messages. + //*************************************************************************** + class Router0 : public etl::message_router + { + public: + + Router0() + : message_router(ROUTER0) + { + } + }; + //*************************************************************************** // Router that handles messages 1, 2, 3, 4 and 5 and returns nothing. // Created from a type list. //*************************************************************************** -#if ETL_USING_CPP17 && !defined(ETL_MESSAGE_ROUTER_FORCE_CPP03_IMPLEMENTATION) using Router1Messages = etl::type_list; class Router1 : public etl::message_router_from_type_list_t -#else - class Router1 : public etl::message_router -#endif { public: @@ -384,6 +394,84 @@ namespace CHECK_EQUAL(4, r2.callback_count); } + //************************************************************************* + TEST(message_router_with_no_message_types) + { + Router0 r0; + Router1 r1; + Router2 r2; + + Message1 message1(r2); + Message2 message2(r2); + Message3 message3(r2); + Message4 message4(r2); + + r0.append_successor(r1); // All messages are passed to r1. + + CHECK_TRUE((etl::is_same>::value)); + + CHECK(!r0.is_null_router()); + CHECK(r0.is_producer()); + CHECK(r0.is_consumer()); + + r1.receive(message1); + CHECK_EQUAL(1, r1.message1_count); + CHECK_EQUAL(0, r1.message2_count); + CHECK_EQUAL(0, r1.message3_count); + CHECK_EQUAL(0, r1.message4_count); + CHECK_EQUAL(0, r1.message_unknown_count); + CHECK_EQUAL(1, r2.callback_count); + + r1.receive(message2); + CHECK_EQUAL(1, r1.message1_count); + CHECK_EQUAL(1, r1.message2_count); + CHECK_EQUAL(0, r1.message3_count); + CHECK_EQUAL(0, r1.message4_count); + CHECK_EQUAL(0, r1.message_unknown_count); + CHECK_EQUAL(2, r2.callback_count); + + r1.receive(message3); + CHECK_EQUAL(1, r1.message1_count); + CHECK_EQUAL(1, r1.message2_count); + CHECK_EQUAL(1, r1.message3_count); + CHECK_EQUAL(0, r1.message4_count); + CHECK_EQUAL(0, r1.message_unknown_count); + CHECK_EQUAL(3, r2.callback_count); + + r1.receive(message4); + CHECK_EQUAL(1, r1.message1_count); + CHECK_EQUAL(1, r1.message2_count); + CHECK_EQUAL(1, r1.message3_count); + CHECK_EQUAL(1, r1.message4_count); + CHECK_EQUAL(0, r1.message_unknown_count); + CHECK_EQUAL(4, r2.callback_count); + + //// Send from the null router. + //etl::send_message(r0, message1); + //CHECK_EQUAL(1, r2.message1_count); + //CHECK_EQUAL(0, r2.message2_count); + //CHECK_EQUAL(0, r2.message4_count); + //CHECK_EQUAL(0, r2.message_unknown_count); + + //etl::send_message(r0, message2); + //CHECK_EQUAL(1, r2.message1_count); + //CHECK_EQUAL(1, r2.message2_count); + //CHECK_EQUAL(0, r2.message4_count); + //CHECK_EQUAL(0, r2.message_unknown_count); + + //etl::send_message(r0, message3); + //CHECK_EQUAL(1, r2.message1_count); + //CHECK_EQUAL(1, r2.message2_count); + //CHECK_EQUAL(0, r2.message4_count); + //CHECK_EQUAL(1, r2.message_unknown_count); + + //etl::send_message(r0, message4); + //CHECK_EQUAL(1, r2.message1_count); + //CHECK_EQUAL(1, r2.message2_count); + //CHECK_EQUAL(1, r2.message4_count); + //CHECK_EQUAL(1, r2.message_unknown_count); + } + //************************************************************************* TEST(message_null_router) { From eb1216146ccba40a969e5854250504cd8020354f Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 28 Jan 2026 17:46:10 +0000 Subject: [PATCH 114/298] Updated VS2022 project files --- test/vs2022/etl.vcxproj | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 09056bad..6396b761 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -10357,11 +10357,9 @@ - - @@ -11435,7 +11433,6 @@ - From fa8f07ab800712a1233888fc52ff7e665e2a7b27 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 28 Jan 2026 17:46:35 +0000 Subject: [PATCH 115/298] Added missing test files CMakeLists.txt --- test/CMakeLists.txt | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 31b7776d..aa4e2aac 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -86,7 +86,6 @@ 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 @@ -184,7 +183,6 @@ 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 @@ -196,12 +194,10 @@ 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 @@ -210,9 +206,7 @@ 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 @@ -234,7 +228,6 @@ add_executable(etl_tests test_message_bus.cpp test_message_packet.cpp test_message_router.cpp - test_message_router_with_type_list.cpp test_message_router_registry.cpp test_message_timer.cpp test_message_timer_atomic.cpp @@ -253,7 +246,6 @@ add_executable(etl_tests test_nth_type.cpp test_numeric.cpp test_observer.cpp - test_observer_with_type_list.cpp test_optional.cpp test_overload.cpp test_packet.cpp @@ -265,7 +257,6 @@ add_executable(etl_tests test_poly_span_fixed_extent.cpp test_pool.cpp test_pool_external_buffer.cpp - test_print.cpp test_priority_queue.cpp test_pseudo_moving_average.cpp test_quantize.cpp @@ -294,7 +285,6 @@ 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 @@ -372,7 +362,6 @@ add_executable(etl_tests test_vector_pointer.cpp test_vector_pointer_external_buffer.cpp test_visitor.cpp - test_visitor_with_type_list.cpp test_xor_checksum.cpp test_xor_rotate_checksum.cpp ) From ff03b2807db65273dcaad1a5a1c2ed58af90ab0a Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 28 Jan 2026 22:24:46 +0000 Subject: [PATCH 116/298] Fix C++03 compatibility Fixed unused aregument warnings --- include/etl/message_packet.h | 23 ++++++------ include/etl/message_router.h | 71 ++++++------------------------------ test/test_message_packet.cpp | 8 ++++ test/test_message_router.cpp | 9 +++-- 4 files changed, 37 insertions(+), 74 deletions(-) diff --git a/include/etl/message_packet.h b/include/etl/message_packet.h index a1565f40..6cdf16e3 100644 --- a/include/etl/message_packet.h +++ b/include/etl/message_packet.h @@ -389,7 +389,6 @@ namespace etl template <> class message_packet<> { - private: //template @@ -413,30 +412,30 @@ namespace etl #include "private/diagnostic_pop.h" //********************************************** - message_packet(const message_packet& other) + message_packet(const message_packet& /*other*/) { } #if ETL_USING_CPP11 //********************************************** - message_packet(message_packet&& other) + message_packet(message_packet&& /*other*/) { } #endif //********************************************** - void copy(const message_packet& other) + void copy(const message_packet& /*other*/) { } //********************************************** - void copy(message_packet&& other) + void copy(message_packet&& /*other*/) { } //********************************************** #include "private/diagnostic_uninitialized_push.h" - message_packet& operator =(const message_packet& rhs) + message_packet& operator =(const message_packet& /*rhs*/) { return *this; } @@ -444,7 +443,7 @@ namespace etl //********************************************** #include "private/diagnostic_uninitialized_push.h" - message_packet& operator =(message_packet&& rhs) + message_packet& operator =(message_packet&& /*rhs*/) { return *this; } @@ -462,13 +461,13 @@ namespace etl } //********************************************** - static ETL_CONSTEXPR bool accepts(etl::message_id_t id) + static ETL_CONSTEXPR bool accepts(etl::message_id_t /*id*/) { return false; } //********************************************** - static ETL_CONSTEXPR bool accepts(const etl::imessage& msg) + static ETL_CONSTEXPR bool accepts(const etl::imessage& /*msg*/) { return false; } @@ -486,7 +485,7 @@ namespace etl typename etl::enable_if::value, bool>::type accepts() { - false; + return false; } enum @@ -515,7 +514,7 @@ namespace etl //*************************************************************************** // The definition for all 16 message types. //*************************************************************************** - template @@ -5353,7 +5352,7 @@ namespace etl template static ETL_CONSTEXPR bool accepts() { - ETL_UNUSED(Id); + //ETL_UNUSED(Id); return false; } diff --git a/include/etl/message_router.h b/include/etl/message_router.h index 70a1607a..564f5fa5 100644 --- a/include/etl/message_router.h +++ b/include/etl/message_router.h @@ -418,28 +418,18 @@ namespace etl message_router() : imessage_router(etl::imessage_router::MESSAGE_ROUTER) { - // CRTP validation: Derived must inherit from this exact specialization. - ETL_STATIC_ASSERT((etl::is_base_of, TDerived>::value), - "Mismatch in derived type: TDerived does not inherit from etl::message_router"); } //********************************************** message_router(etl::imessage_router& successor_) : imessage_router(etl::imessage_router::MESSAGE_ROUTER, successor_) { - // CRTP validation: Derived must inherit from this exact specialization. - ETL_STATIC_ASSERT((etl::is_base_of, TDerived>::value), - "Mismatch in derived type: TDerived does not inherit from etl::message_router"); } //********************************************** message_router(etl::message_router_id_t id_) : imessage_router(id_) { - // CRTP validation: Derived must inherit from this exact specialization. - ETL_STATIC_ASSERT((etl::is_base_of, TDerived>::value), - "Mismatch in derived type: TDerived does not inherit from etl::message_router"); - ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); } @@ -447,10 +437,6 @@ namespace etl message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) : imessage_router(id_, successor_) { - // CRTP validation: Derived must inherit from this exact specialization. - ETL_STATIC_ASSERT((etl::is_base_of, TDerived>::value), - "Mismatch in derived type: TDerived does not inherit from etl::message_router"); - ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); } @@ -566,7 +552,7 @@ namespace etl }; //*************************************************************************** - // The definition for all message types. + // The definition for 0 message types. //*************************************************************************** template class message_router : public imessage_router @@ -580,28 +566,18 @@ namespace etl message_router() : imessage_router(etl::imessage_router::MESSAGE_ROUTER) { - // CRTP validation: Derived must inherit from this exact specialization. - ETL_STATIC_ASSERT((etl::is_base_of, TDerived>::value), - "Mismatch in derived type: TDerived does not inherit from etl::message_router"); } //********************************************** message_router(etl::imessage_router& successor_) : imessage_router(etl::imessage_router::MESSAGE_ROUTER, successor_) { - // CRTP validation: Derived must inherit from this exact specialization. - ETL_STATIC_ASSERT((etl::is_base_of, TDerived>::value), - "Mismatch in derived type: TDerived does not inherit from etl::message_router"); } //********************************************** message_router(etl::message_router_id_t id_) : imessage_router(id_) { - // CRTP validation: Derived must inherit from this exact specialization. - ETL_STATIC_ASSERT((etl::is_base_of, TDerived>::value), - "Mismatch in derived type: TDerived does not inherit from etl::message_router"); - ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); } @@ -609,10 +585,6 @@ namespace etl message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) : imessage_router(id_, successor_) { - // CRTP validation: Derived must inherit from this exact specialization. - ETL_STATIC_ASSERT((etl::is_base_of, TDerived>::value), - "Mismatch in derived type: TDerived does not inherit from etl::message_router"); - ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); } @@ -641,7 +613,7 @@ namespace etl //********************************************** using imessage_router::accepts; - bool accepts(etl::message_id_t id) const ETL_OVERRIDE + bool accepts(etl::message_id_t /*id*/) const ETL_OVERRIDE { return false; } @@ -687,7 +659,7 @@ namespace etl // The definition for all 16 message types. //*************************************************************************** template @@ -3035,7 +3007,7 @@ namespace etl { public: - typedef etl::message_packet message_packet; + typedef etl::message_packet<> message_packet; #if ETL_USING_CPP11 using message_types = etl::type_list<>; @@ -3072,23 +3044,10 @@ namespace etl void receive(const etl::imessage& msg) ETL_OVERRIDE { - const size_t id = msg.get_message_id(); - #include "etl/private/diagnostic_array_bounds_push.h" - switch (id) + if (has_successor()) { - default: - { - if (has_successor()) - { - get_successor().receive(msg); - } - else - { - static_cast(this)->on_receive_unknown(msg); - } - break; - } + get_successor().receive(msg); } #include "etl/private/diagnostic_pop.h" } @@ -3098,19 +3057,13 @@ namespace etl bool accepts(etl::message_id_t id) const ETL_OVERRIDE { - switch (id) + if (has_successor()) { - default: - { - if (has_successor()) - { - return get_successor().accepts(id); - } - else - { - return false; - } - } + return get_successor().accepts(id); + } + else + { + return false; } } diff --git a/test/test_message_packet.cpp b/test/test_message_packet.cpp index e77a3f5b..51b0712d 100644 --- a/test/test_message_packet.cpp +++ b/test/test_message_packet.cpp @@ -203,8 +203,10 @@ namespace using Packet = etl::message_packet; +#if ETL_USING_CPP17 && !defined(ETL_MESSAGE_PACKET_FORCE_CPP03_IMPLEMENTATION) using MessageTypes = etl::type_list; using PacketFromMessageTypes = etl::message_packet_from_type_list_t; +#endif struct Object { @@ -228,7 +230,11 @@ namespace Packet packet1(message1); Packet packet2(message2); +#if ETL_USING_CPP17 && !defined(ETL_MESSAGE_PACKET_FORCE_CPP03_IMPLEMENTATION) PacketFromMessageTypes packet3(message3); +#else + Packet packet3(message3); +#endif NullPacket null_packet; // Should cause a static assert. @@ -236,7 +242,9 @@ namespace //Packet packet4((Message4())); CHECK_TRUE((std::is_same, typename Packet::message_types>::value)); +#if ETL_USING_CPP17 && !defined(ETL_MESSAGE_PACKET_FORCE_CPP03_IMPLEMENTATION) CHECK_TRUE((std::is_same, typename PacketFromMessageTypes::message_types>::value)); +#endif CHECK_TRUE((std::is_same, typename NullPacket::message_types>::value)); CHECK_EQUAL(MESSAGE1, packet1.get().get_message_id()); diff --git a/test/test_message_router.cpp b/test/test_message_router.cpp index 2413d067..a6691297 100644 --- a/test/test_message_router.cpp +++ b/test/test_message_router.cpp @@ -137,9 +137,12 @@ namespace // Router that handles messages 1, 2, 3, 4 and 5 and returns nothing. // Created from a type list. //*************************************************************************** +#if ETL_USING_CPP17 && !defined(ETL_MESSAGE_ROUTER_FORCE_CPP03_IMPLEMENTATION) using Router1Messages = etl::type_list; - class Router1 : public etl::message_router_from_type_list_t +#else + class Router1 : public etl::message_router +#endif { public: @@ -350,13 +353,13 @@ namespace Router1 r1; Router2 r2; - p_router = &r1; - Message1 message1(r2); Message2 message2(r2); Message3 message3(r2); Message4 message4(r2); + p_router = &r1; + CHECK(!r1.is_null_router()); CHECK(r1.is_producer()); CHECK(r1.is_consumer()); From 0ad0cec3428df599501e2a7272bdc9b03a7bd673 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 29 Jan 2026 10:06:42 +0000 Subject: [PATCH 117/298] Synced message_packet generator to updated code --- .../etl/generators/message_packet_generator.h | 209 +++++++++++++++++- include/etl/message_packet.h | 72 +++--- 2 files changed, 240 insertions(+), 41 deletions(-) diff --git a/include/etl/generators/message_packet_generator.h b/include/etl/generators/message_packet_generator.h index ee55c48d..f15efb03 100644 --- a/include/etl/generators/message_packet_generator.h +++ b/include/etl/generators/message_packet_generator.h @@ -71,6 +71,7 @@ cog.outl("//******************************************************************** #include "largest.h" #include "alignment.h" #include "utility.h" +#include "type_list.h" #include @@ -97,6 +98,8 @@ namespace etl public: + using message_types = etl::type_list; + //******************************************** #include "private/diagnostic_uninitialized_push.h" message_packet() @@ -260,7 +263,7 @@ namespace etl //********************************************** template static ETL_CONSTEXPR - typename etl::enable_if::value, bool>::type + typename etl::enable_if::value, bool>::type accepts() { return accepts(); @@ -392,6 +395,132 @@ namespace etl bool valid; }; + //*************************************************************************** + // The definition for no message types. + //*************************************************************************** + template <> + class message_packet<> + { + private: + + //template + //static constexpr bool IsMessagePacket = etl::is_same_v< etl::remove_const_t>, etl::message_packet>; + + template + static constexpr bool IsInMessageList = false; + + template + static constexpr bool IsIMessage = etl::is_same_v>, etl::imessage>; + + public: + + using message_types = etl::type_list<>; + + //******************************************** +#include "private/diagnostic_uninitialized_push.h" + message_packet() + { + } +#include "private/diagnostic_pop.h" + + //********************************************** + message_packet(const message_packet& /*other*/) + { + } + +#if ETL_USING_CPP11 + //********************************************** + message_packet(message_packet&& /*other*/) + { + } +#endif + + //********************************************** + void copy(const message_packet& /*other*/) + { + } + + //********************************************** + void copy(message_packet&& /*other*/) + { + } + + //********************************************** +#include "private/diagnostic_uninitialized_push.h" + message_packet& operator =(const message_packet& /*rhs*/) + { + return *this; + } +#include "private/diagnostic_pop.h" + + //********************************************** +#include "private/diagnostic_uninitialized_push.h" + message_packet& operator =(message_packet&& /*rhs*/) + { + return *this; + } +#include "private/diagnostic_pop.h" + + //******************************************** + ~message_packet() + { + } + + //******************************************** + bool is_valid() const + { + return false; + } + + //********************************************** + static ETL_CONSTEXPR bool accepts(etl::message_id_t /*id*/) + { + return false; + } + + //********************************************** + static ETL_CONSTEXPR bool accepts(const etl::imessage& /*msg*/) + { + return false; + } + + //********************************************** + template + static ETL_CONSTEXPR bool accepts() + { + return false; + } + + //********************************************** + template + static ETL_CONSTEXPR + typename etl::enable_if::value, bool>::type + accepts() + { + return false; + } + + enum + { + SIZE = 0, + ALIGNMENT = 1 + }; + }; + + //*************************************************************************** + /// Helper to turn etl::type_list into etl::message_packet + template + struct message_packet_from_type_list; + + template + struct message_packet_from_type_list> + { + using type = etl::message_packet; + }; + + template + using message_packet_from_type_list_t = typename message_packet_from_type_list::type; + #else /*[[[cog @@ -470,8 +599,7 @@ namespace etl cog.outl("// The definition for all %s message types." % Handlers) cog.outl("//***************************************************************************") cog.out("template <") - cog.out("typename T1, ") - for n in range(2, int(Handlers)): + for n in range(1, int(Handlers)): cog.out("typename T%s = void, " % n) if n % 4 == 0: cog.outl("") @@ -481,6 +609,15 @@ namespace etl cog.outl("{") cog.outl("public:") cog.outl("") + + cog.outl("#if ETL_USING_CPP11") + cog.out(" using message_types = etl::type_list<") + for n in range(1, int(Handlers)): + cog.out("T%s, " % n) + cog.outl("T%s>;" % int(Handlers)) + cog.outl("#endif") + cog.outl("") + cog.outl(" //********************************************") cog.outl("#include \"private/diagnostic_uninitialized_push.h\"") cog.outl(" message_packet()") @@ -785,6 +922,16 @@ namespace etl cog.outl("{") cog.outl("public:") cog.outl("") + + cog.out("#if ETL_USING_CPP11") + cog.outl("") + cog.out(" using message_types = etl::type_list<") + for t in range(1, int(n)): + cog.out("T%s, " % t) + cog.outl("T%s>;" % int(n)) + cog.outl("#endif") + cog.outl("") + cog.outl(" //********************************************") cog.outl("#include \"private/diagnostic_uninitialized_push.h\"") cog.outl(" message_packet()") @@ -1058,6 +1205,62 @@ namespace etl cog.outl("};") ]]]*/ /*[[[end]]]*/ + + //*************************************************************************** + // Specialisation for 0 message types. + //*************************************************************************** + template <> + class message_packet + { + public: + +#if ETL_USING_CPP11 + using message_types = etl::type_list<>; +#endif + + message_packet() + : valid(false) + { + } + + static ETL_CONSTEXPR bool accepts(etl::message_id_t) + { + return false; + } + + static ETL_CONSTEXPR bool accepts(const etl::imessage&) + { + return false; + } + + template + static ETL_CONSTEXPR bool accepts() + { + return false; + } + + template + static ETL_CONSTEXPR typename etl::enable_if::value, bool>::type accepts() + { + return false; + } + + bool is_valid() const + { + return valid; + } + + enum + { + SIZE = 0U, + ALIGNMENT = 1U + }; + + private: + + bool valid; + }; #endif } diff --git a/include/etl/message_packet.h b/include/etl/message_packet.h index 6cdf16e3..9c6f5eb1 100644 --- a/include/etl/message_packet.h +++ b/include/etl/message_packet.h @@ -251,7 +251,7 @@ namespace etl //********************************************** template static ETL_CONSTEXPR - typename etl::enable_if::value, bool>::type + typename etl::enable_if::value, bool>::type accepts() { return accepts(); @@ -482,7 +482,7 @@ namespace etl //********************************************** template static ETL_CONSTEXPR - typename etl::enable_if::value, bool>::type + typename etl::enable_if::value, bool>::type accepts() { return false; @@ -522,9 +522,9 @@ namespace etl { public: -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //******************************************** #include "private/diagnostic_uninitialized_push.h" @@ -850,9 +850,9 @@ namespace etl { public: -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //******************************************** #include "private/diagnostic_uninitialized_push.h" @@ -1176,9 +1176,9 @@ namespace etl { public: -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //******************************************** #include "private/diagnostic_uninitialized_push.h" @@ -1499,9 +1499,9 @@ namespace etl { public: -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //******************************************** #include "private/diagnostic_uninitialized_push.h" @@ -1818,9 +1818,9 @@ namespace etl { public: -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //******************************************** #include "private/diagnostic_uninitialized_push.h" @@ -2131,9 +2131,9 @@ namespace etl { public: -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //******************************************** #include "private/diagnostic_uninitialized_push.h" @@ -2441,9 +2441,9 @@ namespace etl { public: -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //******************************************** #include "private/diagnostic_uninitialized_push.h" @@ -2748,9 +2748,9 @@ namespace etl { public: -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //******************************************** #include "private/diagnostic_uninitialized_push.h" @@ -3051,9 +3051,9 @@ namespace etl { public: -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //******************************************** #include "private/diagnostic_uninitialized_push.h" @@ -3348,9 +3348,9 @@ namespace etl { public: -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //******************************************** #include "private/diagnostic_uninitialized_push.h" @@ -3642,9 +3642,9 @@ namespace etl { public: -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //******************************************** #include "private/diagnostic_uninitialized_push.h" @@ -3933,9 +3933,9 @@ namespace etl { public: -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //******************************************** #include "private/diagnostic_uninitialized_push.h" @@ -4220,9 +4220,9 @@ namespace etl { public: -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //******************************************** #include "private/diagnostic_uninitialized_push.h" @@ -4501,9 +4501,9 @@ namespace etl { public: -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //******************************************** #include "private/diagnostic_uninitialized_push.h" @@ -4779,9 +4779,9 @@ namespace etl { public: -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //******************************************** #include "private/diagnostic_uninitialized_push.h" @@ -5054,12 +5054,9 @@ namespace etl { public: - //ETL_STATIC_ASSERT(!etl::is_type_list::value, - // "message_packet does not accept an etl::type_list before C++17, or when ETL_MESSAGE_PACKET_FORCE_CPP03_IMPLEMENTATION is defined"); - -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //******************************************** #include "private/diagnostic_uninitialized_push.h" @@ -5352,7 +5349,6 @@ namespace etl template static ETL_CONSTEXPR bool accepts() { - //ETL_UNUSED(Id); return false; } From a7fe6bc6b0e2cba2f3bb2cfc9fa83bf1b2d7d80d Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Fri, 30 Jan 2026 09:06:54 +0000 Subject: [PATCH 118/298] Synced message_router generator to updated code --- .../etl/generators/message_router_generator.h | 25 +- include/etl/message_router.h | 263 +++--------------- 2 files changed, 57 insertions(+), 231 deletions(-) diff --git a/include/etl/generators/message_router_generator.h b/include/etl/generators/message_router_generator.h index 868a51ab..71f05dea 100644 --- a/include/etl/generators/message_router_generator.h +++ b/include/etl/generators/message_router_generator.h @@ -76,7 +76,7 @@ cog.outl("//******************************************************************** #include "placement_new.h" #include "successor.h" #include "type_traits.h" - +#include "type_list.h" #include namespace etl @@ -574,8 +574,7 @@ namespace etl cog.outl("//***************************************************************************") cog.outl("template message_packet;" % int(Handlers)) + cog.outl("T%s> message_packet;" % int(Handlers)) cog.outl("") + + cog.outl("#if ETL_USING_CPP11") + cog.out(" using message_types = etl::type_list<") + for n in range(1, int(Handlers)): + cog.out("T%s, " % n) + cog.outl("T%s> message_packet;" % int(Handlers)) + cog.outl("#endif") + cog.outl("") + cog.outl(" //**********************************************") cog.outl(" message_router(etl::message_router_id_t id_)") cog.outl(" : imessage_router(id_)") @@ -765,6 +773,15 @@ namespace etl cog.out("T%s, " % t) cog.outl(" T%s> message_packet;" % n) cog.outl("") + + cog.outl("#if ETL_USING_CPP11") + cog.out(" using message_types = etl::type_list<") + for t in range(1, n): + cog.out("T%s, " % t) + cog.outl("T%s>;" % n) + cog.outl("#endif") + cog.outl("") + cog.outl(" //**********************************************") cog.outl(" message_router(etl::message_router_id_t id_)") cog.outl(" : imessage_router(id_)") diff --git a/include/etl/message_router.h b/include/etl/message_router.h index 564f5fa5..1feaa3c9 100644 --- a/include/etl/message_router.h +++ b/include/etl/message_router.h @@ -65,7 +65,6 @@ SOFTWARE. #include "successor.h" #include "type_traits.h" #include "type_list.h" - #include namespace etl @@ -411,8 +410,7 @@ namespace etl { public: - using message_packet = etl::message_packet; - using message_types = etl::type_list; + typedef etl::message_packet message_packet; //********************************************** message_router() @@ -550,108 +548,7 @@ namespace etl } } }; - - //*************************************************************************** - // The definition for 0 message types. - //*************************************************************************** - template - class message_router : public imessage_router - { - public: - - using message_packet = etl::message_packet<>; - using message_types = etl::type_list<>; - - //********************************************** - message_router() - : imessage_router(etl::imessage_router::MESSAGE_ROUTER) - { - } - - //********************************************** - message_router(etl::imessage_router& successor_) - : imessage_router(etl::imessage_router::MESSAGE_ROUTER, successor_) - { - } - - //********************************************** - message_router(etl::message_router_id_t id_) - : imessage_router(id_) - { - ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); - } - - //********************************************** - message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) - : imessage_router(id_, successor_) - { - ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); - } - - //********************************************** - using etl::imessage_router::receive; - - void receive(const etl::imessage& msg) ETL_OVERRIDE - { - if (has_successor()) - { - get_successor().receive(msg); - } - } - - template ::value, int>::type = 0> - void receive(const TMessage& msg) - { -#include "etl/private/diagnostic_array_bounds_push.h" - if (has_successor()) - { - get_successor().receive(msg); - } -#include "etl/private/diagnostic_pop.h" - } - - //********************************************** - using imessage_router::accepts; - - bool accepts(etl::message_id_t /*id*/) const ETL_OVERRIDE - { - return false; - } - - //******************************************** - ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE - { - return false; - } - - //******************************************** - bool is_producer() const ETL_OVERRIDE - { - return true; - } - - //******************************************** - bool is_consumer() const ETL_OVERRIDE - { - return true; - } - }; - - //*************************************************************************** - /// Helper to turn etl::type_list into etl::tuple - template - struct message_router_from_type_list; - - template - struct message_router_from_type_list> - { - using type = etl::message_router; - }; - - template - using message_router_from_type_list_t = typename message_router_from_type_list::type; - - #else +#else //************************************************************************************************* // For C++14 and below. //************************************************************************************************* @@ -669,9 +566,9 @@ namespace etl typedef etl::message_packet message_packet; -#if ETL_USING_CPP11 - using message_types = etl::type_list; -#endif + #if ETL_USING_CPP11 + using message_types = etl::type_list message_packet; + #endif //********************************************** message_router(etl::message_router_id_t id_) @@ -824,9 +721,9 @@ namespace etl typedef etl::message_packet message_packet; -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //********************************************** message_router(etl::message_router_id_t id_) @@ -979,9 +876,9 @@ namespace etl typedef etl::message_packet message_packet; -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //********************************************** message_router(etl::message_router_id_t id_) @@ -1133,9 +1030,9 @@ namespace etl typedef etl::message_packet message_packet; -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //********************************************** message_router(etl::message_router_id_t id_) @@ -1285,9 +1182,9 @@ namespace etl typedef etl::message_packet message_packet; -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //********************************************** message_router(etl::message_router_id_t id_) @@ -1436,9 +1333,9 @@ namespace etl typedef etl::message_packet message_packet; -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //********************************************** message_router(etl::message_router_id_t id_) @@ -1586,9 +1483,9 @@ namespace etl typedef etl::message_packet message_packet; -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //********************************************** message_router(etl::message_router_id_t id_) @@ -1735,9 +1632,9 @@ namespace etl typedef etl::message_packet message_packet; -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //********************************************** message_router(etl::message_router_id_t id_) @@ -1882,9 +1779,9 @@ namespace etl typedef etl::message_packet message_packet; -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //********************************************** message_router(etl::message_router_id_t id_) @@ -2028,9 +1925,9 @@ namespace etl typedef etl::message_packet message_packet; -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //********************************************** message_router(etl::message_router_id_t id_) @@ -2172,9 +2069,9 @@ namespace etl typedef etl::message_packet message_packet; -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //********************************************** message_router(etl::message_router_id_t id_) @@ -2315,9 +2212,9 @@ namespace etl typedef etl::message_packet message_packet; -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //********************************************** message_router(etl::message_router_id_t id_) @@ -2456,9 +2353,9 @@ namespace etl typedef etl::message_packet message_packet; -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //********************************************** message_router(etl::message_router_id_t id_) @@ -2596,9 +2493,9 @@ namespace etl typedef etl::message_packet message_packet; -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //********************************************** message_router(etl::message_router_id_t id_) @@ -2735,9 +2632,9 @@ namespace etl typedef etl::message_packet message_packet; -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //********************************************** message_router(etl::message_router_id_t id_) @@ -2871,11 +2768,11 @@ namespace etl { public: - typedef etl::message_packet message_packet; + typedef etl::message_packet< T1> message_packet; -#if ETL_USING_CPP11 + #if ETL_USING_CPP11 using message_types = etl::type_list; -#endif + #endif //********************************************** message_router(etl::message_router_id_t id_) @@ -2997,94 +2894,6 @@ namespace etl return true; } }; - - //*************************************************************************** - // Specialisation for 0 message types. - //*************************************************************************** - template - class message_router - : public imessage_router - { - public: - - typedef etl::message_packet<> message_packet; - -#if ETL_USING_CPP11 - using message_types = etl::type_list<>; -#endif - - //********************************************** - message_router(etl::message_router_id_t id_) - : imessage_router(id_) - { - ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); - } - - //********************************************** - message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) - : imessage_router(id_, successor_) - { - ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); - } - - //********************************************** - message_router() - : imessage_router(etl::imessage_router::MESSAGE_ROUTER) - { - } - - //********************************************** - message_router(etl::imessage_router& successor_) - : imessage_router(etl::imessage_router::MESSAGE_ROUTER, successor_) - { - } - - //********************************************** - using etl::imessage_router::receive; - - void receive(const etl::imessage& msg) ETL_OVERRIDE - { -#include "etl/private/diagnostic_array_bounds_push.h" - if (has_successor()) - { - get_successor().receive(msg); - } -#include "etl/private/diagnostic_pop.h" - } - - //********************************************** - using imessage_router::accepts; - - bool accepts(etl::message_id_t id) const ETL_OVERRIDE - { - if (has_successor()) - { - return get_successor().accepts(id); - } - else - { - return false; - } - } - - //******************************************** - ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE - { - return false; - } - - //******************************************** - bool is_producer() const ETL_OVERRIDE - { - return true; - } - - //******************************************** - bool is_consumer() const ETL_OVERRIDE - { - return true; - } - }; #endif } From 53a9cde9a4b9a453e4772a3ca3b458ec25bf119c Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Fri, 30 Jan 2026 09:06:54 +0000 Subject: [PATCH 119/298] Synced message_router generator to updated code # Conflicts: # include/etl/generators/message_router_generator.h # include/etl/message_router.h --- include/etl/generators/message_router_generator.h | 2 +- include/etl/message_router.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/etl/generators/message_router_generator.h b/include/etl/generators/message_router_generator.h index 71f05dea..b6259d17 100644 --- a/include/etl/generators/message_router_generator.h +++ b/include/etl/generators/message_router_generator.h @@ -595,7 +595,7 @@ namespace etl cog.out(" using message_types = etl::type_list<") for n in range(1, int(Handlers)): cog.out("T%s, " % n) - cog.outl("T%s> message_packet;" % int(Handlers)) + cog.outl("T%s>;" % int(Handlers)) cog.outl("#endif") cog.outl("") diff --git a/include/etl/message_router.h b/include/etl/message_router.h index 1feaa3c9..0ac3756a 100644 --- a/include/etl/message_router.h +++ b/include/etl/message_router.h @@ -567,7 +567,7 @@ namespace etl typedef etl::message_packet message_packet; #if ETL_USING_CPP11 - using message_types = etl::type_list message_packet; + using message_types = etl::type_list; #endif //********************************************** From 491c648d3ee27be899387efed768d8dc8d61de96 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Fri, 30 Jan 2026 10:58:57 +0000 Subject: [PATCH 120/298] Fixed missing zero message specialisation for <= C++14 --- .../etl/generators/message_router_generator.h | 88 +++++++++++++++++++ include/etl/message_router.h | 88 +++++++++++++++++++ 2 files changed, 176 insertions(+) diff --git a/include/etl/generators/message_router_generator.h b/include/etl/generators/message_router_generator.h index b6259d17..635254ed 100644 --- a/include/etl/generators/message_router_generator.h +++ b/include/etl/generators/message_router_generator.h @@ -919,6 +919,94 @@ namespace etl cog.outl("};") ]]]*/ /*[[[end]]]*/ + + //*************************************************************************** + // Specialisation for 0 message types. + //*************************************************************************** + template + class message_router + : public imessage_router + { + public: + + typedef etl::message_packet<> message_packet; + +#if ETL_USING_CPP11 + using message_types = etl::type_list<>; +#endif + + //********************************************** + message_router(etl::message_router_id_t id_) + : imessage_router(id_) + { + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + //********************************************** + message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) + : imessage_router(id_, successor_) + { + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + //********************************************** + message_router() + : imessage_router(etl::imessage_router::MESSAGE_ROUTER) + { + } + + //********************************************** + message_router(etl::imessage_router& successor_) + : imessage_router(etl::imessage_router::MESSAGE_ROUTER, successor_) + { + } + + //********************************************** + using etl::imessage_router::receive; + + void receive(const etl::imessage& msg) ETL_OVERRIDE + { +#include "etl/private/diagnostic_array_bounds_push.h" + if (has_successor()) + { + get_successor().receive(msg); + } +#include "etl/private/diagnostic_pop.h" + } + + //********************************************** + using imessage_router::accepts; + + bool accepts(etl::message_id_t id) const ETL_OVERRIDE + { + if (has_successor()) + { + return get_successor().accepts(id); + } + else + { + return false; + } + } + + //******************************************** + ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE + { + return false; + } + + //******************************************** + bool is_producer() const ETL_OVERRIDE + { + return true; + } + + //******************************************** + bool is_consumer() const ETL_OVERRIDE + { + return true; + } + }; #endif } diff --git a/include/etl/message_router.h b/include/etl/message_router.h index 0ac3756a..62efe04b 100644 --- a/include/etl/message_router.h +++ b/include/etl/message_router.h @@ -2894,6 +2894,94 @@ namespace etl return true; } }; + + //*************************************************************************** + // Specialisation for 0 message types. + //*************************************************************************** + template + class message_router + : public imessage_router + { + public: + + typedef etl::message_packet<> message_packet; + +#if ETL_USING_CPP11 + using message_types = etl::type_list<>; +#endif + + //********************************************** + message_router(etl::message_router_id_t id_) + : imessage_router(id_) + { + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + //********************************************** + message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) + : imessage_router(id_, successor_) + { + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + //********************************************** + message_router() + : imessage_router(etl::imessage_router::MESSAGE_ROUTER) + { + } + + //********************************************** + message_router(etl::imessage_router& successor_) + : imessage_router(etl::imessage_router::MESSAGE_ROUTER, successor_) + { + } + + //********************************************** + using etl::imessage_router::receive; + + void receive(const etl::imessage& msg) ETL_OVERRIDE + { +#include "etl/private/diagnostic_array_bounds_push.h" + if (has_successor()) + { + get_successor().receive(msg); + } +#include "etl/private/diagnostic_pop.h" + } + + //********************************************** + using imessage_router::accepts; + + bool accepts(etl::message_id_t id) const ETL_OVERRIDE + { + if (has_successor()) + { + return get_successor().accepts(id); + } + else + { + return false; + } + } + + //******************************************** + ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE + { + return false; + } + + //******************************************** + bool is_producer() const ETL_OVERRIDE + { + return true; + } + + //******************************************** + bool is_consumer() const ETL_OVERRIDE + { + return true; + } + }; #endif } From 15b96484d5095bbd1f14039bc4a5114e62a755c3 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Fri, 30 Jan 2026 10:58:57 +0000 Subject: [PATCH 121/298] Fixed missing zero message specialisation for <= C++14 --- .../etl/generators/message_router_generator.h | 101 ++++++++++++++++++ include/etl/message_router.h | 101 ++++++++++++++++++ 2 files changed, 202 insertions(+) diff --git a/include/etl/generators/message_router_generator.h b/include/etl/generators/message_router_generator.h index 635254ed..6b3602ff 100644 --- a/include/etl/generators/message_router_generator.h +++ b/include/etl/generators/message_router_generator.h @@ -560,6 +560,107 @@ namespace etl } } }; + + //*************************************************************************** + // The definition for 0 message types. + //*************************************************************************** + template + class message_router : public imessage_router + { + public: + + using message_packet = etl::message_packet<>; + using message_types = etl::type_list<>; + + //********************************************** + message_router() + : imessage_router(etl::imessage_router::MESSAGE_ROUTER) + { + } + + //********************************************** + message_router(etl::imessage_router& successor_) + : imessage_router(etl::imessage_router::MESSAGE_ROUTER, successor_) + { + } + + //********************************************** + message_router(etl::message_router_id_t id_) + : imessage_router(id_) + { + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + //********************************************** + message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) + : imessage_router(id_, successor_) + { + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + //********************************************** + using etl::imessage_router::receive; + + void receive(const etl::imessage& msg) ETL_OVERRIDE + { + if (has_successor()) + { + get_successor().receive(msg); + } + } + + template ::value, int>::type = 0> + void receive(const TMessage& msg) + { +#include "etl/private/diagnostic_array_bounds_push.h" + if (has_successor()) + { + get_successor().receive(msg); + } +#include "etl/private/diagnostic_pop.h" + } + + //********************************************** + using imessage_router::accepts; + + bool accepts(etl::message_id_t /*id*/) const ETL_OVERRIDE + { + return false; + } + + //******************************************** + ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE + { + return false; + } + + //******************************************** + bool is_producer() const ETL_OVERRIDE + { + return true; + } + + //******************************************** + bool is_consumer() const ETL_OVERRIDE + { + return true; + } + }; + + //*************************************************************************** + /// Helper to turn etl::type_list into etl::tuple + template + struct message_router_from_type_list; + + template + struct message_router_from_type_list> + { + using type = etl::message_router; + }; + + template + using message_router_from_type_list_t = typename message_router_from_type_list::type; + #else //************************************************************************************************* // For C++14 and below. diff --git a/include/etl/message_router.h b/include/etl/message_router.h index 62efe04b..e46c05a9 100644 --- a/include/etl/message_router.h +++ b/include/etl/message_router.h @@ -548,6 +548,107 @@ namespace etl } } }; + + //*************************************************************************** + // The definition for 0 message types. + //*************************************************************************** + template + class message_router : public imessage_router + { + public: + + using message_packet = etl::message_packet<>; + using message_types = etl::type_list<>; + + //********************************************** + message_router() + : imessage_router(etl::imessage_router::MESSAGE_ROUTER) + { + } + + //********************************************** + message_router(etl::imessage_router& successor_) + : imessage_router(etl::imessage_router::MESSAGE_ROUTER, successor_) + { + } + + //********************************************** + message_router(etl::message_router_id_t id_) + : imessage_router(id_) + { + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + //********************************************** + message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) + : imessage_router(id_, successor_) + { + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + //********************************************** + using etl::imessage_router::receive; + + void receive(const etl::imessage& msg) ETL_OVERRIDE + { + if (has_successor()) + { + get_successor().receive(msg); + } + } + + template ::value, int>::type = 0> + void receive(const TMessage& msg) + { +#include "etl/private/diagnostic_array_bounds_push.h" + if (has_successor()) + { + get_successor().receive(msg); + } +#include "etl/private/diagnostic_pop.h" + } + + //********************************************** + using imessage_router::accepts; + + bool accepts(etl::message_id_t /*id*/) const ETL_OVERRIDE + { + return false; + } + + //******************************************** + ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE + { + return false; + } + + //******************************************** + bool is_producer() const ETL_OVERRIDE + { + return true; + } + + //******************************************** + bool is_consumer() const ETL_OVERRIDE + { + return true; + } + }; + + //*************************************************************************** + /// Helper to turn etl::type_list into etl::tuple + template + struct message_router_from_type_list; + + template + struct message_router_from_type_list> + { + using type = etl::message_router; + }; + + template + using message_router_from_type_list_t = typename message_router_from_type_list::type; + #else //************************************************************************************************* // For C++14 and below. From db89cc892026db80f65d5de8b34c758ec25b4bfb Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Sun, 1 Feb 2026 11:16:41 +0100 Subject: [PATCH 122/298] Add missing includes (#1286) * Remove AppVeyor build status badge Removed AppVeyor build status badge from README. * Update README.md * Update CONTRIBUTING.md Updated the instructions for contributing. * Fix for issue 1276 "Data corruption in the etl::bip_buffer_spsc_atomic" (#1277) * Reproduce data corruption bug in the `etl::bip_buffer_spsc_atomic`. * Fix data corruption bug in the `etl::bip_buffer_spsc_atomic`. * Add missing includes Before this change, the includes needed to be done explicitly by files using basic_string_stream.h, and be included first. This was error prone, especially if includes are reordered (e.g. via the currently defined clang-format rules). --------- Co-authored-by: John Wellbelove Co-authored-by: Sergei --- include/etl/basic_string_stream.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/etl/basic_string_stream.h b/include/etl/basic_string_stream.h index 2b466055..2aa1f28d 100644 --- a/include/etl/basic_string_stream.h +++ b/include/etl/basic_string_stream.h @@ -35,6 +35,10 @@ SOFTWARE. #include "platform.h" #include "to_string.h" +#include "to_u8string.h" +#include "to_u16string.h" +#include "to_u32string.h" +#include "to_wstring.h" namespace etl { From 570a7adaa33823b274749100cce5d81b0130f446 Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Mon, 2 Feb 2026 11:46:00 +0100 Subject: [PATCH 123/298] Move comparison operators of etl::expected to namespace etl (#1287) * Remove AppVeyor build status badge Removed AppVeyor build status badge from README. * Update README.md * Update CONTRIBUTING.md Updated the instructions for contributing. * Fix for issue 1276 "Data corruption in the etl::bip_buffer_spsc_atomic" (#1277) * Reproduce data corruption bug in the `etl::bip_buffer_spsc_atomic`. * Fix data corruption bug in the `etl::bip_buffer_spsc_atomic`. * Move comparison operators of etl::expected to namespace etl --------- Co-authored-by: John Wellbelove Co-authored-by: Sergei --- include/etl/expected.h | 204 ++++++++++++++++++++--------------------- 1 file changed, 102 insertions(+), 102 deletions(-) diff --git a/include/etl/expected.h b/include/etl/expected.h index 722c411e..758e2404 100644 --- a/include/etl/expected.h +++ b/include/etl/expected.h @@ -1296,132 +1296,132 @@ namespace etl } #endif }; -} -//******************************************* -/// Equivalence operators. -//******************************************* -template -ETL_CONSTEXPR14 -bool operator ==(const etl::expected& lhs, const etl::expected& rhs) -{ - if (lhs.has_value() != rhs.has_value()) + //******************************************* + /// Equivalence operators. + //******************************************* + template + ETL_CONSTEXPR14 + bool operator ==(const etl::expected& lhs, const etl::expected& rhs) { - return false; + if (lhs.has_value() != rhs.has_value()) + { + return false; + } + if (lhs.has_value()) + { + return lhs.value() == rhs.value(); + } + return lhs.error() == rhs.error(); } - if (lhs.has_value()) + + //******************************************* + template + ETL_CONSTEXPR14 + bool operator ==(const etl::expected& lhs, const TValue2& rhs) { - return lhs.value() == rhs.value(); + if (!lhs.has_value()) + { + return false; + } + return lhs.value() == rhs; } - return lhs.error() == rhs.error(); -} -//******************************************* -template -ETL_CONSTEXPR14 -bool operator ==(const etl::expected& lhs, const TValue2& rhs) -{ - if (!lhs.has_value()) + //******************************************* + template + ETL_CONSTEXPR14 + bool operator ==(const etl::expected& lhs, const etl::unexpected& rhs) { - return false; + if (lhs.has_value()) + { + return false; + } + return lhs.error() == rhs.error(); } - return lhs.value() == rhs; -} -//******************************************* -template -ETL_CONSTEXPR14 -bool operator ==(const etl::expected& lhs, const etl::unexpected& rhs) -{ - if (lhs.has_value()) + //******************************************* + template + ETL_CONSTEXPR14 + bool operator ==(const etl::expected& lhs, const etl::expected& rhs) { - return false; + if (lhs.has_value() != rhs.has_value()) + { + return false; + } + if (lhs.has_value()) + { + return true; + } + return lhs.error() == rhs.error(); } - return lhs.error() == rhs.error(); -} -//******************************************* -template -ETL_CONSTEXPR14 -bool operator ==(const etl::expected& lhs, const etl::expected& rhs) -{ - if (lhs.has_value() != rhs.has_value()) + //******************************************* + template + ETL_CONSTEXPR14 + bool operator ==(const etl::expected& lhs, const etl::unexpected& rhs) { - return false; + if (lhs.has_value()) + { + return false; + } + return lhs.error() == rhs.error(); } - if (lhs.has_value()) + + //******************************************* + template + ETL_CONSTEXPR14 + bool operator ==(const etl::unexpected& lhs, const etl::unexpected& rhs) { - return true; + return lhs.error() == rhs.error(); } - return lhs.error() == rhs.error(); -} -//******************************************* -template -ETL_CONSTEXPR14 -bool operator ==(const etl::expected& lhs, const etl::unexpected& rhs) -{ - if (lhs.has_value()) + //******************************************* + template + ETL_CONSTEXPR14 + bool operator !=(const etl::expected& lhs, const etl::expected& rhs) { - return false; + return !(lhs == rhs); } - return lhs.error() == rhs.error(); -} -//******************************************* -template -ETL_CONSTEXPR14 -bool operator ==(const etl::unexpected& lhs, const etl::unexpected& rhs) -{ - return lhs.error() == rhs.error(); -} + //******************************************* + template + ETL_CONSTEXPR14 + bool operator !=(const etl::expected& lhs, const TValue2& rhs) + { + return !(lhs == rhs); + } -//******************************************* -template -ETL_CONSTEXPR14 -bool operator !=(const etl::expected& lhs, const etl::expected& rhs) -{ - return !(lhs == rhs); -} + //******************************************* + template + ETL_CONSTEXPR14 + bool operator !=(const etl::expected& lhs, const etl::unexpected& rhs) + { + return !(lhs == rhs); + } -//******************************************* -template -ETL_CONSTEXPR14 -bool operator !=(const etl::expected& lhs, const TValue2& rhs) -{ - return !(lhs == rhs); -} + //******************************************* + template + ETL_CONSTEXPR14 + bool operator !=(const etl::expected& lhs, const etl::expected& rhs) + { + return !(lhs == rhs); + } -//******************************************* -template -ETL_CONSTEXPR14 -bool operator !=(const etl::expected& lhs, const etl::unexpected& rhs) -{ - return !(lhs == rhs); -} + //******************************************* + template + ETL_CONSTEXPR14 + bool operator !=(const etl::expected& lhs, const etl::unexpected& rhs) + { + return !(lhs == rhs); + } -//******************************************* -template -ETL_CONSTEXPR14 -bool operator !=(const etl::expected& lhs, const etl::expected& rhs) -{ - return !(lhs == rhs); -} - -//******************************************* -template -ETL_CONSTEXPR14 -bool operator !=(const etl::expected& lhs, const etl::unexpected& rhs) -{ - return !(lhs == rhs); -} - -//******************************************* -template -ETL_CONSTEXPR14 -bool operator !=(const etl::unexpected& lhs, const etl::unexpected& rhs) -{ - return !(lhs == rhs); + //******************************************* + template + ETL_CONSTEXPR14 + bool operator !=(const etl::unexpected& lhs, const etl::unexpected& rhs) + { + return !(lhs == rhs); + } } //******************************************* From a3c8f802166d9741dee58c2be5864098ddaab1ec Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Mon, 2 Feb 2026 17:43:26 +0100 Subject: [PATCH 124/298] Make typed_storage constructor constexpr (#1291) * Remove AppVeyor build status badge Removed AppVeyor build status badge from README. * Update README.md * Update CONTRIBUTING.md Updated the instructions for contributing. * Fix for issue 1276 "Data corruption in the etl::bip_buffer_spsc_atomic" (#1277) * Reproduce data corruption bug in the `etl::bip_buffer_spsc_atomic`. * Fix data corruption bug in the `etl::bip_buffer_spsc_atomic`. * Make typed_storage constructor constexpr --------- Co-authored-by: John Wellbelove Co-authored-by: Sergei --- include/etl/alignment.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/etl/alignment.h b/include/etl/alignment.h index 73527765..41e8a20c 100644 --- a/include/etl/alignment.h +++ b/include/etl/alignment.h @@ -367,7 +367,7 @@ namespace etl //*************************************************************************** // Default constructor //*************************************************************************** - typed_storage() ETL_NOEXCEPT + ETL_CONSTEXPR typed_storage() ETL_NOEXCEPT : valid(false) { } @@ -567,7 +567,7 @@ namespace etl //******************************* union union_type { - union_type() ETL_NOEXCEPT + ETL_CONSTEXPR union_type() ETL_NOEXCEPT : dummy() { } From b51968d6dd12d2360e34836042cafbf37d14f50c Mon Sep 17 00:00:00 2001 From: Mike Bloom <91038685+mike919192@users.noreply.github.com> Date: Mon, 2 Feb 2026 13:35:25 -0500 Subject: [PATCH 125/298] Add basic_format_arg constructor for ibasic_string (#1288) * Allow string as format arg * Remove AppVeyor build status badge Removed AppVeyor build status badge from README. * Update README.md * Update CONTRIBUTING.md Updated the instructions for contributing. * Fix for issue 1276 "Data corruption in the etl::bip_buffer_spsc_atomic" (#1277) * Reproduce data corruption bug in the `etl::bip_buffer_spsc_atomic`. * Fix data corruption bug in the `etl::bip_buffer_spsc_atomic`. * Added test string escaped * Add temporary string test --------- Co-authored-by: John Wellbelove Co-authored-by: Sergei --- include/etl/format.h | 5 ++++ test/test_format.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/include/etl/format.h b/include/etl/format.h index d090457d..95dafc8d 100644 --- a/include/etl/format.h +++ b/include/etl/format.h @@ -284,6 +284,11 @@ namespace etl { } + basic_format_arg(const etl::ibasic_string& v) + : data(etl::string_view(v.data(), v.size())) + { + } + basic_format_arg(const basic_format_arg& other): data(other.data) { } diff --git a/test/test_format.cpp b/test/test_format.cpp index 31bdecce..2e148bb4 100644 --- a/test/test_format.cpp +++ b/test/test_format.cpp @@ -282,6 +282,68 @@ namespace CHECK_EQUAL("\"data1\\n\"", test_format(s, "{:?}", sv)); } + //************************************************************************* + TEST(test_format_string) + { + etl::string<100> s; + etl::string<10> s_arg = "data1"; + + CHECK_EQUAL("data1", test_format(s, "{}", s_arg)); + CHECK_EQUAL("data1", test_format(s, "{:s}", s_arg)); + CHECK_THROW(test_format(s, "{:d}", s_arg), etl::bad_format_string_exception); + CHECK_EQUAL("data1 ", test_format(s, "{:10s}", s_arg)); + CHECK_EQUAL("data1 ", test_format(s, "{:<10s}", s_arg)); + CHECK_EQUAL(" data1", test_format(s, "{:>10s}", s_arg)); + CHECK_EQUAL(" data1 ", test_format(s, "{:^10s}", s_arg)); + CHECK_EQUAL("data1", test_format(s, "{:3}", s_arg)); + CHECK_EQUAL("dat", test_format(s, "{:.3s}", s_arg)); + CHECK_EQUAL("dat", test_format(s, "{:^.3s}", s_arg)); + CHECK_EQUAL(". dat !", test_format(s, ".{:^8.3s}!", s_arg)); + CHECK_EQUAL("^dat $", test_format(s, "^{:8.3s}$", s_arg)); + } + + //************************************************************************* + //this minimal derived class of etl::string is used to prove that the + //temporary lifetime is long enough for the format operation + template + class clearing_string : public etl::string + { + public: + using etl::string::string; + ~clearing_string() + { + this->clear(); + } + }; + TEST(test_format_string_temporary) + { + etl::string<100> s; + const char* data = "data1"; + using string_t = clearing_string<10>; + + CHECK_EQUAL("data1", test_format(s, "{}", string_t(data))); + CHECK_EQUAL("data1", test_format(s, "{:s}", string_t(data))); + CHECK_THROW(test_format(s, "{:d}", string_t(data)), etl::bad_format_string_exception); + CHECK_EQUAL("data1 ", test_format(s, "{:10s}", string_t(data))); + CHECK_EQUAL("data1 ", test_format(s, "{:<10s}", string_t(data))); + CHECK_EQUAL(" data1", test_format(s, "{:>10s}", string_t(data))); + CHECK_EQUAL(" data1 ", test_format(s, "{:^10s}", string_t(data))); + CHECK_EQUAL("data1", test_format(s, "{:3}", string_t(data))); + CHECK_EQUAL("dat", test_format(s, "{:.3s}", string_t(data))); + CHECK_EQUAL("dat", test_format(s, "{:^.3s}", string_t(data))); + CHECK_EQUAL(". dat !", test_format(s, ".{:^8.3s}!", string_t(data))); + CHECK_EQUAL("^dat $", test_format(s, "^{:8.3s}$", string_t(data))); + } + + //************************************************************************* + TEST(test_format_string_escaped) + { + etl::string<100> s; + etl::string<10> s_arg("data1\n"); + + CHECK_EQUAL("\"data1\\n\"", test_format(s, "{:?}", s_arg)); + } + //************************************************************************* TEST(test_format_chars) { From 21a1f58299cf48e8c7325d329c386dfda438b932 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 28 Jan 2026 22:29:52 +0000 Subject: [PATCH 126/298] QR Code for Github --- images/QR Github.png | Bin 0 -> 20490 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 images/QR Github.png diff --git a/images/QR Github.png b/images/QR Github.png new file mode 100644 index 0000000000000000000000000000000000000000..94c76e0ef54db47ebe96a8cd7f045ee13f37eacd GIT binary patch literal 20490 zcmdVCc|6s5`#;`HBTXvJ6sCkWscfYX$1Os& zux8DgO=_wqHP@{9J{A35zYab#bB|yNAHH+cRQYX9M#IiA_`?roN@tbUtjP-EU|wZ| zKmTa2s_VFB4Ywfr{hgZTzNs~9G~(4xDrwy^n&@(Ky43DExok%DP}-%d^ZlVM_@922 z+ORHdUFyCMsz)Arw>(RU*>6kTCzRLHrPgzGq(9H%QIg9}oQ!Xbdf0K_Fk*ou*Zzp` zj)S|tU(fOC-s|t{>c7A9E5%6(pPn;ZbM)=@Nd}F+Y^KO4b`)?|yjHinek4eKB+e?M zz=LBO$8X=m8@#putS96{!O#Q6H1s{y|{BOR^4_ zZQQugyz)L{#g>n9JIU+GlPBhiU*_j6D^Iz&xDY*`pN)AIQEg#uEz)InIn$_hL-5X* zmop=`AH8AT_ydO}|)}M=4NKagt9IOs2d#dc;?-6yf>#>ZZS76{~zDiHq zpn?+a$)bJDr%#{uTFbt9^gvh?Zf}q7cDn%cW3|KC@scZ4f&cX@{(ro;m0rOswwBbk z^lZ~w?yQxC(9oZCb1ft0gAZjG6zpNlPlQcR-%Rg#k&zMk?AiW<2M)aV3$SX>P@d)E z<7@Q`uxNQ!{kip}ps=vIu#}PO5Le2}mti!TExaNv?LixUxGq{R>*nCQpHkA(BXZ0d z;jZZFMl&lEnJ1ji>C`kf24(0Q8O3Q^=TqmZH9RyM;uSNwc%}OYIfSK__`tS`=J)S| ziA18Rrzct48t(KvagS+^0>Wapw)Hk{?waQca|d-_UAd!e{ouialOq*#)b?DHy+@B8 z?J~3Nja*tP3Wxc|%rdo98-%JerU8|WwfpTEvw;v1PUe}sHB3)L=+N$ut`{~oC`PcS0YiAg2 z|MKO_=mD3_{Bpm9M@GKoJBoeb%a`gZS&j=+pLT7$aI@-5mZ(Ag;o~>^?>2bMd>$X) z7%8gHjSu+Q;*9v^AX=5fnBoADeuZXWMf~KhOFnYEU0sHS6xYvu-Z8 zZ{JSJ&AsFn)_zvHXCJA@B_=7kv$SHoD_8yV=g-%#T=`X4D)r^dqmeSO5Gm)dHmq?p4QQAM`2C0z$b?Zi z_S4Kzt){-dFoQnX?iWyA{u}g$a7n8+^U71k#>U6`oph6IOW{jh5TtU8l)Pf2ogVxslJI8^oz%F4=LKet|BUe<55 ztEG`~nP%T+|E=W3je>%GufZSf7{I_vsxSBs;i!(AzC5 z-_}G3CoXdH@K{ya`E2G3?dsB#@mwj^wjLZAsg3Dl-l(pwZmJnPX47?SF;Q`8??Dlf z4}P0S8Mf{{viduA>DoUN|M{ltJh`e)FmslaId?>SEil6JyfDk%j)X+P31lz z8Gf=HI#u){a`5n}6QM#Z~#W^E`j9qB3o)udjdDakwtOPcS6UX{`BUfOPNr z{qV~fceDTGt6S6kqvKiDLqkJKDk?rk%DC9r*fKa11A)=z{v-_%z2dB&ZCajda2k0m z4ngm0irh$h;ACc6Jg0^Vx1+%EIaHavHznsl@58Y40_)I?s59Y=p4OWxS~1%de_u7e z%Sq7dD0e)5P*k@+z_ck;uvdp$v^SS%zGfx!|2UHVS20S~t|W3ySE2Ju>&|TDG)0er zw*lEU-BJ^ss0-jGi(3e#DbJogJN4+%qkTA>zOaup5K$W?4oIdsSv`@et*s3xq&nTs z#wLBIqKAR76u^SPYN7aWKrrw{$?8#08U0_zT3}K|L6wlNM zH~00yT)g=FT!c{Et>3uCji5bl-@d&`HouWH*l>i@I6vN*$i?gG>e`g!*i-1Nmvux= zZf8BdDv(bvx)@6OsoC?~B3hyFLEY5SQX?t5-Zc5WVlVceINrI7+rQw0Syy>N>fVkG z(kC>BV=PhYfVum%!+8yK38_vT!(X#kry|IXStyqeG{L2!O@# zr=%VDiGIVDlllvk_di+RD-);5hnYLl9VC*vmcCE%`&-d40QIG!lyrSk4M2f6O9Rrj zlmp#)HZ5_n?u_~B#2^Jrg+47uYC5UrqK3R+bTmMyEUR`g1g-Ae`R*@Zth7|Y!pbTv zE9*#l$8l(K1bR_lL|K^EDY7f#YKl&QIe{*cBHm-czF0bw?2kZw5)R~ zw8WtyHB-~%!NEb8dPPRI?mqYL6HNvH)XkJkx@!Ome9A@M#L1~bwFkVN-f=)oEV9va zWmdv-g#b;FUOC&SD9$5h@ZPWQ*_r4)8VZX^B8G)p!cr7hZJ4rd^W#l^oA6{wDXE%5 zXDZR8BKBI4+{_=vOP^mtWl}tJN^a-Qk5m4=8+Pt`k?QOF}*l_w!hLpaj_x#sEV-ExyQ$ML%#}zvt&_u3JwfWfLlZ-fr|_%ORURGC2(hxUx1DX zcPx(fJbA3;c`bRBK~@p}m{MM{O)v9AD%+(h`Jf(0*K9}nJvT9Z_2h)lUe`5Y_?O4j zCu?Dy`@57RnDy@f+yY#)fcAac%?-w|sHmvYFZ-d*s_GXwn7(gmNlfgJxixj=yq?|; zeBDVs817r{tMOGfe5&yA&d$z881vAfLtfB}sRvvF1r+(~;#o)0b#|ByPIk)$W_xGn zb`kwN5gL9v>l-TQ)G%T-Y(NU%8n&0#&!xAjN}l;jMJ=aIOaIpx-+yZMe`&#`g@t-? zgc-Go-Is{Dxz&4vX&KvCx>Oi@r-i}q77)wg+ z_`*W|{P@1TFA8@>Z~Mw{4h2LKzcLzpY;0s?WWtLV2fp@rd3ky0@l$uU|CP{eT^E{= zmL`II*{^KRHR9VYjNiQ@{!r1=gK`8b^FTh_Gbm}e2Sjd!NeisndV4c~%(&G}GC8^SJ%5Dp>=xt9bD$-lHMfIy%3M_Y?uK8fZ|(Yro|UJC$RN2#)0XzmXds1ccgdZ-yAqa^z82L&i#I0)m9C;-3XJ$1thVx z!qnKlbLR*C;GJV*W1%rI!dW_Jgr(kARV6N4xx3}FPa{x+R1?2VJRRiK<;mK5={|rS z78Vvw>c7t|?H7JgxLCOS(L?Xi!-s#&dowH!>MBX<&N?$*Pq0(x&T5}O+eYXq_}JDS zyEQVDODjy$_~U9rEE%9nS562qVZ+B&i`A9ornQUEx?#$hRQip6cUey_m5VGW{NmZ8 z>ujxBVQC4EEaA0xwBGjpZ;Dg@sa5@(c7~*qxSul&i}s`58@KxGY|MTxF0QVaV$c}| zN1GBQjvRTyQmERb<>d{9J-W%BWYma;YNMc^O!rsLB#XPN*%prNXHiu_^+?qlH=b!* zLqYA+^I_>D=gyrY3S{Txz$?tn4|I_$Dk`92tlC5t1y%<<-$4Q8_LI`m(#+j^N?(0w zY1zvu|0Ni;Hux%8*&T)?UTIt4vha(z8Rk9!%BUzIdY>n`E*5tg#^vJZFttHlohFB; zQXBBP;zq9#V3r9yR6MMmt|z#@7nTdr|G~27W;L%Gk!UGr`)ac@Z<11(z9^lqMJ5vK1Hv@`fo*vdEuOUt$r`i zG1RI(Ij@)bwWQszg-){pkYF%W`~0rgd4tY zNqdw_B2iNpGK-3EFH%$e7@+LX_+9APxxh}>S+%A4;%@9oPe|C+QQ}4lG!Y^ctZz%# z=Rp|Y7cFmq)iCZ)si=5^m{rB+n4QaGbW7=Sr6)7s?@?`82Ln@k4qk1~Fr1mH;IwM= zw7cCBGx)@ZKU7BqsLj}1yK$7b`(3KqR$26DC^#uk_%;^niqv)H8Suk63snVMtg4Bo;ugpFjJ}SL9l?1J@!Fk9BcY zR#t+P2#3hL6lN5Q;228NTQq@N5j`Cp9N-I+l1`Q~hs0IrhKKCi(*ZGnG6!tE<=I(( z8V9~q-+`XhZH7jdUqEqjv3V(p;@}Um;-*d2#w$a{k1{j6$+o3-93r_uUiM`moHdxWjZMN)hno7gJ370=s6E_JG&@+3DwYHtXU8W zU8#pJ)WRZfb+P~ZDN^a2X!Mb5FajRSIv?ud9BGIJwh0sVonxcC5L6^w5s+9%3xREE z!eNl}1l9Bu)w+6OElD8F_+zM`u2SoAg}1)Xg9jjw*~gDHRO{Q7T!I5BX^amnn5|o4 z>#QdwB>XCI^k}Y0RXyIxNy|-&BFk(NSPo&fdoD+5k26PA6homFtr`RMjp@Gy|6I;? z>gVN|DDuYgn1l5}L-3dj<3t zOm-rqU>2lx0w z=p37vhzJwXfRgDgaT~hB&L6x_)UgJ7La151yEaxEiRtO0dVLtL(g(#xAgLT1FH!;h0|9aJh7b%N6z9 zlInvNO0DvDX(e={+238N`0(%Oed|1K;d z@?i4@b+KOy=5kAIs~_2Ai|A&bES=BIRJ(aI3sC!fm(>gnPu9n@w!N)hmLM+^1t=Qo z0|Nt1E6$3df>xzS21flo%+GH_`huvgQZ8^qk1vS=)#;>OAiy-`*%Jaw!8>K0RE0ep zSEoMCS4@!lpdrx;#u{RKittvI_ub0uXAMcVvD)MLjE?&5M@2z7+1W&CwF0mPK&De# z2*!_<5p5{>7gSz>h!-5b*lfOv>+<6g_JYhGsLRLFzwbOjDOoRbqL zPAGwf{1svw5vG;-*iyX67yirE-M^tDKepY=Js;*Lx`&|u|4a?ago0M#cRlIm0Kqc?sbX+$v`AyiP7IbazBiGYqAvmi z0+i{~K-l1V!I`ZVSe+KA_1!82XRYK)fqP^~$P+Gd!SBQK-W&>%6!+n_vL&YT>YC|@ zOoH+uVPQC@u|c%QP9w>JbWTBAKF|>0mFd)+Mg?K8RY2m#D==G)mm|P-Ft7Ba$*ks) zO2Do`M|H6^(<50P*SFY!zg}^F6J}|AMM+_$CCd|boB$}DF73~Rv%>zV`vygFChH!% z9a1rJ=zmt65wFb2xu|j{_o!LJ4}gzvw#NoUO}E=j`n4&Knx?;m-)@gF*Ys zo#7H&5<7KIP>1Z{PC4RkvuV>NSvUQ!l5#pwW|dbJ{{-OgGTyP9Q*P?_`Ei(awa}rT z$m0NCYZ@74$m0Oih1d}Wctg=Gf>Ngh!%wf8YVCj7$W>Wkp^UTU_3Ph3Y#Sb~0gHGa zVh2(nJMD^Jcq5bq<5yV9!NK9_qTZwrxIM~LHx?A2PKmG1h-)G~#JhLz-li4IbnSy# zojAK2vs@{je$-pE43w5#3Ju)^norQXxdHMO<;EpT8rx_K^3k$c7^*wpA8#?@m z7p~o|V2B%(kDWWik$E=ExN2gur^|{~aJ70O6G$ldEuh+w8o{j_OpY>Y_FFAonaiy0 z%C*Wh8$nGUK&n;aId}IG>)v8rHz@>zyq|#k;O0VM18uR_jQ>4AS|LUF$@g*lTY$0{ zVpqC&W1&$b{rRNUwOVUfz<{KyN$kwE265d?muk3+~2=aHW+Od z7gAGm8ZOg!9X)p7f5SWS`n=jd?>*-qIndxt&p+1H3wQ04Fux6 zrqVBh_3}%H_f+s748#2w^-FF$+e0%ln^h@6zyCW~-K#)*Enh0Mv4$S#iJxq6c1wPa=m$TT}CAmVUBTVbD85 z`0`u6mMZP@=eLaamgt+=nO(WEONV4@i2fbS@@p&SnY^;RGPm4nF|!bK}OTSwIm5Zv9{lK4Yxn_GUl;$pzmm&x-OpbAC+Icd% zhr0V#^5(~r^v?GHd!)EcmPlX{KkZ||t?8$WviWOAiu#r_K-RaYw1c9bdAB#{BNvpIbC^(tXlR0@F?5+&C*W*W;lK;i!1shD+>v1>e_~ zUU8i>mF8hjzgMIvayCZltOAJd>dMOZw5=g%Q^V+`E4U6tT!uRXY(rj%;wptrWt!_) zhW@#8fq<*5PVB zq%U8bppU}M2Ux|T;N#;DXaktKZf`{$#<3z6b#)IEx|fMgG)jT_Y8;Dq(pTq6WKpQ5 zX1@SXeX8SE7vpQ25>+r7Z2%qY`mI|aP;TJh7%CWv^KXz;2SVNC>^9eW8R9x%Fh0t3 z<1dS=m7x_*KuAQ`g|ZkN74=*mH_{j%1>9(&GbJ-Ksy;^Asu2M%Bpa098W92d{lvt?%yf{a z+#~!Udrm3*UX3$n%q#7XTE%~|txQ}O9e&p@O)AMS(1fLKG{%X>GbkfTn2=@AadS3T zp#_@4vJ~(vm=of!Y*zu~L$V2eZPQL~Wal~1Lr_7TY5-Kt3u_bz3$LIR@cc&FOk-;b z#o1A0b=av0gO$q2$mrdX#P@_w6C6jDCYO6BEgBox6{fyJWGP)9SG_(}Y&0p{raQ0T z`i)+g#$HpwkosU^%2VW_Y9k{nVCN-No+W-r(aLfKDucb~r8?RnLHJxZ)0q5*i* ze(8$^7);XxRo;uUBULa{zzHt?2m+bxhBRk9p8e9LOMur-so!gR|30Cpvkf%P{=g`( zbyEYc`1}({2i*Fkq9T1amlY~`MV(eO37{MqqriMu!?D6Ia+wH)u6Q{u%GKWfFeH8& z)Bl_vX=~G7%u!_Im>cWt0OJRk+dJskaDOHhp}y7B)dTPa&{%5lrL%m|3hr<^T>dS- z23L{jSzBA1YchZ&uT8vCh}L{1;60Nbmxmi-UviO6fl||zk+{or0nKXES`jgA=5PZq zskCjxE<1lD2qM4K=OsR(t~u*RXS@N z02~WtOp^QLR5w8y4(?*EnGm#Hwj5wZ0Iwhq$*eSH-g^)bz_NmH?;r$ZRw_VQJBs9i zME9#>k@~hFXp~4m{v~~(-Y^q714hM|r_L{n@+?rC)gwNRlzSJ6bBpRFagmet&d16+ zTM|o2y|-V&&#+SVX1SsXLUcgAbai!SD2|PSf(glwssudcmVEfF;+H-=56vzG1RM?{ zo)v9@sFe5NF9lkmKa0xMd4abZTe4ctb7vPJzj9d&3m05{@!ci|-FBd9zMMmRbp6V}e+L`FVC3UM-y&j^!lePQ5^0(7vop#nMhSmq7y3&OgIbIv2L zl2KDrylw`Gmist-AH9@bjR~j~6Z-U>*+%SDv1ZWmx@P-I=)J<-B)j&wSX77E9?Q2U z76TGeL2F7*OFQGXQZy8)KR5}NLjBsi93Gx@yr&ue?_tSLpZ=yWm!hF&3-Mp;oj4bf zCCbW*2WSCe!33&)pC7+NB=q2c8!bpTBv2cX?<|`p@A>yu^*%p92r+D{kTAD2E}pWD%JCVeWL(gplBpS zkY3CLz4stE1$xu*`bfW<=)CD#HQ|r!1&I&s?d&MYrKR_C7vQz|U4#y*W%rML6rc$> zr0-0<{t<-&=3PKz^TP6^=bmZn>TU=3a14xt#KgT1ad=w_6fDRZSM6s8Ar}zHs8jam z#)yEC5&xgn(ZuQx;NW-xH3!$h4qT%bDJj0lb@=43J=O0o4(U;@e*%Ea%%nX_0;^MbV^>wUMG>DDHZ2c9$#=dJM{8K_1X#-}2f$ zWKTg}=6l)1#L)jU&(E5STH5JQ)CR$hdBBZ-ZpYt|EJR%!z>$;79WZ zH3`N6oB+@$`ho!?TUOdZ+~71I{?#o5aduc3b`w6nU?kX$Ul+{WU=6Smn!T6JHh z8VAi(Ck=n~&D06QsE6Bc1#;@KSZloQ>O%}qgKn^%Q{Zb~m%9t5nO;8v-j^>&W#q*I zH)99G0$Br>w6uOem;J*2Ot|wZRzKN+=SF*UkJA-$^N@-@f9Vnzz39xdVH63_&!_&guXaz#1D-CuK-k2HBX*|t>2%tl_PL;8nV$o=*clcXj%uXg3 zP@P-ON~`HTnkX8H>HV^Qv5eDW7Zx1|KvEIC5)c6hS z8yd1?q?tH+u?onWx&35u&&ArAA|Se;hQ{%9c6N5n@+w^dn;w!dnC~${ZZ~o}8+WVU z_rQx}FKAUL%614vBC|eyKebHn69>=_(;`$*eek96a_Tme&pibMu?|`=*oJ_iZrwUw zD4s@-<}kNiH7ayc6Ao*Ez`@QQ9x)v~2l11(ib*wV0~40?X>4tVB$i)sXXcs!;~`7w zp*VKbOJn`PfFc7F=8M5OE}9&~E?VOFcz(CCv?Pwm@MvAE&a>$@cqL``=_>b`GiSg) zY6mIXdusPKd;r1v6E7Z8SRhIMD;A@W$0e-&1B$povI-b=8KuB+AfxHJB}8bO^v<}z zK~w_VOp$yl*jxUQcbrmi@iK4q$85FYTn%E$R5^#N*XjcA-?@d8th1%L?<|D)YSDg# znHlOy&W`+|8NfmD^4|5Nm?E zi-?L+hh!HBUFN0^pU1|0=PRC^@ByWILZ9T>qmVb)pn^YFINKcRR#&vhVpc{*MozRe zebPDM6-VloWr8Ec*|E{hYVuYU?x|$nJae|O_WmYbaNfFz7NH=4%JV`47CY}TxL3f} zc8fZ~t#Zt%3LuPaZTnGR1`>xJj0v?LU!x5db^*eBX2SU7WE3bk4~%><>T zAuoaK>oPC4(8wE%__ZMH{?T@oK!E(Nk=ukMBIEVO{h-_<9?XC1<9A~;8k!Ma;~DxA z{3lcHqFN<5F|OL%qpZR*m39rUsDJ3dfj=6mF_rO`Uw-+6CQW~w6K<*08aqNO=mg9U zuGAteL*LmsS9^S)@C(?9F@AO~HdP*n`bsi{lif}koIiUXQYX8LZ;4Gj%mY&Nd3_!V zu1oacX!(2B_mx84P`u=e=9W_DDi8_tAjQ0EW0@?Y`ekmeBt$p^i%wyn8&x$ZCEpSa z_$N@p2|JveoJK7x^fWXyUO5caffl%k7FD=Y>>S4L(ST3W$1 zzJ2=^!~+-sGa2|2btCt=OX(dCrEK(^&Osa(eEuZ{BXO~mIRlZYkeC?WdJ;q^!PaEF zmY1euIdGcHGzuTU>3+$D6Igi7ejOB76kzZN=k-rw$~vrp7oKp3fCe1)>(xKIg7*HD z-6t6~Al_jEVUwI`O*owUkr)vKP|y@;n#0PKt%l63C5MA<0ts7~J5QJOAvDBAb_Vs+ zn^WNcLS57PAY?m{hfuosl$x3vX!1I*euejXr+K0;Q6&hjFNa)JkU$g`TDtG{oqf9~ z*1#$Lkuj5)XOcflsc(;+1h=3aGP#Qu)kF7D&Sa*`D$}Aeu$v4Q9>8M|VQ??(Yo%eD ziS3=RJ&&!ol$z#$3%0Yg#jw`im3b2T)rTKCyE{wW-GV{)!q-)Q(9SgCyUQu_7peaI zCQPdDfOs`W`T6Zo@m-MR_dd)VJFvnbFjEG*IiRale*k^O3-Y6eT&v#{6f%d+OfD>> zeXQg${?K#P49t}dq$M7K<*k@~6<_0? zs^O$Wyj?c4cXBz7`Q^D{1VjkZI~Jg{_IggSd+tKfwCKlZ4=&yA>QyM@@jkLKGH<`7 z`8J@fisohz$sv=gN)$jBloj+DiT5d2AZ z;FvaPs3UVfetFz18|o7Tw{~Hukmi;aP+%a}t$F#f5SD@MGs)5+dZxGU<|LK3 zM6)V3AH;SW8(?k@LBbEHD{x)lp?hRIL?9EOrlO)!^TYi0o1ACqhx0tHfGW?obLWHk ziqTPI$bDo0!aFr`H+g2pVX--?bRS3}5Y~ki)lq_K1kZ6&sps5fPgDLh2pT+f6vF1s zGmUtDh&6qG?I0u_l$7oeru~h>AwXzl>ab(`_7KE}Ht#$RSFw6SY9LO)An?^ZShtc( z>}#zAmfrhZ@60xZgFX{Ir#O}W>-Qf$!`j-~67usqO4uIe!3xLK<4u3=_n@-uK6Kpq zb9kVHYpjC1te*cZtHEm=#v)#jx&sjOO;16T^*aG9f1~JnPy9X>Nnqv6Z%tS7IER1O zQfiKroIDg(Q<)O@ClvO7Ot*TtfmLxGS{Y0>uJjJb+!PR28GTV8a_9<6f#kMNT)dIs z4to=WP#cjLaeC{;#xaOW1VktcQwIm??M8X}JC-poFJ?>0-;H(oBPegP*yt$+-yO0C zNC-#e?21(Ge$t;e4e!HZqN^MhbEFyAk7VL}L;;N0s1Kg$yZ9HB-< zap{7L>r4{ZW2UCnh0k!+K>PM@91+zO!2qnS;ItZ1;U<2kpUX`4QFEw zwzf7g_f^}sRR@%$ft)1dPr=dr)1s^hYf;t(HZQ$kee0{6Q@qgcFS|jL?VnJP|FiP* zAJYFIB{hHeun*!UdebrbKA%2aon<^tPd~fT?a8onnC@4GVuef!NK3VK(MO@6AaV*z zIm30^A@IcQuLe<;FD=aw4;~UyT=d1ptQ1JUJn55GnI+(+(ilaK@}i=WD-&;e$TS5P zdQS46OY#(KSR*qZg}zMoii>Nk3@EOg=$(lq!CsJlH`t|}C`OBA#i&JCQ@!cPFCfqk zp%>$P$~Do5;TQ+dp~HmY37W9gAf_r0)}sWrw4cJQ6~r%p2y$hfqV1WGzX<@n%mQMM zn2?DUWy&qlY7%pJK1!b*zyA66^zWzci4%5jh>V0()FC)+j|~tVl%f>!gU|^l4h9EU zurps;G-@F!l-nuB*Fe8xAclZ_ir`oiJUQZCa$^g*~ASdQ)^#bvH|Ni{>ix;<|&@t=@ zVd<{QhBt3czPeg*9}2h&Ful{ZZ(*2!iVyjpR=#1q^g7CphCzD&5m@RFdCV{@LQ6aA zQ0_Gm5GtHWEb8*_vG~2*{wM-Y9HbfJjdl8}PyleB6(6`Lys>8B&cM6`sjdLr{~<^U z1E2&Ei^&{Oi~=~19FFy?ggy`El-ZD`1lQK0c-pCqal1Ta=sumH%CL z?>tJ9kCdaXj5%yvI7LQh<5zcO1l$|aF)1l{>qz_>?b6-zBK1FP5Un9SgoO+uGZO8WmTIVf6!KkqZ|t09Mu`!h##B=wJuN?n@0h*Ke-cJAqb&!jph6 zc(_TWw0o~Z85EG(OR}$&!5Z{UdL=cJ43Q)hwcLaD6LNA0iw+FODz?_^FETSZ%l$_* z<1H{p?RH8{PWE##ipN?)><}4wU<%L( zSqWTN<$kB(F|&1c&Y4l0K8XdH>K;j|L&>bDAzTT z-D!^5Xr*$YK31Am2-?s&nAncxv78YR5h#3j;v2yAa4c*5T0enB;$p_7P&Pq|EBVMj z{GV7MrgGV5E8Utl_iO26tRe2d&$Kk94MeKDoUTCFVM$NP!{gfqV)@i_*dnm| z$l7N_wUYo2GxRkX!h-#Ih}1!1q8pMU-as`!j|*isG&EcR!gRCUTq1X>QWV93E=|W{ zkLf{=?wOgH`HCr71r;!Mjn%2l;&({dbZrB@tIJ?M=dI`R+Q0otODv7orl;^yo^|IQ z;PSBahqjy`uKMMRs+HBt`TdzOwuNf8MH5nL>N)N{ow-&~z!Iu4kwxqBWu(deYuone zq7fvUA)_j)w{LYJX!QWxUsxdkee@lmOEuQ~(bCpF4H_D%4JfajGJA4!bFnmL#{pqs z|F4^0l){xNPo|Fn*#jc4P(44@)A1f7c+j_iywCV*5XuSe&tY*KmbLLt=aRmMx{^h+ z6iCp~qo%E?mxk##vmwo(+$c?*-3=(}wh=t=0u(1eNyqvi)(p`dw8JJOZQYT;g{tV5 zW_I<;GGhqDny#FS#>V0?(spfeKk;aV?FLcENG?kAEbs^CACf}R12xdo4gQ4but&0d z0uun#9)N4!Q^~6EET5^5WxF<-eSJ*JahT|VCL>dyDwKXXgx0ySXFa$0q?qyJT+YCY0S%gq_QSJ$9NW`MN(><-ipS$w9@l$w?RwK#FwT0M^B~>RA2?=( zRH4;5&cAV+_TqPg#;Z zdZNYPJszWA;4vUxLXgH97AN39u~Jbpz*v7{Awy_Kz&WnNEMST4^^YWB6ZIuVSe9AO z9I$V<0$A5njBWW*t=xM+a!bm}x&V()c*aEzfG0mu-*ZX7?2T{0Mq}`ZQ^l+j{ zWLh06sCP#&%8?=iqc(*LM>B{&Y8E)p#CO|})BsHW58fByc03qyN?i{gVzEWxu2cJB z=2x*CS?Suh3~dkf}O* z=FAVgQr3SI&HEyslFxLe|DW^dCiro7p@cK6|3a!s)6h^9a10o9a2Kyn_Li`q1)%7# zZacCeHd_)&B Date: Fri, 16 Jan 2026 09:02:46 +0100 Subject: [PATCH 127/298] Fix year_month arithmetic and correct chrono API behavior (#1257) * Fix & add more tests for year_month arithmetic * Minor addtions to previous commit * More missing values to be uninitialized * Update the default constructors to = default and correct default constructor tests accordingly * Fix & add more tests for year_month arithmetic * Minor addtions to previous commit * More missing values to be uninitialized * Update the default constructors to = default and correct default constructor tests accordingly * Restore default constructor behavior for chrono calender --- include/etl/private/chrono/day.h | 61 ++------------- include/etl/private/chrono/month.h | 54 ++----------- include/etl/private/chrono/weekday.h | 20 ----- include/etl/private/chrono/year.h | 66 +++++----------- include/etl/private/chrono/year_month.h | 16 ++-- include/etl/private/chrono/year_month_day.h | 20 +++-- .../etl/private/chrono/year_month_weekday.h | 12 ++- test/test_chrono_day.cpp | 9 --- test/test_chrono_month.cpp | 9 --- test/test_chrono_weekday_last.cpp | 1 - test/test_chrono_year.cpp | 23 +++--- test/test_chrono_year_month.cpp | 75 ++++++++++++++++++- test/test_chrono_year_month_day.cpp | 2 +- 13 files changed, 148 insertions(+), 220 deletions(-) diff --git a/include/etl/private/chrono/day.h b/include/etl/private/chrono/day.h index fa5bb712..6797c81f 100644 --- a/include/etl/private/chrono/day.h +++ b/include/etl/private/chrono/day.h @@ -57,39 +57,10 @@ namespace etl /// Construct from unsigned //*********************************************************************** ETL_CONSTEXPR explicit day(unsigned value_) ETL_NOEXCEPT - : value(static_cast(value_)) + : value(static_cast(value_)) { } - //*********************************************************************** - /// Copy constructor - //*********************************************************************** - ETL_CONSTEXPR14 day(const etl::chrono::day& other) ETL_NOEXCEPT - : value(other.value) - { - } - - //*********************************************************************** - /// Assignment operator - //*********************************************************************** - ETL_CONSTEXPR14 etl::chrono::day& operator =(const etl::chrono::day& rhs) ETL_NOEXCEPT - { - value = rhs.value; - - return *this; - } - - //*********************************************************************** - /// Assignment operator - //*********************************************************************** - template - ETL_CONSTEXPR14 etl::chrono::day& operator =(const etl::chrono::duration& rhs) - { - value = etl::chrono::duration_cast(rhs); - - return *this; - } - //*********************************************************************** /// Pre-increment operator //*********************************************************************** @@ -105,7 +76,7 @@ namespace etl //*********************************************************************** ETL_CONSTEXPR14 etl::chrono::day operator ++(int) ETL_NOEXCEPT { - const etl::chrono::day temp = *this; + etl::chrono::day temp = *this; ++value; return temp; @@ -126,7 +97,7 @@ namespace etl //*********************************************************************** ETL_CONSTEXPR14 etl::chrono::day operator --(int) ETL_NOEXCEPT { - const etl::chrono::day temp = *this; + etl::chrono::day temp = *this; --value; return temp; @@ -137,7 +108,7 @@ namespace etl //*********************************************************************** ETL_CONSTEXPR14 etl::chrono::day& operator +=(const etl::chrono::days& ds) ETL_NOEXCEPT { - value += static_cast(ds.count()); + value += static_cast(ds.count()); return *this; } @@ -147,7 +118,7 @@ namespace etl //*********************************************************************** ETL_CONSTEXPR14 etl::chrono::day& operator -=(const etl::chrono::days& ds) ETL_NOEXCEPT { - value -= static_cast(ds.count()); + value -= static_cast(ds.count()); return *this; } @@ -164,9 +135,9 @@ namespace etl //*********************************************************************** /// Conversion operator to unsigned int //*********************************************************************** - ETL_CONSTEXPR14 operator unsigned() const ETL_NOEXCEPT + ETL_CONSTEXPR14 /*explicit*/ operator unsigned() const ETL_NOEXCEPT { - return static_cast(value); + return value; } //*********************************************************************** @@ -184,24 +155,6 @@ namespace etl return 0; } - //*********************************************************************** - /// The minimum day value for which ok() will return true - //*********************************************************************** - ETL_NODISCARD - static ETL_CONSTEXPR14 etl::chrono::day min() ETL_NOEXCEPT - { - return etl::chrono::day(1); - } - - //*********************************************************************** - /// The maximum day value for which ok() will return true - //*********************************************************************** - ETL_NODISCARD - static ETL_CONSTEXPR14 etl::chrono::day max() ETL_NOEXCEPT - { - return etl::chrono::day(31); - } - private: rep value; diff --git a/include/etl/private/chrono/month.h b/include/etl/private/chrono/month.h index 1ab694d4..4f257da3 100644 --- a/include/etl/private/chrono/month.h +++ b/include/etl/private/chrono/month.h @@ -72,24 +72,6 @@ namespace etl { } - //*********************************************************************** - /// Copy constructor - //*********************************************************************** - ETL_CONSTEXPR14 month(const etl::chrono::month& other) ETL_NOEXCEPT - : value(other.value) - { - } - - //*********************************************************************** - /// Assignment operator - //*********************************************************************** - ETL_CONSTEXPR14 etl::chrono::month& operator =(const etl::chrono::month& rhs) ETL_NOEXCEPT - { - value = rhs.value; - - return *this; - } - //*********************************************************************** /// Pre-increment operator //*********************************************************************** @@ -105,9 +87,9 @@ namespace etl //*********************************************************************** ETL_CONSTEXPR14 etl::chrono::month operator ++(int) ETL_NOEXCEPT { - const etl::chrono::month temp = *this; + etl::chrono::month temp = *this; - *this += etl::chrono::months(1); + ++*this; return temp; } @@ -129,7 +111,7 @@ namespace etl { etl::chrono::month temp = *this; - *this -= etl::chrono::months(1); + --*this; return temp; } @@ -155,7 +137,7 @@ namespace etl } //*********************************************************************** - /// Returns true if the month is within the valid 1 to 31 range + /// Returns true if the month is within the valid 1 to 12 range //*********************************************************************** ETL_NODISCARD ETL_CONSTEXPR14 bool ok() const ETL_NOEXCEPT @@ -178,30 +160,12 @@ namespace etl return 0; } - //*********************************************************************** - /// The minimum month value for which ok() will return true - //*********************************************************************** - ETL_NODISCARD - static ETL_CONSTEXPR14 etl::chrono::month min() ETL_NOEXCEPT - { - return etl::chrono::month(1); - } - - //*********************************************************************** - /// The maximum month value for which ok() will return true - //*********************************************************************** - ETL_NODISCARD - static ETL_CONSTEXPR14 etl::chrono::month max() ETL_NOEXCEPT - { - return etl::chrono::month(12); - } - //*********************************************************************** /// Conversion operator to unsigned int //*********************************************************************** - ETL_CONSTEXPR14 operator unsigned() const ETL_NOEXCEPT + ETL_CONSTEXPR14 /*explicit*/ operator unsigned() const ETL_NOEXCEPT { - return static_cast(value); + return value; } private: @@ -331,10 +295,8 @@ namespace etl etl::chrono::months ms(difference); // Check for validity. - if (m1 == (m2 + ms)) - { - return ms; - } + assert(m1 == (m2 + ms)); + return ms; } return etl::chrono::months(); diff --git a/include/etl/private/chrono/weekday.h b/include/etl/private/chrono/weekday.h index de511a83..19246368 100644 --- a/include/etl/private/chrono/weekday.h +++ b/include/etl/private/chrono/weekday.h @@ -362,26 +362,6 @@ namespace etl { } - //*********************************************************************** - /// Copy constructor - //*********************************************************************** - ETL_CONSTEXPR14 weekday_indexed(const etl::chrono::weekday_indexed& other) ETL_NOEXCEPT - : wd(other.wd) - , i(other.i) - { - } - - //*********************************************************************** - /// Assignment operator - //*********************************************************************** - ETL_CONSTEXPR14 etl::chrono::weekday_indexed& operator =(const etl::chrono::weekday_indexed& rhs) ETL_NOEXCEPT - { - wd = rhs.wd; - i = rhs.i; - - return *this; - } - //*********************************************************************** /// Get weekday //*********************************************************************** diff --git a/include/etl/private/chrono/year.h b/include/etl/private/chrono/year.h index fd3d8096..b21c572e 100644 --- a/include/etl/private/chrono/year.h +++ b/include/etl/private/chrono/year.h @@ -54,31 +54,13 @@ namespace etl } //*********************************************************************** - /// Construct from unsigned + /// Construct from int //*********************************************************************** - ETL_CONSTEXPR explicit year(unsigned value_) ETL_NOEXCEPT + ETL_CONSTEXPR explicit year(int value_) ETL_NOEXCEPT : value(value_) { } - //*********************************************************************** - /// Copy constructor - //*********************************************************************** - ETL_CONSTEXPR14 year(const etl::chrono::year& other) ETL_NOEXCEPT - : value(other.value) - { - } - - //*********************************************************************** - /// Assignment operator - //*********************************************************************** - ETL_CONSTEXPR14 etl::chrono::year& operator =(const etl::chrono::year& rhs) ETL_NOEXCEPT - { - value = rhs.value; - - return *this; - } - //*********************************************************************** /// Pre-increment operator //*********************************************************************** @@ -94,7 +76,7 @@ namespace etl //*********************************************************************** ETL_CONSTEXPR14 etl::chrono::year operator ++(int) ETL_NOEXCEPT { - const etl::chrono::year temp = *this; + etl::chrono::year temp = *this; ++value; return temp; @@ -115,7 +97,7 @@ namespace etl //*********************************************************************** ETL_CONSTEXPR14 etl::chrono::year operator --(int) ETL_NOEXCEPT { - const etl::chrono::year temp = *this; + etl::chrono::year temp = *this; --value; return temp; @@ -126,7 +108,7 @@ namespace etl //*********************************************************************** ETL_CONSTEXPR14 etl::chrono::year& operator +=(const etl::chrono::years& ys) ETL_NOEXCEPT { - value += static_cast(ys.count()); + value += ys.count(); return *this; } @@ -136,7 +118,7 @@ namespace etl //*********************************************************************** ETL_CONSTEXPR14 etl::chrono::year& operator -=(const etl::chrono::years& ys) ETL_NOEXCEPT { - value -= static_cast(ys.count()); + value -= ys.count(); return *this; } @@ -182,9 +164,9 @@ namespace etl //*********************************************************************** /// Conversion operator to unsigned int //*********************************************************************** - ETL_CONSTEXPR14 operator int() const ETL_NOEXCEPT + ETL_CONSTEXPR14 /*explicit*/ operator int() const ETL_NOEXCEPT { - return static_cast(value); + return value; } //*********************************************************************** @@ -212,7 +194,7 @@ namespace etl //*********************************************************************** inline ETL_CONSTEXPR14 bool operator ==(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT { - return (static_cast(y1) == static_cast(y2)); + return (static_cast(y1) == static_cast(y2)); } //*********************************************************************** @@ -228,7 +210,7 @@ namespace etl //*********************************************************************** inline ETL_CONSTEXPR14 bool operator <(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT { - return (static_cast(y1) < static_cast(y2)); + return (static_cast(y1) < static_cast(y2)); } //*********************************************************************** @@ -236,7 +218,7 @@ namespace etl //*********************************************************************** inline ETL_CONSTEXPR14 bool operator <=(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT { - return (static_cast(y1) <= static_cast(y2)); + return (static_cast(y1) <= static_cast(y2)); } //*********************************************************************** @@ -244,7 +226,7 @@ namespace etl //*********************************************************************** inline ETL_CONSTEXPR14 bool operator >(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT { - return (static_cast(y1) > static_cast(y2)); + return (static_cast(y1) > static_cast(y2)); } //*********************************************************************** @@ -252,7 +234,7 @@ namespace etl //*********************************************************************** inline ETL_CONSTEXPR14 bool operator >=(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT { - return (static_cast(y1) >= static_cast(y2)); + return (static_cast(y1) >= static_cast(y2)); } //*********************************************************************** @@ -261,7 +243,7 @@ namespace etl #if ETL_USING_CPP20 [[nodiscard]] inline constexpr auto operator <=>(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT { - return (static_cast(y1) <=> static_cast(y2)); + return (static_cast(y1) <=> static_cast(y2)); } #endif @@ -304,27 +286,13 @@ namespace etl return result; } - //*********************************************************************** - /// Subtract etl::chrono::year from etl::chrono::years - ///\return etl::chrono::years - //*********************************************************************** - inline ETL_CONSTEXPR14 etl::chrono::year operator -(const etl::chrono::years& ys, const etl::chrono::year& y) ETL_NOEXCEPT - { - etl::chrono::year result(y); - - result -= ys; - - return result; - } - //*********************************************************************** /// Subtract etl::chrono::year from etl::chrono::year ///\return etl::chrono::years //*********************************************************************** inline ETL_CONSTEXPR14 etl::chrono::years operator -(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT { - return etl::chrono::years(static_cast(static_cast(y1)) - - static_cast(static_cast(y2))); + return etl::chrono::years(static_cast(y1) - static_cast(y2)); } } @@ -337,7 +305,7 @@ namespace etl { size_t operator()(const etl::chrono::year& y) const { - etl::chrono::year::rep value = static_cast(static_cast(y)); + etl::chrono::year::rep value = static_cast(static_cast(y)); const uint8_t* p = reinterpret_cast(&value); return etl::private_hash::generic_hash(p, p + sizeof(value)); @@ -362,7 +330,7 @@ namespace etl inline ETL_CONSTEXPR14 etl::chrono::year operator ""_y(unsigned long long y) ETL_NOEXCEPT #endif { - return etl::chrono::year(static_cast(y)); + return etl::chrono::year(static_cast(y)); } } } diff --git a/include/etl/private/chrono/year_month.h b/include/etl/private/chrono/year_month.h index 672aadd6..36ca0526 100644 --- a/include/etl/private/chrono/year_month.h +++ b/include/etl/private/chrono/year_month.h @@ -135,7 +135,12 @@ namespace etl inline ETL_CONSTEXPR14 etl::chrono::year_month operator +(const etl::chrono::year_month& ym, const etl::chrono::months& dm) ETL_NOEXCEPT { - return etl::chrono::year_month(ym.year(), ym.month() + dm); + int dmonths = static_cast(static_cast(ym.month())) - 1 + dm.count(); + int dyears = (dmonths - 11 * (dmonths < 0)) / 12; + dmonths -= dyears * 12; + ++dmonths; + return etl::chrono::year_month((ym.year() + etl::chrono::years(dyears)), + etl::chrono::month(static_cast(dmonths))); } //************************************************************************* @@ -144,7 +149,7 @@ namespace etl inline ETL_CONSTEXPR14 etl::chrono::year_month operator +(const etl::chrono::months& dm, const etl::chrono::year_month& ym) ETL_NOEXCEPT { - return etl::chrono::year_month(ym.year(), ym.month() + dm); + return ym + dm; } //************************************************************************* @@ -162,7 +167,7 @@ namespace etl inline ETL_CONSTEXPR14 etl::chrono::year_month operator -(const etl::chrono::year_month& ym, const etl::chrono::months& dm) ETL_NOEXCEPT { - return etl::chrono::year_month(ym.year(), ym.month() - dm); + return ym + -dm; } //************************************************************************* @@ -171,7 +176,8 @@ namespace etl inline ETL_CONSTEXPR14 etl::chrono::months operator -(const etl::chrono::year_month& ym1, const etl::chrono::year_month& ym2) ETL_NOEXCEPT { - return etl::chrono::months(static_cast(((int(ym1.year()) - int(ym2.year())) * 12) + (unsigned(ym1.month()) - unsigned(ym2.month())))); + return etl::chrono::months((ym1.year() - ym2.year()) + etl::chrono::months( + static_cast(static_cast(ym1.month())) - static_cast(static_cast(ym2.month())))); } //************************************************************************* @@ -273,7 +279,7 @@ namespace etl { size_t operator()(const etl::chrono::year_month& ym) const { - etl::chrono::year::rep y = static_cast(static_cast(ym.year())); + etl::chrono::year::rep y = static_cast(static_cast(ym.year())); etl::chrono::month::rep m = static_cast(static_cast(ym.month())); uint8_t buffer[sizeof(y) + sizeof(m)]; diff --git a/include/etl/private/chrono/year_month_day.h b/include/etl/private/chrono/year_month_day.h index 6dcfa9d3..0a911a54 100644 --- a/include/etl/private/chrono/year_month_day.h +++ b/include/etl/private/chrono/year_month_day.h @@ -76,6 +76,9 @@ namespace etl /// Construct from sys_days. //************************************************************************* ETL_CONSTEXPR14 year_month_day(const etl::chrono::sys_days& sd) ETL_NOEXCEPT + : y(0) + , m(0U) + , d(0U) { // Days since 1970-01-01 int days_since_epoch = static_cast(sd.time_since_epoch().count()); @@ -101,7 +104,7 @@ namespace etl // Find the month while (true) { - unsigned char days_in_month = etl::chrono::private_chrono::days_in_month[current_month]; + unsigned char days_in_month = etl::chrono::private_chrono::days_in_month[static_cast(current_month)]; if (current_month == etl::chrono::February && current_year.is_leap()) { ++days_in_month; @@ -126,6 +129,9 @@ namespace etl /// Construct from local_days. //************************************************************************* ETL_CONSTEXPR14 year_month_day(const etl::chrono::local_days& ld) ETL_NOEXCEPT + : y(0) + , m(0) + , d(0) { etl::chrono::year_month_day ymd = sys_days(ld.time_since_epoch()); @@ -254,7 +260,7 @@ namespace etl // Add days for months in the current year for (etl::chrono::month mth(1); mth < this->month(); ++mth) { - day_count += private_chrono::days_in_month[mth]; + day_count += private_chrono::days_in_month[static_cast(mth)]; if (mth == etl::chrono::February && this->year().is_leap()) { @@ -289,7 +295,7 @@ namespace etl if (y.ok() && m.ok()) { - count = private_chrono::days_in_month[m]; + count = private_chrono::days_in_month[static_cast(m)]; if (y.is_leap() && (m == February)) { @@ -507,9 +513,9 @@ namespace etl ETL_NODISCARD ETL_CONSTEXPR14 etl::chrono::day day() const ETL_NOEXCEPT { - etl::chrono::day d = etl::chrono::day(etl::chrono::private_chrono::days_in_month[m]); + etl::chrono::day d = etl::chrono::day(etl::chrono::private_chrono::days_in_month[static_cast(m)]); - return (d == 28) && y.is_leap() ? etl::chrono::day(29) : d; + return (d == etl::chrono::day(28)) && y.is_leap() ? etl::chrono::day(29) : d; } //************************************************************************* @@ -788,7 +794,7 @@ namespace etl { size_t operator()(const etl::chrono::year_month_day& ymd) const { - etl::chrono::year::rep y = static_cast(static_cast(ymd.year())); + etl::chrono::year::rep y = static_cast(static_cast(ymd.year())); etl::chrono::month::rep m = static_cast(static_cast(ymd.month())); etl::chrono::day::rep d = static_cast(static_cast(ymd.day())); @@ -812,7 +818,7 @@ namespace etl { size_t operator()(const etl::chrono::year_month_day_last& ymdl) const { - etl::chrono::year::rep y = static_cast(static_cast(ymdl.year())); + etl::chrono::year::rep y = static_cast(static_cast(ymdl.year())); etl::chrono::month::rep m = static_cast(static_cast(ymdl.month())); etl::chrono::day::rep d = static_cast(static_cast(ymdl.day())); diff --git a/include/etl/private/chrono/year_month_weekday.h b/include/etl/private/chrono/year_month_weekday.h index ef8d9b31..909ff007 100644 --- a/include/etl/private/chrono/year_month_weekday.h +++ b/include/etl/private/chrono/year_month_weekday.h @@ -69,6 +69,9 @@ namespace etl /// Construct from sys_days. //************************************************************************* ETL_CONSTEXPR14 year_month_weekday(const etl::chrono::sys_days& sd) ETL_NOEXCEPT + : y(0) + , m(0U) + , wdi(etl::chrono::weekday(0), 0U) { // Extract year, month, and day year_month_day ymd = year_month_day{sd}; @@ -84,7 +87,7 @@ namespace etl // We walk backward from the given day in steps of 7 days unsigned index = 1; - for (int offset = static_cast(dy) - 7; offset > 0; offset -= 7) + for (int offset = static_cast(static_cast(dy)) - 7; offset > 0; offset -= 7) { ++index; } @@ -98,6 +101,9 @@ namespace etl /// Construct from local_days. //************************************************************************* ETL_CONSTEXPR14 year_month_weekday(const etl::chrono::local_days& ld) ETL_NOEXCEPT + : y(0) + , m(0U) + , wdi(etl::chrono::weekday(0), 0U) { year_month_weekday ymwd(sys_days(ld.time_since_epoch())); @@ -506,7 +512,7 @@ namespace etl { size_t operator()(const etl::chrono::year_month_weekday& ymwd) const { - etl::chrono::year::rep y = static_cast(static_cast(ymwd.year())); + etl::chrono::year::rep y = static_cast(static_cast(ymwd.year())); etl::chrono::month::rep m = static_cast(static_cast(ymwd.month())); unsigned int wd = ymwd.weekday().c_encoding(); @@ -530,7 +536,7 @@ namespace etl { size_t operator()(const etl::chrono::year_month_weekday_last& ymwdl) const { - etl::chrono::year::rep y = static_cast(static_cast(ymwdl.year())); + etl::chrono::year::rep y = static_cast(static_cast(ymwdl.year())); etl::chrono::month::rep m = static_cast(static_cast(ymwdl.month())); unsigned int wd = ymwdl.weekday().c_encoding(); diff --git a/test/test_chrono_day.cpp b/test/test_chrono_day.cpp index af9dec6c..28d90d2e 100644 --- a/test/test_chrono_day.cpp +++ b/test/test_chrono_day.cpp @@ -240,15 +240,6 @@ namespace } } -#if ETL_USING_ETL_CHRONO - //************************************************************************* - TEST(test_min_max_day) - { - CHECK_EQUAL(1U, Chrono::day::min()); - CHECK_EQUAL(31U, Chrono::day::max()); - } -#endif - #if ETL_USING_ETL_CHRONO //************************************************************************* TEST(test_literal_day) diff --git a/test/test_chrono_month.cpp b/test/test_chrono_month.cpp index 765d018f..d2363528 100644 --- a/test/test_chrono_month.cpp +++ b/test/test_chrono_month.cpp @@ -269,15 +269,6 @@ namespace } } -#if ETL_USING_ETL_CHRONO - //************************************************************************* - TEST(test_min_max_month) - { - CHECK_EQUAL(1U, Chrono::month::min()); - CHECK_EQUAL(12U, Chrono::month::max()); - } -#endif - #if ETL_USING_ETL_CHRONO //************************************************************************* TEST(test_month_compare) diff --git a/test/test_chrono_weekday_last.cpp b/test/test_chrono_weekday_last.cpp index 9b949160..14fefb92 100644 --- a/test/test_chrono_weekday_last.cpp +++ b/test/test_chrono_weekday_last.cpp @@ -59,7 +59,6 @@ namespace //************************************************************************* TEST(test_constructor_in_range) { - for (unsigned i = 1U; i < 5U; ++i) { Chrono::weekday_last weekday_last_monday(Chrono::Monday); Chrono::weekday_last weekday_last_tuesday(Chrono::Tuesday); diff --git a/test/test_chrono_year.cpp b/test/test_chrono_year.cpp index e7ec7904..4bb91b85 100644 --- a/test/test_chrono_year.cpp +++ b/test/test_chrono_year.cpp @@ -71,7 +71,7 @@ namespace etl::chrono::year year(i); CHECK_TRUE(year.ok()); - CHECK_EQUAL(i, int(year)); + CHECK_EQUAL(i, static_cast(year)); } } @@ -87,7 +87,7 @@ namespace etl::chrono::year this_year = ++year; CHECK_TRUE(year.ok()); - CHECK_EQUAL(count, year); + CHECK_EQUAL(count, static_cast(year)); CHECK_EQUAL(this_year, year); } } @@ -226,16 +226,11 @@ namespace //************************************************************************* TEST(test_year_minus_year) { - etl::chrono::year year(256); - etl::chrono::years years(2); - - for (int i = 0; i < 128; ++i) - { - year = years - year; - - CHECK_TRUE(year.ok()); - CHECK_EQUAL((256 - (2 * i)) - 2, int(year)); - } + etl::chrono::year y1(2056); + CHECK_TRUE(y1 - y1 == etl::chrono::years(0)); + etl::chrono::year y2(2); + CHECK_TRUE(y1 - y2 == etl::chrono::years(2054)); + CHECK_TRUE(y2 - y1 == etl::chrono::years(-2054)); } //************************************************************************* @@ -256,8 +251,8 @@ namespace //************************************************************************* TEST(test_min_max_year) { - CHECK_EQUAL(-32767, etl::chrono::year::min()); - CHECK_EQUAL(32767, etl::chrono::year::max()); + CHECK_EQUAL(-32767, static_cast(etl::chrono::year::min())); + CHECK_EQUAL(32767, static_cast(etl::chrono::year::max())); } #endif diff --git a/test/test_chrono_year_month.cpp b/test/test_chrono_year_month.cpp index e016e8c4..556b82ba 100644 --- a/test/test_chrono_year_month.cpp +++ b/test/test_chrono_year_month.cpp @@ -128,7 +128,7 @@ namespace Chrono::year_month ym2{Chrono::year(2001), Chrono::January}; Chrono::year_month ym3{Chrono::year(2000), Chrono::February}; - CHECK_TRUE(ym1 == ym1); // Same year/month/day + CHECK_TRUE(ym1 == ym1); // Same year/month CHECK_FALSE(ym1 == ym2); // Different year CHECK_FALSE(ym1 == ym3); // Different month } @@ -140,9 +140,80 @@ namespace Chrono::year_month ym2{Chrono::year(2001), Chrono::January}; Chrono::year_month ym3{Chrono::year(2000), Chrono::February}; - CHECK_FALSE(ym1 != ym1); // Same year/month/day + CHECK_FALSE(ym1 != ym1); // Same year/month CHECK_TRUE(ym1 != ym2); // Different year CHECK_TRUE(ym1 != ym3); // Different month } + + //************************************************************************* + TEST(test_year_month_relational_operators) + { + Chrono::year_month ym1(Chrono::year(2021), Chrono::January); + CHECK_FALSE(ym1 < ym1); // Same year/month + CHECK_TRUE(ym1 <= ym1); + CHECK_FALSE(ym1 > ym1); + CHECK_TRUE(ym1 >= ym1); + + Chrono::year_month ym2(Chrono::year(2026), Chrono::December); + CHECK_TRUE(ym1 < ym2); // left year/month strict less + CHECK_TRUE(ym1 <= ym2); + CHECK_FALSE(ym1 > ym2); + CHECK_FALSE(ym1 >= ym2); + + CHECK_FALSE(ym2 < ym1); // left year/month strict greater + CHECK_FALSE(ym2 <= ym1); + CHECK_TRUE(ym2 > ym1); + CHECK_TRUE(ym2 >= ym1); + } + + //************************************************************************* + TEST(test_year_month_year_month_diff_operator) + { + Chrono::year_month ym1(Chrono::year(2021), Chrono::January); + Chrono::months dms = ym1 - ym1; + CHECK_EQUAL(dms.count(), 0); + Chrono::year_month ym2(Chrono::year(2026), Chrono::December); + dms = ym2 - ym1; // positive + CHECK_EQUAL(dms.count(), (2026 - 2021) * 12 + 11); + dms = ym1 - ym2; // negative + CHECK_EQUAL(dms.count(), (2021 - 2026) * 12 - 11); + } + + //************************************************************************* + TEST(test_year_month_add_sub_months_operators) + { + Chrono::year_month ym1(Chrono::year(2021), Chrono::January); + Chrono::months dms(0); // zero + CHECK_TRUE(dms + ym1 == ym1); + CHECK_TRUE(ym1 + dms == ym1); + CHECK_TRUE(ym1 - dms == ym1); + Chrono::year_month ym2(Chrono::year(2026), Chrono::December); + dms = ym1 - ym2; // negative + CHECK_TRUE(dms + ym2 == ym1); + CHECK_TRUE(ym2 + dms == ym1); + CHECK_TRUE(ym1 - dms == ym2); + dms = ym2 - ym1; // positive + CHECK_TRUE(dms + ym1 == ym2); + CHECK_TRUE(ym1 + dms == ym2); + CHECK_TRUE(ym2 - dms == ym1); + } + + //************************************************************************* + TEST(test_year_month_add_sub_years_operator) + { + Chrono::year_month ym(Chrono::year(2021), Chrono::January); + Chrono::years dys(0); // zero + CHECK_TRUE((ym + dys == Chrono::year_month(ym.year() + dys, ym.month()))); + CHECK_TRUE((dys + ym == Chrono::year_month(ym.year() + dys, ym.month()))); + CHECK_TRUE((ym - dys == Chrono::year_month(ym.year() - dys, ym.month()))); + dys = Chrono::years(-200); // negative + CHECK_TRUE((ym + dys == Chrono::year_month(ym.year() + dys, ym.month()))); + CHECK_TRUE((dys + ym == Chrono::year_month(ym.year() + dys, ym.month()))); + CHECK_TRUE((ym - dys == Chrono::year_month(ym.year() - dys, ym.month()))); + dys = Chrono::years(300); // positive + CHECK_TRUE((ym + dys == Chrono::year_month(ym.year() + dys, ym.month()))); + CHECK_TRUE((dys + ym == Chrono::year_month(ym.year() + dys, ym.month()))); + CHECK_TRUE((ym - dys == Chrono::year_month(ym.year() - dys, ym.month()))); + } } } diff --git a/test/test_chrono_year_month_day.cpp b/test/test_chrono_year_month_day.cpp index a5710e73..ae698465 100644 --- a/test/test_chrono_year_month_day.cpp +++ b/test/test_chrono_year_month_day.cpp @@ -151,7 +151,7 @@ namespace Chrono::year_month_day ymd{Chrono::sys_days(etl::chrono::days(10997))}; Chrono::year_month_day expected{Chrono::year(2000), Chrono::February, Chrono::day(10)}; - CHECK_EQUAL((unsigned)expected.year(), (unsigned)ymd.year()); + CHECK_EQUAL((int)expected.year(), (int)ymd.year()); CHECK_EQUAL((unsigned)expected.month(), (unsigned)ymd.month()); CHECK_EQUAL((unsigned)expected.day(), (unsigned)ymd.day()); } From 2a727b12b4b8aa5ac550fe0a5b608cfe61646a1f Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Fri, 16 Jan 2026 09:51:11 +0100 Subject: [PATCH 128/298] Suppress warnings from std in optimized builds (#1259) When testing with ./run-tests.sh 23 3 10, some warnings from std surfaced which resulted in build errors. --- include/etl/algorithm.h | 2 ++ include/etl/memory.h | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/etl/algorithm.h b/include/etl/algorithm.h index a5879e2c..74fbb8ed 100644 --- a/include/etl/algorithm.h +++ b/include/etl/algorithm.h @@ -338,7 +338,9 @@ namespace etl template ETL_CONSTEXPR20 TIterator2 move_backward(TIterator1 sb, TIterator1 se, TIterator2 de) { +#include "etl/private/diagnostic_array_bounds_push.h" return std::move_backward(sb, se, de); +#include "etl/private/diagnostic_pop.h" } #elif ETL_USING_CPP11 // For C++11 diff --git a/include/etl/memory.h b/include/etl/memory.h index 57b89879..1c282452 100644 --- a/include/etl/memory.h +++ b/include/etl/memory.h @@ -382,9 +382,13 @@ namespace etl ///\ingroup memory //***************************************************************************** template - TOutputIterator uninitialized_move(TInputIterator i_begin, TInputIterator i_end, TOutputIterator o_begin) + TOutputIterator uninitialized_move(TInputIterator i_begin, TInputIterator i_end, TOutputIterator o_begin) { +#include "etl/private/diagnostic_array_bounds_push.h" +#include "etl/private/diagnostic_stringop_overflow_push.h" return std::uninitialized_move(i_begin, i_end, o_begin); +#include "etl/private/diagnostic_pop.h" +#include "etl/private/diagnostic_pop.h" } //***************************************************************************** @@ -398,7 +402,9 @@ namespace etl { count += int32_t(etl::distance(i_begin, i_end)); +#include "etl/private/diagnostic_array_bounds_push.h" return std::uninitialized_move(i_begin, i_end, o_begin); +#include "etl/private/diagnostic_pop.h" } #else //***************************************************************************** From 45e5668782b74f8bf99347a1a85c0c0cbd02aab3 Mon Sep 17 00:00:00 2001 From: Mike Bloom <91038685+mike919192@users.noreply.github.com> Date: Fri, 16 Jan 2026 03:57:09 -0500 Subject: [PATCH 129/298] Add template deduction guide for span from vector (#1264) * Create span from vector deduction * Use ivector for deduction. Add vector_ext to test * Add vector pointer to test * Finish tests * Initialize pdata_ext and others --- include/etl/span.h | 12 +++++ test/test_span_dynamic_extent.cpp | 87 +++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) diff --git a/include/etl/span.h b/include/etl/span.h index c6f18799..8f57148f 100644 --- a/include/etl/span.h +++ b/include/etl/span.h @@ -1258,6 +1258,18 @@ namespace etl span(const etl::array&) -> span; + // Forward declaration of etl::ivector + template + class ivector; + + template + span(etl::ivector&) + -> span; + + template + span(const etl::ivector&) + -> span; + #if ETL_USING_STL && ETL_USING_CPP11 template span(std::array&) diff --git a/test/test_span_dynamic_extent.cpp b/test/test_span_dynamic_extent.cpp index e9045504..7fc1c8c0 100644 --- a/test/test_span_dynamic_extent.cpp +++ b/test/test_span_dynamic_extent.cpp @@ -31,6 +31,7 @@ SOFTWARE. #include "etl/span.h" #include "etl/array.h" #include "etl/unaligned_type.h" +#include "etl/vector.h" #include #include @@ -778,6 +779,92 @@ namespace CHECK((std::is_same_v>)); } + //************************************************************************* + TEST(test_template_deduction_guide_for_etl_vector) + { + const size_t max_size = 10; + const size_t size = 4; + + int buffer1[max_size]; + int buffer2[max_size]; + int * buffer3[max_size]; + int * buffer4[max_size]; + const int * buffer5[max_size]; + const int * buffer6[max_size]; + + etl::vector data(size, 0); + const etl::vector data2(size, 0); + etl::vector_ext data_ext(size, 0, buffer1, max_size); + const etl::vector_ext data2_ext(size, 0, buffer2, max_size); + + etl::span span = data; + etl::span span2 = data2; + etl::span span_ext = data_ext; + etl::span span2_ext = data2_ext; + + CHECK_EQUAL(etl::dynamic_extent, span.extent); + CHECK_EQUAL(ETL_OR_STD17::size(data), span.size()); + CHECK_EQUAL(etl::dynamic_extent, span2.extent); + CHECK_EQUAL(ETL_OR_STD17::size(data2), span2.size()); + CHECK_EQUAL(etl::dynamic_extent, span_ext.extent); + CHECK_EQUAL(ETL_OR_STD17::size(data_ext), span_ext.size()); + CHECK_EQUAL(etl::dynamic_extent, span2_ext.extent); + CHECK_EQUAL(ETL_OR_STD17::size(data2_ext), span2_ext.size()); + + CHECK((std::is_same_v>)); + CHECK((std::is_same_v>)); + CHECK((std::is_same_v>)); + CHECK((std::is_same_v>)); + + etl::vector pdata(size, nullptr); + const etl::vector pdata2(size, nullptr); + etl::vector pdata3(size, nullptr); + const etl::vector pdata4(size, nullptr); + + etl::span pspan = pdata; + etl::span pspan2 = pdata2; + etl::span pspan3 = pdata3; + etl::span pspan4 = pdata4; + + CHECK_EQUAL(etl::dynamic_extent, pspan.extent); + CHECK_EQUAL(ETL_OR_STD17::size(pdata), pspan.size()); + CHECK_EQUAL(etl::dynamic_extent, pspan2.extent); + CHECK_EQUAL(ETL_OR_STD17::size(pdata2), pspan2.size()); + CHECK_EQUAL(etl::dynamic_extent, pspan3.extent); + CHECK_EQUAL(ETL_OR_STD17::size(pdata3), pspan3.size()); + CHECK_EQUAL(etl::dynamic_extent, pspan4.extent); + CHECK_EQUAL(ETL_OR_STD17::size(pdata4), pspan4.size()); + + CHECK((std::is_same_v>)); + CHECK((std::is_same_v>)); + CHECK((std::is_same_v>)); + CHECK((std::is_same_v>)); + + etl::vector_ext pdata_ext(size, nullptr, buffer3, max_size); + const etl::vector_ext pdata2_ext(size, nullptr, buffer4, max_size); + etl::vector_ext pdata3_ext(size, nullptr, buffer5, max_size); + const etl::vector_ext pdata4_ext(size, nullptr, buffer6, max_size); + + etl::span pspan_ext = pdata_ext; + etl::span pspan2_ext = pdata2_ext; + etl::span pspan3_ext = pdata3_ext; + etl::span pspan4_ext = pdata4_ext; + + CHECK_EQUAL(etl::dynamic_extent, pspan_ext.extent); + CHECK_EQUAL(ETL_OR_STD17::size(pdata_ext), pspan_ext.size()); + CHECK_EQUAL(etl::dynamic_extent, pspan2_ext.extent); + CHECK_EQUAL(ETL_OR_STD17::size(pdata2_ext), pspan2_ext.size()); + CHECK_EQUAL(etl::dynamic_extent, pspan3_ext.extent); + CHECK_EQUAL(ETL_OR_STD17::size(pdata3_ext), pspan3_ext.size()); + CHECK_EQUAL(etl::dynamic_extent, pspan4_ext.extent); + CHECK_EQUAL(ETL_OR_STD17::size(pdata4_ext), pspan4_ext.size()); + + CHECK((std::is_same_v>)); + CHECK((std::is_same_v>)); + CHECK((std::is_same_v>)); + CHECK((std::is_same_v>)); + } + //************************************************************************* TEST(test_template_deduction_guide_for_iterators) { From 24421edd2952fee957ce8d5bb31f06e0352b2870 Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Sat, 17 Jan 2026 14:26:16 +0100 Subject: [PATCH 130/298] Document how to implement platform specifics (#1262) Some interfaces need to be implemented in every project or platform using the ETL: * etl_get_high_resolution_clock * etl_get_system_clock * etl_get_steady_clock * etl_putchar Co-authored-by: John Wellbelove --- README.md | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/README.md b/README.md index a762e43f..c199268c 100644 --- a/README.md +++ b/README.md @@ -182,6 +182,84 @@ add_executable(foo main.cpp) target_link_libraries(foo PRIVATE etl::etl) ``` +## Profile definition + +When using ETL in a project, there is typically an `etl_profile.h` defined to +adjust ETL to the project needs. ETL will automatically find `etl_profile.h` +if it is available in the include path(s). If it's not available, ETL will +work with default values. + +### Example + +``` +#ifndef __ETL_PROFILE_H__ +#define __ETL_PROFILE_H__ + +#define ETL_TARGET_DEVICE_GENERIC +#define ETL_TARGET_OS_NONE + +#define ETL_NO_STL + +#endif +``` + +## Platform specific implementation + +Although ETL is generally a self-contained header-only library, some interfaces need to be +implemented in every project or platform, at least if those interfaces are actually being +used, due to project specifics: + +| ETL header | Platform specific API to be implemented | Needed when using | +|------------|-----------------------------------------|-------------------------------------| +| `chrono.h` | `etl_get_high_resolution_clock()` | `etl::high_resolution_clock::now()` | +| | `etl_get_system_clock()` | `etl::system_clock::now()` | +| | `etl_get_steady_clock()` | `etl::steady_clock::now()` | +| `print.h` | `etl_putchar()` | `etl::print()` | +| | | `etl::println()` | + +### Example + +``` +#include +#include + +extern "C" +{ + +etl::chrono::high_resolution_clock::rep etl_get_high_resolution_clock() +{ + etl::chrono::high_resolution_clock::rep(static_cast(getSystemTimeNs())); +} + +etl::chrono::system_clock::rep etl_get_system_clock() +{ + return etl::chrono::system_clock::rep(static_cast(getSystemTimeNs())); +} + +etl::chrono::system_clock::rep etl_get_steady_clock() +{ + return etl::chrono::system_clock::rep(static_cast(getSystemTimeNs())); +} + +void etl_putchar(int c) +{ + putByteToStdout(static_cast(c)); +} + +} +``` + +The following default values apply if the respective macros are not defined +(e.g. in `etl_profile.h`): + +| Macro | Default | +|-----------------------------------------------|----------------------------| +| `ETL_CHRONO_SYSTEM_CLOCK_DURATION` | `etl::chrono::nanoseconds` | +| `ETL_CHRONO_SYSTEM_CLOCK_IS_STEADY` | `true` | +| `ETL_CHRONO_HIGH_RESOLUTION_CLOCK_DURATION` | `etl::chrono::nanoseconds` | +| `ETL_CHRONO_HIGH_RESOLUTION_CLOCK_IS_STEADY` | `true` | +| `ETL_CHRONO_STEADY_CLOCK_DURATION` | `etl::chrono::nanoseconds` | + ## Arduino library The content of this repo is available as a library in the Arduino IDE (search for the "Embedded Template Library" in the IDE library manager). The Arduino library repository is available at ```https://github.com/ETLCPP/etl-arduino```, see there for more details. From d419bbf16f7ad933eabbf0c6ffbaa4cbcaafe377 Mon Sep 17 00:00:00 2001 From: taltenbach <92919739+taltenbach@users.noreply.github.com> Date: Sat, 17 Jan 2026 23:04:52 +0100 Subject: [PATCH 131/298] Fix etl::as_bytes for etl::span (#1266) A missing 'const' in the etl::as_bytes implementation was causing a compile-time error when etl::as_bytes was called on a span of const values. Co-authored-by: John Wellbelove --- include/etl/span.h | 2 +- test/test_span_dynamic_extent.cpp | 3 ++- test/test_span_fixed_extent.cpp | 5 +++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/include/etl/span.h b/include/etl/span.h index 8f57148f..5d03632a 100644 --- a/include/etl/span.h +++ b/include/etl/span.h @@ -1303,7 +1303,7 @@ namespace etl span as_bytes(span s) ETL_NOEXCEPT { - return span(reinterpret_cast(s.data()), s.size_bytes()); + return span(reinterpret_cast(s.data()), s.size_bytes()); } //************************************************************************* diff --git a/test/test_span_dynamic_extent.cpp b/test/test_span_dynamic_extent.cpp index 7fc1c8c0..586eadcb 100644 --- a/test/test_span_dynamic_extent.cpp +++ b/test/test_span_dynamic_extent.cpp @@ -1325,8 +1325,9 @@ namespace TEST(test_convert_span_any_to_span_byte) { float data[2]{3.141592f, 2.71828f }; + const float const_data[2]{3.141592f, 2.71828f }; - auto const const_bytes = etl::as_bytes(etl::span{data}); + auto const const_bytes = etl::as_bytes(etl::span{const_data}); auto const writable_bytes = etl::as_writable_bytes(etl::span{data}); CHECK_EQUAL(const_bytes.size(), sizeof(data)); diff --git a/test/test_span_fixed_extent.cpp b/test/test_span_fixed_extent.cpp index 137bd9b8..a1825c2c 100644 --- a/test/test_span_fixed_extent.cpp +++ b/test/test_span_fixed_extent.cpp @@ -1163,12 +1163,13 @@ namespace TEST(test_convert_span_any_to_span_byte) { float data[2]{3.141592f, 2.71828f}; + const float const_data[2]{3.141592f, 2.71828f}; #if ETL_USING_CPP17 - auto const const_bytes = etl::as_bytes(etl::span{ data }); + auto const const_bytes = etl::as_bytes(etl::span{ const_data }); auto const writable_bytes = etl::as_writable_bytes(etl::span{ data }); #else - auto const const_bytes = etl::as_bytes(etl::span(data)); + auto const const_bytes = etl::as_bytes(etl::span(const_data)); auto const writable_bytes = etl::as_writable_bytes(etl::span(data)); #endif From a8436506494b7c1f0478cbb12174582e2c47ccb8 Mon Sep 17 00:00:00 2001 From: Bo Rydberg <2945606+bolry@users.noreply.github.com> Date: Tue, 20 Jan 2026 11:15:38 +0100 Subject: [PATCH 132/298] Remove some UB in test_vector_non_trivial.cpp (#1268) Some of the tests' UB are detectable by Gcc15 and thus give a compile error due to warnings-as-error flag. Co-authored-by: John Wellbelove --- test/test_vector_non_trivial.cpp | 41 ++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/test/test_vector_non_trivial.cpp b/test/test_vector_non_trivial.cpp index 1a10ac77..99772202 100644 --- a/test/test_vector_non_trivial.cpp +++ b/test/test_vector_non_trivial.cpp @@ -964,8 +964,9 @@ namespace DataNDC data; data.assign(initial_data.begin(), initial_data.begin() + INITIAL_SIZE); - DataNDC data2; - CHECK_THROW(data.insert(data2.cbegin(), INITIAL_VALUE), etl::vector_out_of_bounds); + DataNDC::iterator it = data.begin(); + --it; + CHECK_THROW(data.insert(it, INITIAL_VALUE), etl::vector_out_of_bounds); } //************************************************************************* @@ -1002,19 +1003,34 @@ namespace const std::string INITIAL_VALUE("1"); DataNDC data; - DataNDC data2; data.assign(initial_data.begin(), initial_data.begin() + INITIAL_SIZE); - CHECK_THROW(data.emplace(data2.cbegin(), INITIAL_VALUE), etl::vector_out_of_bounds); + DataNDC::const_iterator it = data.cend(); + ++it; + CHECK_THROW(data.emplace(it, INITIAL_VALUE), etl::vector_out_of_bounds); } //************************************************************************* - TEST(test_emplace_out_of_range) + TEST(test_emplace_out_of_range_past_end) { DataNDC data; - DataNDC data2; + DataNDC::iterator it = data.end(); + ++it; + const std::string INITIAL_VALUE("1"); - CHECK_THROW(data.emplace(data2.end(), INITIAL_VALUE);, etl::vector_out_of_bounds); + CHECK_THROW(data.emplace(it, INITIAL_VALUE), etl::vector_out_of_bounds); + } + + //************************************************************************* + TEST(test_emplace_out_of_range_before_begin) + { + DataNDC data; + DataNDC::iterator it = data.begin(); + --it; + + const std::string INITIAL_VALUE("1"); + + CHECK_THROW(data.emplace(it, INITIAL_VALUE), etl::vector_out_of_bounds); } //************************************************************************* @@ -1072,10 +1088,11 @@ namespace TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) { DataNDC data; - DataNDC data2; + DataNDC::const_iterator it = data.cend(); + ++it; const NDC INITIAL_VALUE("1"); - CHECK_THROW(data.insert(data2.end(), 1, INITIAL_VALUE);, etl::vector_out_of_bounds); + CHECK_THROW(data.insert(it, 1, INITIAL_VALUE), etl::vector_out_of_bounds); } //************************************************************************* @@ -1163,7 +1180,7 @@ namespace DataNDC data; DataNDC data2; - CHECK_THROW(data.insert(data2.end(), insert_data.cbegin(), insert_data.cend());, etl::vector_out_of_bounds); + CHECK_THROW(data.insert(data2.end(), insert_data.cbegin(), insert_data.cend()), etl::vector_out_of_bounds); } //************************************************************************* @@ -1190,7 +1207,7 @@ namespace { DataNDC data(initial_data.begin(), initial_data.end()); - CHECK_THROW(data.erase(data.end());, etl::vector_out_of_bounds); + CHECK_THROW(data.erase(data.end()), etl::vector_out_of_bounds); } //************************************************************************* @@ -1218,7 +1235,7 @@ namespace DataNDC data(initial_data.begin(), initial_data.end()); DataNDC data2(initial_data.begin(), initial_data.end()); - CHECK_THROW(data.erase(data2.begin(), data2.end());, etl::vector_out_of_bounds); + CHECK_THROW(data.erase(data2.begin(), data2.end()), etl::vector_out_of_bounds); } //************************************************************************* From dbaffa9169d3a41fcd3d420af55e3a87d86fc3af Mon Sep 17 00:00:00 2001 From: Bo Rydberg <2945606+bolry@users.noreply.github.com> Date: Tue, 20 Jan 2026 11:36:14 +0100 Subject: [PATCH 133/298] Update C++26 deprecated constructs to ensure future standard compliance (#1267) * Update C++26 deprecated constructs to ensure future standard compliance I replaced std::is_trivial with a combination of std::is_trivially_default_constructible and std::is_trivially_copyable. Additionally, I added the required comma before the ellipsis in variadic functions to match updated language specifications. * Some additional is_trivial related changes not found directly when compiling tests in C++26 --------- Co-authored-by: John Wellbelove --- include/etl/generators/type_traits_generator.h | 4 ++-- include/etl/type_traits.h | 4 ++-- test/test_successor.cpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/etl/generators/type_traits_generator.h b/include/etl/generators/type_traits_generator.h index 68c937f8..1588544f 100644 --- a/include/etl/generators/type_traits_generator.h +++ b/include/etl/generators/type_traits_generator.h @@ -1227,11 +1227,11 @@ typedef integral_constant true_type; /// is_pod ///\ingroup type_traits template - struct is_pod : std::integral_constant::value && std::is_trivial::value> {}; + struct is_pod : std::integral_constant::value && std::is_trivially_default_constructible::value && std::is_trivially_copyable::value> {}; #if ETL_USING_CPP17 template - inline constexpr bool is_pod_v = std::is_standard_layout_v && std::is_trivial_v; + inline constexpr bool is_pod_v = std::is_standard_layout_v && std::is_trivially_default_constructible_v && std::is_trivially_copyable_v; #endif #if defined(ETL_COMPILER_GCC) diff --git a/include/etl/type_traits.h b/include/etl/type_traits.h index 26cd6aef..524b74eb 100644 --- a/include/etl/type_traits.h +++ b/include/etl/type_traits.h @@ -1215,11 +1215,11 @@ typedef integral_constant true_type; /// is_pod ///\ingroup type_traits template - struct is_pod : std::integral_constant::value && std::is_trivial::value> {}; + struct is_pod : std::integral_constant::value && std::is_trivially_default_constructible::value && std::is_trivially_copyable::value> {}; #if ETL_USING_CPP17 template - inline constexpr bool is_pod_v = std::is_standard_layout_v && std::is_trivial_v; + inline constexpr bool is_pod_v = std::is_standard_layout_v && std::is_trivially_default_constructible_v && std::is_trivially_copyable_v; #endif #if defined(ETL_COMPILER_GCC) diff --git a/test/test_successor.cpp b/test/test_successor.cpp index 2e42c0d1..ebbd1300 100644 --- a/test/test_successor.cpp +++ b/test/test_successor.cpp @@ -39,7 +39,7 @@ namespace { } - SuccessorBase(SuccessorBase& successors...) + SuccessorBase(SuccessorBase& successors, ...) : successor(successors) { } @@ -55,7 +55,7 @@ namespace { } - SuccessorSameBase1(SuccessorBase& successors...) + SuccessorSameBase1(SuccessorBase& successors, ...) : SuccessorBase(successors) , value(0) { From 8b0fd64289dc8bca0b2b009724dace726af08dad Mon Sep 17 00:00:00 2001 From: Mike Bloom <91038685+mike919192@users.noreply.github.com> Date: Wed, 21 Jan 2026 13:40:19 -0500 Subject: [PATCH 134/298] Fix return value of get_token_list (#1271) Co-authored-by: John Wellbelove --- include/etl/string_utilities.h | 6 ++--- test/test_string_utilities.cpp | 42 ++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/include/etl/string_utilities.h b/include/etl/string_utilities.h index d20225c9..64e0365e 100644 --- a/include/etl/string_utilities.h +++ b/include/etl/string_utilities.h @@ -782,9 +782,9 @@ namespace etl etl::optional token; size_t count = 0; - while ((count != output.max_size()) && - (count != max_n_tokens) && - (token = etl::get_token(input, delimiters, token, ignore_empty_tokens))) + while ((token = etl::get_token(input, delimiters, token, ignore_empty_tokens)) && + (count != output.max_size()) && + (count != max_n_tokens)) { output.push_back(token.value()); ++count; diff --git a/test/test_string_utilities.cpp b/test/test_string_utilities.cpp index 0f450da3..a5df21ec 100644 --- a/test/test_string_utilities.cpp +++ b/test/test_string_utilities.cpp @@ -1115,6 +1115,48 @@ namespace CHECK_EQUAL(std::string("mat"), std::string(views[5].begin(), views[5].end())); } + //************************************************************************* + //before the issue fix, + //the return value was false when output vector max size equaled the number of tokens + //it should be true + TEST(test_issue_1270_output_vector_max_size_equals_num_tokens) + { + String text(STR(",,,The,cat,sat,,on,the,mat")); + etl::vector views; + + bool all_views_found = etl::get_token_list(text, views, STR(","), true); + + CHECK_TRUE(all_views_found); + CHECK_EQUAL(6, views.size()); + CHECK_EQUAL(std::string("The"), std::string(views[0].begin(), views[0].end())); + CHECK_EQUAL(std::string("cat"), std::string(views[1].begin(), views[1].end())); + CHECK_EQUAL(std::string("sat"), std::string(views[2].begin(), views[2].end())); + CHECK_EQUAL(std::string("on"), std::string(views[3].begin(), views[3].end())); + CHECK_EQUAL(std::string("the"), std::string(views[4].begin(), views[4].end())); + CHECK_EQUAL(std::string("mat"), std::string(views[5].begin(), views[5].end())); + } + + //************************************************************************* + //before the issue fix, + //the return value was false when max number of tokens equaled the number of tokens + //it should be true + TEST(test_issue_1270_max_tokens_equals_num_tokens) + { + String text(STR(",,,The,cat,sat,,on,the,mat")); + VectorOfViews7 views; + + bool all_views_found = etl::get_token_list(text, views, STR(","), true, 6); + + CHECK_TRUE(all_views_found); + CHECK_EQUAL(6, views.size()); + CHECK_EQUAL(std::string("The"), std::string(views[0].begin(), views[0].end())); + CHECK_EQUAL(std::string("cat"), std::string(views[1].begin(), views[1].end())); + CHECK_EQUAL(std::string("sat"), std::string(views[2].begin(), views[2].end())); + CHECK_EQUAL(std::string("on"), std::string(views[3].begin(), views[3].end())); + CHECK_EQUAL(std::string("the"), std::string(views[4].begin(), views[4].end())); + CHECK_EQUAL(std::string("mat"), std::string(views[5].begin(), views[5].end())); + } + //************************************************************************* TEST(test_get_token_list_to_vector_of_string_view_all_but_1_tokens_captured_ignore_empty_tokens) { From 012bbea249419ff5f5e49c51e9a59cc2c6a7ac72 Mon Sep 17 00:00:00 2001 From: Bryton Flecker Date: Wed, 21 Jan 2026 22:30:20 -0600 Subject: [PATCH 135/298] Fix etl::tuple template signature error in pair assignment operator (#1265) * Fix etl::tuple template signature error in pair assignment operator * Remove AppVeyor build status badge Removed AppVeyor build status badge from README. * Update README.md * Update etl::tuple to explicitly use etl::pair or std::pair in assignment operator * Added tests for etl::tuple assignment from pair --------- Co-authored-by: Bryton Flecker Co-authored-by: John Wellbelove --- include/etl/tuple.h | 20 +++++++-------- test/test_tuple.cpp | 62 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 10 deletions(-) diff --git a/include/etl/tuple.h b/include/etl/tuple.h index dbdbdaa2..dde08d13 100644 --- a/include/etl/tuple.h +++ b/include/etl/tuple.h @@ -562,9 +562,9 @@ namespace etl //********************************* /// Assign from lvalue pair tuple type. //********************************* - template , etl::enable_if_t = 0> + template (), etl::enable_if_t = 0> ETL_CONSTEXPR14 - tuple& operator =(pair& p) + tuple& operator =(ETL_OR_STD::pair& p) { get_value() = p.first; get_base().get_value() = p.second; @@ -575,9 +575,9 @@ namespace etl //********************************* /// Assign from const lvalue pair tuple type. //********************************* - template , etl::enable_if_t = 0> + template (), etl::enable_if_t = 0> ETL_CONSTEXPR14 - tuple& operator =(const pair& p) + tuple& operator =(const ETL_OR_STD::pair& p) { get_value() = p.first; get_base().get_value() = p.second; @@ -588,9 +588,9 @@ namespace etl //********************************* /// Assign from rvalue pair tuple type. //********************************* - template , etl::enable_if_t = 0> + template (), etl::enable_if_t = 0> ETL_CONSTEXPR14 - tuple& operator =(pair&& p) + tuple& operator =(ETL_OR_STD::pair&& p) { get_value() = etl::forward(p.first); get_base().get_value() = etl::forward(p.second); @@ -601,12 +601,12 @@ namespace etl //********************************* /// Assign from const rvalue pair tuple type. //********************************* - template , etl::enable_if_t = 0> + template (), etl::enable_if_t = 0> ETL_CONSTEXPR14 - tuple& operator =(const pair&& p) + tuple& operator =(const ETL_OR_STD::pair&& p) { - get_value() = etl::forward(p.first); - get_base().get_value() = etl::forward(p.second); + get_value() = p.first; + get_base().get_value() = p.second; return *this; } diff --git a/test/test_tuple.cpp b/test/test_tuple.cpp index d84940d9..918541e0 100644 --- a/test/test_tuple.cpp +++ b/test/test_tuple.cpp @@ -777,5 +777,67 @@ namespace CHECK_EQUAL(etl::get<2>(tp), s); } #endif + + //************************************************************************* + TEST(test_assign_from_lvalue_pair) + { + ETL_OR_STD::pair p(1, Data("2")); + + etl::tuple tp(0, Data("")); + + tp = p; + + int i = etl::get<0>(tp); + Data d = etl::get<1>(tp); + + CHECK_EQUAL(1, i); + CHECK_EQUAL(std::string("2"), d.value); + } + + //************************************************************************* + TEST(test_assign_from_const_lvalue_pair) + { + const ETL_OR_STD::pair p(1, Data("2")); + + etl::tuple tp(0, Data("")); + + tp = p; + + int i = etl::get<0>(tp); + Data d = etl::get<1>(tp); + + CHECK_EQUAL(1, i); + CHECK_EQUAL(std::string("2"), d.value); + } + + //************************************************************************* + TEST(test_assign_from_rvalue_pair) + { + etl::tuple tp(0, Data("")); + + tp = ETL_OR_STD::pair(1, Data("2")); + + int i = etl::get<0>(tp); + Data d = etl::get<1>(tp); + + CHECK_EQUAL(1, i); + CHECK_EQUAL(std::string("2"), d.value); + } + + //************************************************************************* + TEST(test_assign_from_const_rvalue_pair) + { + const ETL_OR_STD::pair p(1, Data("2")); + + etl::tuple tp(0, Data("")); + + tp = static_cast&&>(p); + + int i = etl::get<0>(tp); + Data d = etl::get<1>(tp); + + CHECK_EQUAL(1, i); + CHECK_EQUAL(std::string("2"), d.value); + } } } From 17e6167317e11aa21af69ee5af2ef64b65405f04 Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Fri, 23 Jan 2026 19:33:08 +0100 Subject: [PATCH 136/298] Remove advance() on static spans (#1281) * Remove AppVeyor build status badge Removed AppVeyor build status badge from README. * Update README.md * Update CONTRIBUTING.md Updated the instructions for contributing. * Fix for issue 1276 "Data corruption in the etl::bip_buffer_spsc_atomic" (#1277) * Reproduce data corruption bug in the `etl::bip_buffer_spsc_atomic`. * Fix data corruption bug in the `etl::bip_buffer_spsc_atomic`. * Remove advance() on static spans Since the size of a static span is constant, we can't reasonably advance() on it. --------- Co-authored-by: John Wellbelove Co-authored-by: Sergei --- include/etl/span.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/include/etl/span.h b/include/etl/span.h index 5d03632a..c60a9125 100644 --- a/include/etl/span.h +++ b/include/etl/span.h @@ -605,16 +605,6 @@ namespace etl #endif } - //************************************************************************* - /// Moves the pointer to the first element of the span further by a specified number of elements. - ///\tparam elements Number of elements to move forward - //************************************************************************* - void advance(size_t elements) ETL_NOEXCEPT - { - elements = etl::min(elements, size()); - pbegin += elements; - } - //************************************************************************* /// Reinterpret the span as a span with different element type. //************************************************************************* From d8d41871762e4e10cd7c6550b1a69eb9086e7547 Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Sun, 1 Feb 2026 11:16:41 +0100 Subject: [PATCH 137/298] Add missing includes (#1286) * Remove AppVeyor build status badge Removed AppVeyor build status badge from README. * Update README.md * Update CONTRIBUTING.md Updated the instructions for contributing. * Fix for issue 1276 "Data corruption in the etl::bip_buffer_spsc_atomic" (#1277) * Reproduce data corruption bug in the `etl::bip_buffer_spsc_atomic`. * Fix data corruption bug in the `etl::bip_buffer_spsc_atomic`. * Add missing includes Before this change, the includes needed to be done explicitly by files using basic_string_stream.h, and be included first. This was error prone, especially if includes are reordered (e.g. via the currently defined clang-format rules). --------- Co-authored-by: John Wellbelove Co-authored-by: Sergei --- include/etl/basic_string_stream.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/etl/basic_string_stream.h b/include/etl/basic_string_stream.h index 2b466055..2aa1f28d 100644 --- a/include/etl/basic_string_stream.h +++ b/include/etl/basic_string_stream.h @@ -35,6 +35,10 @@ SOFTWARE. #include "platform.h" #include "to_string.h" +#include "to_u8string.h" +#include "to_u16string.h" +#include "to_u32string.h" +#include "to_wstring.h" namespace etl { From 353c36c393a0027cba0bcbed881b6016d2ca30ee Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Mon, 2 Feb 2026 11:46:00 +0100 Subject: [PATCH 138/298] Move comparison operators of etl::expected to namespace etl (#1287) * Remove AppVeyor build status badge Removed AppVeyor build status badge from README. * Update README.md * Update CONTRIBUTING.md Updated the instructions for contributing. * Fix for issue 1276 "Data corruption in the etl::bip_buffer_spsc_atomic" (#1277) * Reproduce data corruption bug in the `etl::bip_buffer_spsc_atomic`. * Fix data corruption bug in the `etl::bip_buffer_spsc_atomic`. * Move comparison operators of etl::expected to namespace etl --------- Co-authored-by: John Wellbelove Co-authored-by: Sergei --- include/etl/expected.h | 204 ++++++++++++++++++++--------------------- 1 file changed, 102 insertions(+), 102 deletions(-) diff --git a/include/etl/expected.h b/include/etl/expected.h index 722c411e..758e2404 100644 --- a/include/etl/expected.h +++ b/include/etl/expected.h @@ -1296,132 +1296,132 @@ namespace etl } #endif }; -} -//******************************************* -/// Equivalence operators. -//******************************************* -template -ETL_CONSTEXPR14 -bool operator ==(const etl::expected& lhs, const etl::expected& rhs) -{ - if (lhs.has_value() != rhs.has_value()) + //******************************************* + /// Equivalence operators. + //******************************************* + template + ETL_CONSTEXPR14 + bool operator ==(const etl::expected& lhs, const etl::expected& rhs) { - return false; + if (lhs.has_value() != rhs.has_value()) + { + return false; + } + if (lhs.has_value()) + { + return lhs.value() == rhs.value(); + } + return lhs.error() == rhs.error(); } - if (lhs.has_value()) + + //******************************************* + template + ETL_CONSTEXPR14 + bool operator ==(const etl::expected& lhs, const TValue2& rhs) { - return lhs.value() == rhs.value(); + if (!lhs.has_value()) + { + return false; + } + return lhs.value() == rhs; } - return lhs.error() == rhs.error(); -} -//******************************************* -template -ETL_CONSTEXPR14 -bool operator ==(const etl::expected& lhs, const TValue2& rhs) -{ - if (!lhs.has_value()) + //******************************************* + template + ETL_CONSTEXPR14 + bool operator ==(const etl::expected& lhs, const etl::unexpected& rhs) { - return false; + if (lhs.has_value()) + { + return false; + } + return lhs.error() == rhs.error(); } - return lhs.value() == rhs; -} -//******************************************* -template -ETL_CONSTEXPR14 -bool operator ==(const etl::expected& lhs, const etl::unexpected& rhs) -{ - if (lhs.has_value()) + //******************************************* + template + ETL_CONSTEXPR14 + bool operator ==(const etl::expected& lhs, const etl::expected& rhs) { - return false; + if (lhs.has_value() != rhs.has_value()) + { + return false; + } + if (lhs.has_value()) + { + return true; + } + return lhs.error() == rhs.error(); } - return lhs.error() == rhs.error(); -} -//******************************************* -template -ETL_CONSTEXPR14 -bool operator ==(const etl::expected& lhs, const etl::expected& rhs) -{ - if (lhs.has_value() != rhs.has_value()) + //******************************************* + template + ETL_CONSTEXPR14 + bool operator ==(const etl::expected& lhs, const etl::unexpected& rhs) { - return false; + if (lhs.has_value()) + { + return false; + } + return lhs.error() == rhs.error(); } - if (lhs.has_value()) + + //******************************************* + template + ETL_CONSTEXPR14 + bool operator ==(const etl::unexpected& lhs, const etl::unexpected& rhs) { - return true; + return lhs.error() == rhs.error(); } - return lhs.error() == rhs.error(); -} -//******************************************* -template -ETL_CONSTEXPR14 -bool operator ==(const etl::expected& lhs, const etl::unexpected& rhs) -{ - if (lhs.has_value()) + //******************************************* + template + ETL_CONSTEXPR14 + bool operator !=(const etl::expected& lhs, const etl::expected& rhs) { - return false; + return !(lhs == rhs); } - return lhs.error() == rhs.error(); -} -//******************************************* -template -ETL_CONSTEXPR14 -bool operator ==(const etl::unexpected& lhs, const etl::unexpected& rhs) -{ - return lhs.error() == rhs.error(); -} + //******************************************* + template + ETL_CONSTEXPR14 + bool operator !=(const etl::expected& lhs, const TValue2& rhs) + { + return !(lhs == rhs); + } -//******************************************* -template -ETL_CONSTEXPR14 -bool operator !=(const etl::expected& lhs, const etl::expected& rhs) -{ - return !(lhs == rhs); -} + //******************************************* + template + ETL_CONSTEXPR14 + bool operator !=(const etl::expected& lhs, const etl::unexpected& rhs) + { + return !(lhs == rhs); + } -//******************************************* -template -ETL_CONSTEXPR14 -bool operator !=(const etl::expected& lhs, const TValue2& rhs) -{ - return !(lhs == rhs); -} + //******************************************* + template + ETL_CONSTEXPR14 + bool operator !=(const etl::expected& lhs, const etl::expected& rhs) + { + return !(lhs == rhs); + } -//******************************************* -template -ETL_CONSTEXPR14 -bool operator !=(const etl::expected& lhs, const etl::unexpected& rhs) -{ - return !(lhs == rhs); -} + //******************************************* + template + ETL_CONSTEXPR14 + bool operator !=(const etl::expected& lhs, const etl::unexpected& rhs) + { + return !(lhs == rhs); + } -//******************************************* -template -ETL_CONSTEXPR14 -bool operator !=(const etl::expected& lhs, const etl::expected& rhs) -{ - return !(lhs == rhs); -} - -//******************************************* -template -ETL_CONSTEXPR14 -bool operator !=(const etl::expected& lhs, const etl::unexpected& rhs) -{ - return !(lhs == rhs); -} - -//******************************************* -template -ETL_CONSTEXPR14 -bool operator !=(const etl::unexpected& lhs, const etl::unexpected& rhs) -{ - return !(lhs == rhs); + //******************************************* + template + ETL_CONSTEXPR14 + bool operator !=(const etl::unexpected& lhs, const etl::unexpected& rhs) + { + return !(lhs == rhs); + } } //******************************************* From 75eb6680d69f6d2bdbe3206a6572f8cf4b725311 Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Mon, 2 Feb 2026 17:43:26 +0100 Subject: [PATCH 139/298] Make typed_storage constructor constexpr (#1291) * Remove AppVeyor build status badge Removed AppVeyor build status badge from README. * Update README.md * Update CONTRIBUTING.md Updated the instructions for contributing. * Fix for issue 1276 "Data corruption in the etl::bip_buffer_spsc_atomic" (#1277) * Reproduce data corruption bug in the `etl::bip_buffer_spsc_atomic`. * Fix data corruption bug in the `etl::bip_buffer_spsc_atomic`. * Make typed_storage constructor constexpr --------- Co-authored-by: John Wellbelove Co-authored-by: Sergei --- include/etl/alignment.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/etl/alignment.h b/include/etl/alignment.h index 73527765..41e8a20c 100644 --- a/include/etl/alignment.h +++ b/include/etl/alignment.h @@ -367,7 +367,7 @@ namespace etl //*************************************************************************** // Default constructor //*************************************************************************** - typed_storage() ETL_NOEXCEPT + ETL_CONSTEXPR typed_storage() ETL_NOEXCEPT : valid(false) { } @@ -567,7 +567,7 @@ namespace etl //******************************* union union_type { - union_type() ETL_NOEXCEPT + ETL_CONSTEXPR union_type() ETL_NOEXCEPT : dummy() { } From e80623bc1a68cc385c596d136320b7ce10b38769 Mon Sep 17 00:00:00 2001 From: Mike Bloom <91038685+mike919192@users.noreply.github.com> Date: Mon, 2 Feb 2026 13:35:25 -0500 Subject: [PATCH 140/298] Add basic_format_arg constructor for ibasic_string (#1288) * Allow string as format arg * Remove AppVeyor build status badge Removed AppVeyor build status badge from README. * Update README.md * Update CONTRIBUTING.md Updated the instructions for contributing. * Fix for issue 1276 "Data corruption in the etl::bip_buffer_spsc_atomic" (#1277) * Reproduce data corruption bug in the `etl::bip_buffer_spsc_atomic`. * Fix data corruption bug in the `etl::bip_buffer_spsc_atomic`. * Added test string escaped * Add temporary string test --------- Co-authored-by: John Wellbelove Co-authored-by: Sergei --- include/etl/format.h | 5 ++++ test/test_format.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/include/etl/format.h b/include/etl/format.h index d090457d..95dafc8d 100644 --- a/include/etl/format.h +++ b/include/etl/format.h @@ -284,6 +284,11 @@ namespace etl { } + basic_format_arg(const etl::ibasic_string& v) + : data(etl::string_view(v.data(), v.size())) + { + } + basic_format_arg(const basic_format_arg& other): data(other.data) { } diff --git a/test/test_format.cpp b/test/test_format.cpp index 31bdecce..2e148bb4 100644 --- a/test/test_format.cpp +++ b/test/test_format.cpp @@ -282,6 +282,68 @@ namespace CHECK_EQUAL("\"data1\\n\"", test_format(s, "{:?}", sv)); } + //************************************************************************* + TEST(test_format_string) + { + etl::string<100> s; + etl::string<10> s_arg = "data1"; + + CHECK_EQUAL("data1", test_format(s, "{}", s_arg)); + CHECK_EQUAL("data1", test_format(s, "{:s}", s_arg)); + CHECK_THROW(test_format(s, "{:d}", s_arg), etl::bad_format_string_exception); + CHECK_EQUAL("data1 ", test_format(s, "{:10s}", s_arg)); + CHECK_EQUAL("data1 ", test_format(s, "{:<10s}", s_arg)); + CHECK_EQUAL(" data1", test_format(s, "{:>10s}", s_arg)); + CHECK_EQUAL(" data1 ", test_format(s, "{:^10s}", s_arg)); + CHECK_EQUAL("data1", test_format(s, "{:3}", s_arg)); + CHECK_EQUAL("dat", test_format(s, "{:.3s}", s_arg)); + CHECK_EQUAL("dat", test_format(s, "{:^.3s}", s_arg)); + CHECK_EQUAL(". dat !", test_format(s, ".{:^8.3s}!", s_arg)); + CHECK_EQUAL("^dat $", test_format(s, "^{:8.3s}$", s_arg)); + } + + //************************************************************************* + //this minimal derived class of etl::string is used to prove that the + //temporary lifetime is long enough for the format operation + template + class clearing_string : public etl::string + { + public: + using etl::string::string; + ~clearing_string() + { + this->clear(); + } + }; + TEST(test_format_string_temporary) + { + etl::string<100> s; + const char* data = "data1"; + using string_t = clearing_string<10>; + + CHECK_EQUAL("data1", test_format(s, "{}", string_t(data))); + CHECK_EQUAL("data1", test_format(s, "{:s}", string_t(data))); + CHECK_THROW(test_format(s, "{:d}", string_t(data)), etl::bad_format_string_exception); + CHECK_EQUAL("data1 ", test_format(s, "{:10s}", string_t(data))); + CHECK_EQUAL("data1 ", test_format(s, "{:<10s}", string_t(data))); + CHECK_EQUAL(" data1", test_format(s, "{:>10s}", string_t(data))); + CHECK_EQUAL(" data1 ", test_format(s, "{:^10s}", string_t(data))); + CHECK_EQUAL("data1", test_format(s, "{:3}", string_t(data))); + CHECK_EQUAL("dat", test_format(s, "{:.3s}", string_t(data))); + CHECK_EQUAL("dat", test_format(s, "{:^.3s}", string_t(data))); + CHECK_EQUAL(". dat !", test_format(s, ".{:^8.3s}!", string_t(data))); + CHECK_EQUAL("^dat $", test_format(s, "^{:8.3s}$", string_t(data))); + } + + //************************************************************************* + TEST(test_format_string_escaped) + { + etl::string<100> s; + etl::string<10> s_arg("data1\n"); + + CHECK_EQUAL("\"data1\\n\"", test_format(s, "{:?}", s_arg)); + } + //************************************************************************* TEST(test_format_chars) { From 3826e2ab2ebb3f67c34c2c49e3bf00788b4640a4 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 28 Jan 2026 22:29:52 +0000 Subject: [PATCH 141/298] QR Code for Github --- images/QR Github.png | Bin 0 -> 20490 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 images/QR Github.png diff --git a/images/QR Github.png b/images/QR Github.png new file mode 100644 index 0000000000000000000000000000000000000000..94c76e0ef54db47ebe96a8cd7f045ee13f37eacd GIT binary patch literal 20490 zcmdVCc|6s5`#;`HBTXvJ6sCkWscfYX$1Os& zux8DgO=_wqHP@{9J{A35zYab#bB|yNAHH+cRQYX9M#IiA_`?roN@tbUtjP-EU|wZ| zKmTa2s_VFB4Ywfr{hgZTzNs~9G~(4xDrwy^n&@(Ky43DExok%DP}-%d^ZlVM_@922 z+ORHdUFyCMsz)Arw>(RU*>6kTCzRLHrPgzGq(9H%QIg9}oQ!Xbdf0K_Fk*ou*Zzp` zj)S|tU(fOC-s|t{>c7A9E5%6(pPn;ZbM)=@Nd}F+Y^KO4b`)?|yjHinek4eKB+e?M zz=LBO$8X=m8@#putS96{!O#Q6H1s{y|{BOR^4_ zZQQugyz)L{#g>n9JIU+GlPBhiU*_j6D^Iz&xDY*`pN)AIQEg#uEz)InIn$_hL-5X* zmop=`AH8AT_ydO}|)}M=4NKagt9IOs2d#dc;?-6yf>#>ZZS76{~zDiHq zpn?+a$)bJDr%#{uTFbt9^gvh?Zf}q7cDn%cW3|KC@scZ4f&cX@{(ro;m0rOswwBbk z^lZ~w?yQxC(9oZCb1ft0gAZjG6zpNlPlQcR-%Rg#k&zMk?AiW<2M)aV3$SX>P@d)E z<7@Q`uxNQ!{kip}ps=vIu#}PO5Le2}mti!TExaNv?LixUxGq{R>*nCQpHkA(BXZ0d z;jZZFMl&lEnJ1ji>C`kf24(0Q8O3Q^=TqmZH9RyM;uSNwc%}OYIfSK__`tS`=J)S| ziA18Rrzct48t(KvagS+^0>Wapw)Hk{?waQca|d-_UAd!e{ouialOq*#)b?DHy+@B8 z?J~3Nja*tP3Wxc|%rdo98-%JerU8|WwfpTEvw;v1PUe}sHB3)L=+N$ut`{~oC`PcS0YiAg2 z|MKO_=mD3_{Bpm9M@GKoJBoeb%a`gZS&j=+pLT7$aI@-5mZ(Ag;o~>^?>2bMd>$X) z7%8gHjSu+Q;*9v^AX=5fnBoADeuZXWMf~KhOFnYEU0sHS6xYvu-Z8 zZ{JSJ&AsFn)_zvHXCJA@B_=7kv$SHoD_8yV=g-%#T=`X4D)r^dqmeSO5Gm)dHmq?p4QQAM`2C0z$b?Zi z_S4Kzt){-dFoQnX?iWyA{u}g$a7n8+^U71k#>U6`oph6IOW{jh5TtU8l)Pf2ogVxslJI8^oz%F4=LKet|BUe<55 ztEG`~nP%T+|E=W3je>%GufZSf7{I_vsxSBs;i!(AzC5 z-_}G3CoXdH@K{ya`E2G3?dsB#@mwj^wjLZAsg3Dl-l(pwZmJnPX47?SF;Q`8??Dlf z4}P0S8Mf{{viduA>DoUN|M{ltJh`e)FmslaId?>SEil6JyfDk%j)X+P31lz z8Gf=HI#u){a`5n}6QM#Z~#W^E`j9qB3o)udjdDakwtOPcS6UX{`BUfOPNr z{qV~fceDTGt6S6kqvKiDLqkJKDk?rk%DC9r*fKa11A)=z{v-_%z2dB&ZCajda2k0m z4ngm0irh$h;ACc6Jg0^Vx1+%EIaHavHznsl@58Y40_)I?s59Y=p4OWxS~1%de_u7e z%Sq7dD0e)5P*k@+z_ck;uvdp$v^SS%zGfx!|2UHVS20S~t|W3ySE2Ju>&|TDG)0er zw*lEU-BJ^ss0-jGi(3e#DbJogJN4+%qkTA>zOaup5K$W?4oIdsSv`@et*s3xq&nTs z#wLBIqKAR76u^SPYN7aWKrrw{$?8#08U0_zT3}K|L6wlNM zH~00yT)g=FT!c{Et>3uCji5bl-@d&`HouWH*l>i@I6vN*$i?gG>e`g!*i-1Nmvux= zZf8BdDv(bvx)@6OsoC?~B3hyFLEY5SQX?t5-Zc5WVlVceINrI7+rQw0Syy>N>fVkG z(kC>BV=PhYfVum%!+8yK38_vT!(X#kry|IXStyqeG{L2!O@# zr=%VDiGIVDlllvk_di+RD-);5hnYLl9VC*vmcCE%`&-d40QIG!lyrSk4M2f6O9Rrj zlmp#)HZ5_n?u_~B#2^Jrg+47uYC5UrqK3R+bTmMyEUR`g1g-Ae`R*@Zth7|Y!pbTv zE9*#l$8l(K1bR_lL|K^EDY7f#YKl&QIe{*cBHm-czF0bw?2kZw5)R~ zw8WtyHB-~%!NEb8dPPRI?mqYL6HNvH)XkJkx@!Ome9A@M#L1~bwFkVN-f=)oEV9va zWmdv-g#b;FUOC&SD9$5h@ZPWQ*_r4)8VZX^B8G)p!cr7hZJ4rd^W#l^oA6{wDXE%5 zXDZR8BKBI4+{_=vOP^mtWl}tJN^a-Qk5m4=8+Pt`k?QOF}*l_w!hLpaj_x#sEV-ExyQ$ML%#}zvt&_u3JwfWfLlZ-fr|_%ORURGC2(hxUx1DX zcPx(fJbA3;c`bRBK~@p}m{MM{O)v9AD%+(h`Jf(0*K9}nJvT9Z_2h)lUe`5Y_?O4j zCu?Dy`@57RnDy@f+yY#)fcAac%?-w|sHmvYFZ-d*s_GXwn7(gmNlfgJxixj=yq?|; zeBDVs817r{tMOGfe5&yA&d$z881vAfLtfB}sRvvF1r+(~;#o)0b#|ByPIk)$W_xGn zb`kwN5gL9v>l-TQ)G%T-Y(NU%8n&0#&!xAjN}l;jMJ=aIOaIpx-+yZMe`&#`g@t-? zgc-Go-Is{Dxz&4vX&KvCx>Oi@r-i}q77)wg+ z_`*W|{P@1TFA8@>Z~Mw{4h2LKzcLzpY;0s?WWtLV2fp@rd3ky0@l$uU|CP{eT^E{= zmL`II*{^KRHR9VYjNiQ@{!r1=gK`8b^FTh_Gbm}e2Sjd!NeisndV4c~%(&G}GC8^SJ%5Dp>=xt9bD$-lHMfIy%3M_Y?uK8fZ|(Yro|UJC$RN2#)0XzmXds1ccgdZ-yAqa^z82L&i#I0)m9C;-3XJ$1thVx z!qnKlbLR*C;GJV*W1%rI!dW_Jgr(kARV6N4xx3}FPa{x+R1?2VJRRiK<;mK5={|rS z78Vvw>c7t|?H7JgxLCOS(L?Xi!-s#&dowH!>MBX<&N?$*Pq0(x&T5}O+eYXq_}JDS zyEQVDODjy$_~U9rEE%9nS562qVZ+B&i`A9ornQUEx?#$hRQip6cUey_m5VGW{NmZ8 z>ujxBVQC4EEaA0xwBGjpZ;Dg@sa5@(c7~*qxSul&i}s`58@KxGY|MTxF0QVaV$c}| zN1GBQjvRTyQmERb<>d{9J-W%BWYma;YNMc^O!rsLB#XPN*%prNXHiu_^+?qlH=b!* zLqYA+^I_>D=gyrY3S{Txz$?tn4|I_$Dk`92tlC5t1y%<<-$4Q8_LI`m(#+j^N?(0w zY1zvu|0Ni;Hux%8*&T)?UTIt4vha(z8Rk9!%BUzIdY>n`E*5tg#^vJZFttHlohFB; zQXBBP;zq9#V3r9yR6MMmt|z#@7nTdr|G~27W;L%Gk!UGr`)ac@Z<11(z9^lqMJ5vK1Hv@`fo*vdEuOUt$r`i zG1RI(Ij@)bwWQszg-){pkYF%W`~0rgd4tY zNqdw_B2iNpGK-3EFH%$e7@+LX_+9APxxh}>S+%A4;%@9oPe|C+QQ}4lG!Y^ctZz%# z=Rp|Y7cFmq)iCZ)si=5^m{rB+n4QaGbW7=Sr6)7s?@?`82Ln@k4qk1~Fr1mH;IwM= zw7cCBGx)@ZKU7BqsLj}1yK$7b`(3KqR$26DC^#uk_%;^niqv)H8Suk63snVMtg4Bo;ugpFjJ}SL9l?1J@!Fk9BcY zR#t+P2#3hL6lN5Q;228NTQq@N5j`Cp9N-I+l1`Q~hs0IrhKKCi(*ZGnG6!tE<=I(( z8V9~q-+`XhZH7jdUqEqjv3V(p;@}Um;-*d2#w$a{k1{j6$+o3-93r_uUiM`moHdxWjZMN)hno7gJ370=s6E_JG&@+3DwYHtXU8W zU8#pJ)WRZfb+P~ZDN^a2X!Mb5FajRSIv?ud9BGIJwh0sVonxcC5L6^w5s+9%3xREE z!eNl}1l9Bu)w+6OElD8F_+zM`u2SoAg}1)Xg9jjw*~gDHRO{Q7T!I5BX^amnn5|o4 z>#QdwB>XCI^k}Y0RXyIxNy|-&BFk(NSPo&fdoD+5k26PA6homFtr`RMjp@Gy|6I;? z>gVN|DDuYgn1l5}L-3dj<3t zOm-rqU>2lx0w z=p37vhzJwXfRgDgaT~hB&L6x_)UgJ7La151yEaxEiRtO0dVLtL(g(#xAgLT1FH!;h0|9aJh7b%N6z9 zlInvNO0DvDX(e={+238N`0(%Oed|1K;d z@?i4@b+KOy=5kAIs~_2Ai|A&bES=BIRJ(aI3sC!fm(>gnPu9n@w!N)hmLM+^1t=Qo z0|Nt1E6$3df>xzS21flo%+GH_`huvgQZ8^qk1vS=)#;>OAiy-`*%Jaw!8>K0RE0ep zSEoMCS4@!lpdrx;#u{RKittvI_ub0uXAMcVvD)MLjE?&5M@2z7+1W&CwF0mPK&De# z2*!_<5p5{>7gSz>h!-5b*lfOv>+<6g_JYhGsLRLFzwbOjDOoRbqL zPAGwf{1svw5vG;-*iyX67yirE-M^tDKepY=Js;*Lx`&|u|4a?ago0M#cRlIm0Kqc?sbX+$v`AyiP7IbazBiGYqAvmi z0+i{~K-l1V!I`ZVSe+KA_1!82XRYK)fqP^~$P+Gd!SBQK-W&>%6!+n_vL&YT>YC|@ zOoH+uVPQC@u|c%QP9w>JbWTBAKF|>0mFd)+Mg?K8RY2m#D==G)mm|P-Ft7Ba$*ks) zO2Do`M|H6^(<50P*SFY!zg}^F6J}|AMM+_$CCd|boB$}DF73~Rv%>zV`vygFChH!% z9a1rJ=zmt65wFb2xu|j{_o!LJ4}gzvw#NoUO}E=j`n4&Knx?;m-)@gF*Ys zo#7H&5<7KIP>1Z{PC4RkvuV>NSvUQ!l5#pwW|dbJ{{-OgGTyP9Q*P?_`Ei(awa}rT z$m0NCYZ@74$m0Oih1d}Wctg=Gf>Ngh!%wf8YVCj7$W>Wkp^UTU_3Ph3Y#Sb~0gHGa zVh2(nJMD^Jcq5bq<5yV9!NK9_qTZwrxIM~LHx?A2PKmG1h-)G~#JhLz-li4IbnSy# zojAK2vs@{je$-pE43w5#3Ju)^norQXxdHMO<;EpT8rx_K^3k$c7^*wpA8#?@m z7p~o|V2B%(kDWWik$E=ExN2gur^|{~aJ70O6G$ldEuh+w8o{j_OpY>Y_FFAonaiy0 z%C*Wh8$nGUK&n;aId}IG>)v8rHz@>zyq|#k;O0VM18uR_jQ>4AS|LUF$@g*lTY$0{ zVpqC&W1&$b{rRNUwOVUfz<{KyN$kwE265d?muk3+~2=aHW+Od z7gAGm8ZOg!9X)p7f5SWS`n=jd?>*-qIndxt&p+1H3wQ04Fux6 zrqVBh_3}%H_f+s748#2w^-FF$+e0%ln^h@6zyCW~-K#)*Enh0Mv4$S#iJxq6c1wPa=m$TT}CAmVUBTVbD85 z`0`u6mMZP@=eLaamgt+=nO(WEONV4@i2fbS@@p&SnY^;RGPm4nF|!bK}OTSwIm5Zv9{lK4Yxn_GUl;$pzmm&x-OpbAC+Icd% zhr0V#^5(~r^v?GHd!)EcmPlX{KkZ||t?8$WviWOAiu#r_K-RaYw1c9bdAB#{BNvpIbC^(tXlR0@F?5+&C*W*W;lK;i!1shD+>v1>e_~ zUU8i>mF8hjzgMIvayCZltOAJd>dMOZw5=g%Q^V+`E4U6tT!uRXY(rj%;wptrWt!_) zhW@#8fq<*5PVB zq%U8bppU}M2Ux|T;N#;DXaktKZf`{$#<3z6b#)IEx|fMgG)jT_Y8;Dq(pTq6WKpQ5 zX1@SXeX8SE7vpQ25>+r7Z2%qY`mI|aP;TJh7%CWv^KXz;2SVNC>^9eW8R9x%Fh0t3 z<1dS=m7x_*KuAQ`g|ZkN74=*mH_{j%1>9(&GbJ-Ksy;^Asu2M%Bpa098W92d{lvt?%yf{a z+#~!Udrm3*UX3$n%q#7XTE%~|txQ}O9e&p@O)AMS(1fLKG{%X>GbkfTn2=@AadS3T zp#_@4vJ~(vm=of!Y*zu~L$V2eZPQL~Wal~1Lr_7TY5-Kt3u_bz3$LIR@cc&FOk-;b z#o1A0b=av0gO$q2$mrdX#P@_w6C6jDCYO6BEgBox6{fyJWGP)9SG_(}Y&0p{raQ0T z`i)+g#$HpwkosU^%2VW_Y9k{nVCN-No+W-r(aLfKDucb~r8?RnLHJxZ)0q5*i* ze(8$^7);XxRo;uUBULa{zzHt?2m+bxhBRk9p8e9LOMur-so!gR|30Cpvkf%P{=g`( zbyEYc`1}({2i*Fkq9T1amlY~`MV(eO37{MqqriMu!?D6Ia+wH)u6Q{u%GKWfFeH8& z)Bl_vX=~G7%u!_Im>cWt0OJRk+dJskaDOHhp}y7B)dTPa&{%5lrL%m|3hr<^T>dS- z23L{jSzBA1YchZ&uT8vCh}L{1;60Nbmxmi-UviO6fl||zk+{or0nKXES`jgA=5PZq zskCjxE<1lD2qM4K=OsR(t~u*RXS@N z02~WtOp^QLR5w8y4(?*EnGm#Hwj5wZ0Iwhq$*eSH-g^)bz_NmH?;r$ZRw_VQJBs9i zME9#>k@~hFXp~4m{v~~(-Y^q714hM|r_L{n@+?rC)gwNRlzSJ6bBpRFagmet&d16+ zTM|o2y|-V&&#+SVX1SsXLUcgAbai!SD2|PSf(glwssudcmVEfF;+H-=56vzG1RM?{ zo)v9@sFe5NF9lkmKa0xMd4abZTe4ctb7vPJzj9d&3m05{@!ci|-FBd9zMMmRbp6V}e+L`FVC3UM-y&j^!lePQ5^0(7vop#nMhSmq7y3&OgIbIv2L zl2KDrylw`Gmist-AH9@bjR~j~6Z-U>*+%SDv1ZWmx@P-I=)J<-B)j&wSX77E9?Q2U z76TGeL2F7*OFQGXQZy8)KR5}NLjBsi93Gx@yr&ue?_tSLpZ=yWm!hF&3-Mp;oj4bf zCCbW*2WSCe!33&)pC7+NB=q2c8!bpTBv2cX?<|`p@A>yu^*%p92r+D{kTAD2E}pWD%JCVeWL(gplBpS zkY3CLz4stE1$xu*`bfW<=)CD#HQ|r!1&I&s?d&MYrKR_C7vQz|U4#y*W%rML6rc$> zr0-0<{t<-&=3PKz^TP6^=bmZn>TU=3a14xt#KgT1ad=w_6fDRZSM6s8Ar}zHs8jam z#)yEC5&xgn(ZuQx;NW-xH3!$h4qT%bDJj0lb@=43J=O0o4(U;@e*%Ea%%nX_0;^MbV^>wUMG>DDHZ2c9$#=dJM{8K_1X#-}2f$ zWKTg}=6l)1#L)jU&(E5STH5JQ)CR$hdBBZ-ZpYt|EJR%!z>$;79WZ zH3`N6oB+@$`ho!?TUOdZ+~71I{?#o5aduc3b`w6nU?kX$Ul+{WU=6Smn!T6JHh z8VAi(Ck=n~&D06QsE6Bc1#;@KSZloQ>O%}qgKn^%Q{Zb~m%9t5nO;8v-j^>&W#q*I zH)99G0$Br>w6uOem;J*2Ot|wZRzKN+=SF*UkJA-$^N@-@f9Vnzz39xdVH63_&!_&guXaz#1D-CuK-k2HBX*|t>2%tl_PL;8nV$o=*clcXj%uXg3 zP@P-ON~`HTnkX8H>HV^Qv5eDW7Zx1|KvEIC5)c6hS z8yd1?q?tH+u?onWx&35u&&ArAA|Se;hQ{%9c6N5n@+w^dn;w!dnC~${ZZ~o}8+WVU z_rQx}FKAUL%614vBC|eyKebHn69>=_(;`$*eek96a_Tme&pibMu?|`=*oJ_iZrwUw zD4s@-<}kNiH7ayc6Ao*Ez`@QQ9x)v~2l11(ib*wV0~40?X>4tVB$i)sXXcs!;~`7w zp*VKbOJn`PfFc7F=8M5OE}9&~E?VOFcz(CCv?Pwm@MvAE&a>$@cqL``=_>b`GiSg) zY6mIXdusPKd;r1v6E7Z8SRhIMD;A@W$0e-&1B$povI-b=8KuB+AfxHJB}8bO^v<}z zK~w_VOp$yl*jxUQcbrmi@iK4q$85FYTn%E$R5^#N*XjcA-?@d8th1%L?<|D)YSDg# znHlOy&W`+|8NfmD^4|5Nm?E zi-?L+hh!HBUFN0^pU1|0=PRC^@ByWILZ9T>qmVb)pn^YFINKcRR#&vhVpc{*MozRe zebPDM6-VloWr8Ec*|E{hYVuYU?x|$nJae|O_WmYbaNfFz7NH=4%JV`47CY}TxL3f} zc8fZ~t#Zt%3LuPaZTnGR1`>xJj0v?LU!x5db^*eBX2SU7WE3bk4~%><>T zAuoaK>oPC4(8wE%__ZMH{?T@oK!E(Nk=ukMBIEVO{h-_<9?XC1<9A~;8k!Ma;~DxA z{3lcHqFN<5F|OL%qpZR*m39rUsDJ3dfj=6mF_rO`Uw-+6CQW~w6K<*08aqNO=mg9U zuGAteL*LmsS9^S)@C(?9F@AO~HdP*n`bsi{lif}koIiUXQYX8LZ;4Gj%mY&Nd3_!V zu1oacX!(2B_mx84P`u=e=9W_DDi8_tAjQ0EW0@?Y`ekmeBt$p^i%wyn8&x$ZCEpSa z_$N@p2|JveoJK7x^fWXyUO5caffl%k7FD=Y>>S4L(ST3W$1 zzJ2=^!~+-sGa2|2btCt=OX(dCrEK(^&Osa(eEuZ{BXO~mIRlZYkeC?WdJ;q^!PaEF zmY1euIdGcHGzuTU>3+$D6Igi7ejOB76kzZN=k-rw$~vrp7oKp3fCe1)>(xKIg7*HD z-6t6~Al_jEVUwI`O*owUkr)vKP|y@;n#0PKt%l63C5MA<0ts7~J5QJOAvDBAb_Vs+ zn^WNcLS57PAY?m{hfuosl$x3vX!1I*euejXr+K0;Q6&hjFNa)JkU$g`TDtG{oqf9~ z*1#$Lkuj5)XOcflsc(;+1h=3aGP#Qu)kF7D&Sa*`D$}Aeu$v4Q9>8M|VQ??(Yo%eD ziS3=RJ&&!ol$z#$3%0Yg#jw`im3b2T)rTKCyE{wW-GV{)!q-)Q(9SgCyUQu_7peaI zCQPdDfOs`W`T6Zo@m-MR_dd)VJFvnbFjEG*IiRale*k^O3-Y6eT&v#{6f%d+OfD>> zeXQg${?K#P49t}dq$M7K<*k@~6<_0? zs^O$Wyj?c4cXBz7`Q^D{1VjkZI~Jg{_IggSd+tKfwCKlZ4=&yA>QyM@@jkLKGH<`7 z`8J@fisohz$sv=gN)$jBloj+DiT5d2AZ z;FvaPs3UVfetFz18|o7Tw{~Hukmi;aP+%a}t$F#f5SD@MGs)5+dZxGU<|LK3 zM6)V3AH;SW8(?k@LBbEHD{x)lp?hRIL?9EOrlO)!^TYi0o1ACqhx0tHfGW?obLWHk ziqTPI$bDo0!aFr`H+g2pVX--?bRS3}5Y~ki)lq_K1kZ6&sps5fPgDLh2pT+f6vF1s zGmUtDh&6qG?I0u_l$7oeru~h>AwXzl>ab(`_7KE}Ht#$RSFw6SY9LO)An?^ZShtc( z>}#zAmfrhZ@60xZgFX{Ir#O}W>-Qf$!`j-~67usqO4uIe!3xLK<4u3=_n@-uK6Kpq zb9kVHYpjC1te*cZtHEm=#v)#jx&sjOO;16T^*aG9f1~JnPy9X>Nnqv6Z%tS7IER1O zQfiKroIDg(Q<)O@ClvO7Ot*TtfmLxGS{Y0>uJjJb+!PR28GTV8a_9<6f#kMNT)dIs z4to=WP#cjLaeC{;#xaOW1VktcQwIm??M8X}JC-poFJ?>0-;H(oBPegP*yt$+-yO0C zNC-#e?21(Ge$t;e4e!HZqN^MhbEFyAk7VL}L;;N0s1Kg$yZ9HB-< zap{7L>r4{ZW2UCnh0k!+K>PM@91+zO!2qnS;ItZ1;U<2kpUX`4QFEw zwzf7g_f^}sRR@%$ft)1dPr=dr)1s^hYf;t(HZQ$kee0{6Q@qgcFS|jL?VnJP|FiP* zAJYFIB{hHeun*!UdebrbKA%2aon<^tPd~fT?a8onnC@4GVuef!NK3VK(MO@6AaV*z zIm30^A@IcQuLe<;FD=aw4;~UyT=d1ptQ1JUJn55GnI+(+(ilaK@}i=WD-&;e$TS5P zdQS46OY#(KSR*qZg}zMoii>Nk3@EOg=$(lq!CsJlH`t|}C`OBA#i&JCQ@!cPFCfqk zp%>$P$~Do5;TQ+dp~HmY37W9gAf_r0)}sWrw4cJQ6~r%p2y$hfqV1WGzX<@n%mQMM zn2?DUWy&qlY7%pJK1!b*zyA66^zWzci4%5jh>V0()FC)+j|~tVl%f>!gU|^l4h9EU zurps;G-@F!l-nuB*Fe8xAclZ_ir`oiJUQZCa$^g*~ASdQ)^#bvH|Ni{>ix;<|&@t=@ zVd<{QhBt3czPeg*9}2h&Ful{ZZ(*2!iVyjpR=#1q^g7CphCzD&5m@RFdCV{@LQ6aA zQ0_Gm5GtHWEb8*_vG~2*{wM-Y9HbfJjdl8}PyleB6(6`Lys>8B&cM6`sjdLr{~<^U z1E2&Ei^&{Oi~=~19FFy?ggy`El-ZD`1lQK0c-pCqal1Ta=sumH%CL z?>tJ9kCdaXj5%yvI7LQh<5zcO1l$|aF)1l{>qz_>?b6-zBK1FP5Un9SgoO+uGZO8WmTIVf6!KkqZ|t09Mu`!h##B=wJuN?n@0h*Ke-cJAqb&!jph6 zc(_TWw0o~Z85EG(OR}$&!5Z{UdL=cJ43Q)hwcLaD6LNA0iw+FODz?_^FETSZ%l$_* z<1H{p?RH8{PWE##ipN?)><}4wU<%L( zSqWTN<$kB(F|&1c&Y4l0K8XdH>K;j|L&>bDAzTT z-D!^5Xr*$YK31Am2-?s&nAncxv78YR5h#3j;v2yAa4c*5T0enB;$p_7P&Pq|EBVMj z{GV7MrgGV5E8Utl_iO26tRe2d&$Kk94MeKDoUTCFVM$NP!{gfqV)@i_*dnm| z$l7N_wUYo2GxRkX!h-#Ih}1!1q8pMU-as`!j|*isG&EcR!gRCUTq1X>QWV93E=|W{ zkLf{=?wOgH`HCr71r;!Mjn%2l;&({dbZrB@tIJ?M=dI`R+Q0otODv7orl;^yo^|IQ z;PSBahqjy`uKMMRs+HBt`TdzOwuNf8MH5nL>N)N{ow-&~z!Iu4kwxqBWu(deYuone zq7fvUA)_j)w{LYJX!QWxUsxdkee@lmOEuQ~(bCpF4H_D%4JfajGJA4!bFnmL#{pqs z|F4^0l){xNPo|Fn*#jc4P(44@)A1f7c+j_iywCV*5XuSe&tY*KmbLLt=aRmMx{^h+ z6iCp~qo%E?mxk##vmwo(+$c?*-3=(}wh=t=0u(1eNyqvi)(p`dw8JJOZQYT;g{tV5 zW_I<;GGhqDny#FS#>V0?(spfeKk;aV?FLcENG?kAEbs^CACf}R12xdo4gQ4but&0d z0uun#9)N4!Q^~6EET5^5WxF<-eSJ*JahT|VCL>dyDwKXXgx0ySXFa$0q?qyJT+YCY0S%gq_QSJ$9NW`MN(><-ipS$w9@l$w?RwK#FwT0M^B~>RA2?=( zRH4;5&cAV+_TqPg#;Z zdZNYPJszWA;4vUxLXgH97AN39u~Jbpz*v7{Awy_Kz&WnNEMST4^^YWB6ZIuVSe9AO z9I$V<0$A5njBWW*t=xM+a!bm}x&V()c*aEzfG0mu-*ZX7?2T{0Mq}`ZQ^l+j{ zWLh06sCP#&%8?=iqc(*LM>B{&Y8E)p#CO|})BsHW58fByc03qyN?i{gVzEWxu2cJB z=2x*CS?Suh3~dkf}O* z=FAVgQr3SI&HEyslFxLe|DW^dCiro7p@cK6|3a!s)6h^9a10o9a2Kyn_Li`q1)%7# zZacCeHd_)&B Date: Tue, 3 Feb 2026 08:58:24 +0000 Subject: [PATCH 142/298] Added etl::visitor_from_type_list --- include/etl/visitor.h | 21 ++++++++++----------- test/test_visitor.cpp | 13 +++++++++++++ 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/include/etl/visitor.h b/include/etl/visitor.h index 1d917c0a..c9ee698e 100644 --- a/include/etl/visitor.h +++ b/include/etl/visitor.h @@ -205,21 +205,20 @@ namespace etl virtual void visit(T1) = 0; }; - //***************************************************************** - /// The visitor class for an etl::type_list. - /// Expands the type_list into the existing variadic visitor. - ///\ingroup visitor - //***************************************************************** + //*************************************************************************** + /// Helper to turn etl::type_list into etl::visitor + template + struct visitor_from_type_list; + template - class visitor> : public visitor + struct visitor_from_type_list> { - ETL_STATIC_ASSERT(sizeof...(TTypes) != 0, "etl::type_list must not be empty"); - - public: - - using visitor::visit; + using type = etl::visitor; }; + template + using visitor_from_type_list_t = typename visitor_from_type_list::type; + #else //***************************************************************** diff --git a/test/test_visitor.cpp b/test/test_visitor.cpp index db881e78..1ab34f77 100644 --- a/test/test_visitor.cpp +++ b/test/test_visitor.cpp @@ -747,6 +747,19 @@ namespace #endif } +#if !defined(ETL_VISITOR_FORCE_CPP03_IMPLEMENTATION) + //************************************************************************* + TEST(test_visitor_from_type_list) + { + using Visitor1 = etl::visitor; + + using TypeList = etl::type_list; + using Visitor2 = etl::visitor_from_type_list_t; + + CHECK_TRUE((std::is_same::value)); + } +#endif + #if !defined(ETL_VISITOR_FORCE_CPP03_IMPLEMENTATION) //************************************************************************* TEST(test_visitable_from_type_list) From fc7c80bb976264a71f0996036596d3c0ec119915 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 3 Feb 2026 20:33:45 +0000 Subject: [PATCH 143/298] accepts(id) for empty router passes on to a sucessor --- include/etl/generators/message_router_generator.h | 9 ++++++++- include/etl/message_router.h | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/include/etl/generators/message_router_generator.h b/include/etl/generators/message_router_generator.h index 6b3602ff..f54df20d 100644 --- a/include/etl/generators/message_router_generator.h +++ b/include/etl/generators/message_router_generator.h @@ -625,7 +625,14 @@ namespace etl bool accepts(etl::message_id_t /*id*/) const ETL_OVERRIDE { - return false; + if (has_successor()) + { + return get_successor().accepts(id); + } + else + { + return false; + } } //******************************************** diff --git a/include/etl/message_router.h b/include/etl/message_router.h index e46c05a9..6ae44d18 100644 --- a/include/etl/message_router.h +++ b/include/etl/message_router.h @@ -613,7 +613,14 @@ namespace etl bool accepts(etl::message_id_t /*id*/) const ETL_OVERRIDE { - return false; + if (has_successor()) + { + return get_successor().accepts(id); + } + else + { + return false; + } } //******************************************** From 2e54c01c69d08920de4861bccdc261ca873d5a50 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 3 Feb 2026 20:35:44 +0000 Subject: [PATCH 144/298] Fixed incorrect comment from 'tuple' to 'message_router' --- include/etl/generators/message_router_generator.h | 2 +- include/etl/message_router.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/etl/generators/message_router_generator.h b/include/etl/generators/message_router_generator.h index f54df20d..1f8e19da 100644 --- a/include/etl/generators/message_router_generator.h +++ b/include/etl/generators/message_router_generator.h @@ -655,7 +655,7 @@ namespace etl }; //*************************************************************************** - /// Helper to turn etl::type_list into etl::tuple + /// Helper to turn etl::type_list into etl::message_router template struct message_router_from_type_list; diff --git a/include/etl/message_router.h b/include/etl/message_router.h index 6ae44d18..42735ab0 100644 --- a/include/etl/message_router.h +++ b/include/etl/message_router.h @@ -643,7 +643,7 @@ namespace etl }; //*************************************************************************** - /// Helper to turn etl::type_list into etl::tuple + /// Helper to turn etl::type_list into etl::message_router template struct message_router_from_type_list; From 1e2b69bc958da6bd31a5ede1cbc40e48a53315ef Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 5 Feb 2026 10:53:08 +0000 Subject: [PATCH 145/298] PR review changes --- .../etl/generators/message_packet_generator.h | 20 ++++---- .../etl/generators/message_router_generator.h | 2 +- include/etl/message_packet.h | 48 +++++++++---------- include/etl/message_router.h | 2 +- include/etl/type_list.h | 5 ++ test/test_message_router.cpp | 25 ---------- test/test_type_list.cpp | 18 +++++++ 7 files changed, 59 insertions(+), 61 deletions(-) diff --git a/include/etl/generators/message_packet_generator.h b/include/etl/generators/message_packet_generator.h index f15efb03..354601b9 100644 --- a/include/etl/generators/message_packet_generator.h +++ b/include/etl/generators/message_packet_generator.h @@ -88,13 +88,13 @@ namespace etl private: template - static constexpr bool IsMessagePacket = etl::is_same_v< etl::remove_const_t>, etl::message_packet>; + static constexpr bool IsMessagePacket = etl::is_same_v>, etl::message_packet>; template static constexpr bool IsInMessageList = etl::is_one_of_v>, TMessageTypes...>; template - static constexpr bool IsIMessage = etl::is_same_v>, etl::imessage>; + static constexpr bool IsIMessage = etl::is_same_v>, etl::imessage>; public: @@ -102,7 +102,7 @@ namespace etl //******************************************** #include "private/diagnostic_uninitialized_push.h" - message_packet() + constexpr message_packet() noexcept : valid(false) { } @@ -403,14 +403,14 @@ namespace etl { private: - //template - //static constexpr bool IsMessagePacket = etl::is_same_v< etl::remove_const_t>, etl::message_packet>; + template + static constexpr bool IsMessagePacket = etl::is_same_v>, etl::message_packet>; template static constexpr bool IsInMessageList = false; template - static constexpr bool IsIMessage = etl::is_same_v>, etl::imessage>; + static constexpr bool IsIMessage = etl::is_same_v>, etl::imessage>; public: @@ -418,7 +418,7 @@ namespace etl //******************************************** #include "private/diagnostic_uninitialized_push.h" - message_packet() + constexpr message_packet() noexcept { } #include "private/diagnostic_pop.h" @@ -620,7 +620,7 @@ namespace etl cog.outl(" //********************************************") cog.outl("#include \"private/diagnostic_uninitialized_push.h\"") - cog.outl(" message_packet()") + cog.outl(" ETL_CONSTEXPR message_packet() ETL_NOEXCEPT") cog.outl(" : valid(false)") cog.outl(" {") cog.outl(" }") @@ -934,7 +934,7 @@ namespace etl cog.outl(" //********************************************") cog.outl("#include \"private/diagnostic_uninitialized_push.h\"") - cog.outl(" message_packet()") + cog.outl(" ETL_CONSTEXPR message_packet() ETL_NOEXCEPT") cog.outl(" : valid(false)") cog.outl(" {") cog.outl(" }") @@ -1219,7 +1219,7 @@ namespace etl using message_types = etl::type_list<>; #endif - message_packet() + ETL_CONSTEXPR message_packet() ETL_NOEXCEPT : valid(false) { } diff --git a/include/etl/generators/message_router_generator.h b/include/etl/generators/message_router_generator.h index 1f8e19da..02140088 100644 --- a/include/etl/generators/message_router_generator.h +++ b/include/etl/generators/message_router_generator.h @@ -623,7 +623,7 @@ namespace etl //********************************************** using imessage_router::accepts; - bool accepts(etl::message_id_t /*id*/) const ETL_OVERRIDE + bool accepts(etl::message_id_t id) const ETL_OVERRIDE { if (has_successor()) { diff --git a/include/etl/message_packet.h b/include/etl/message_packet.h index 9c6f5eb1..a097d55c 100644 --- a/include/etl/message_packet.h +++ b/include/etl/message_packet.h @@ -76,13 +76,13 @@ namespace etl private: template - static constexpr bool IsMessagePacket = etl::is_same_v< etl::remove_const_t>, etl::message_packet>; + static constexpr bool IsMessagePacket = etl::is_same_v>, etl::message_packet>; template static constexpr bool IsInMessageList = etl::is_one_of_v>, TMessageTypes...>; template - static constexpr bool IsIMessage = etl::is_same_v>, etl::imessage>; + static constexpr bool IsIMessage = etl::is_same_v>, etl::imessage>; public: @@ -90,7 +90,7 @@ namespace etl //******************************************** #include "private/diagnostic_uninitialized_push.h" - message_packet() + constexpr message_packet() noexcept : valid(false) { } @@ -391,14 +391,14 @@ namespace etl { private: - //template - //static constexpr bool IsMessagePacket = etl::is_same_v< etl::remove_const_t>, etl::message_packet>; + template + static constexpr bool IsMessagePacket = etl::is_same_v>, etl::message_packet>; template static constexpr bool IsInMessageList = false; template - static constexpr bool IsIMessage = etl::is_same_v>, etl::imessage>; + static constexpr bool IsIMessage = etl::is_same_v>, etl::imessage>; public: @@ -406,7 +406,7 @@ namespace etl //******************************************** #include "private/diagnostic_uninitialized_push.h" - message_packet() + constexpr message_packet() noexcept { } #include "private/diagnostic_pop.h" @@ -528,7 +528,7 @@ namespace etl //******************************************** #include "private/diagnostic_uninitialized_push.h" - message_packet() + ETL_CONSTEXPR message_packet() ETL_NOEXCEPT : valid(false) { } @@ -856,7 +856,7 @@ namespace etl //******************************************** #include "private/diagnostic_uninitialized_push.h" - message_packet() + ETL_CONSTEXPR message_packet() ETL_NOEXCEPT : valid(false) { } @@ -1182,7 +1182,7 @@ namespace etl //******************************************** #include "private/diagnostic_uninitialized_push.h" - message_packet() + ETL_CONSTEXPR message_packet() ETL_NOEXCEPT : valid(false) { } @@ -1505,7 +1505,7 @@ namespace etl //******************************************** #include "private/diagnostic_uninitialized_push.h" - message_packet() + ETL_CONSTEXPR message_packet() ETL_NOEXCEPT : valid(false) { } @@ -1824,7 +1824,7 @@ namespace etl //******************************************** #include "private/diagnostic_uninitialized_push.h" - message_packet() + ETL_CONSTEXPR message_packet() ETL_NOEXCEPT : valid(false) { } @@ -2137,7 +2137,7 @@ namespace etl //******************************************** #include "private/diagnostic_uninitialized_push.h" - message_packet() + ETL_CONSTEXPR message_packet() ETL_NOEXCEPT : valid(false) { } @@ -2447,7 +2447,7 @@ namespace etl //******************************************** #include "private/diagnostic_uninitialized_push.h" - message_packet() + ETL_CONSTEXPR message_packet() ETL_NOEXCEPT : valid(false) { } @@ -2754,7 +2754,7 @@ namespace etl //******************************************** #include "private/diagnostic_uninitialized_push.h" - message_packet() + ETL_CONSTEXPR message_packet() ETL_NOEXCEPT : valid(false) { } @@ -3057,7 +3057,7 @@ namespace etl //******************************************** #include "private/diagnostic_uninitialized_push.h" - message_packet() + ETL_CONSTEXPR message_packet() ETL_NOEXCEPT : valid(false) { } @@ -3354,7 +3354,7 @@ namespace etl //******************************************** #include "private/diagnostic_uninitialized_push.h" - message_packet() + ETL_CONSTEXPR message_packet() ETL_NOEXCEPT : valid(false) { } @@ -3648,7 +3648,7 @@ namespace etl //******************************************** #include "private/diagnostic_uninitialized_push.h" - message_packet() + ETL_CONSTEXPR message_packet() ETL_NOEXCEPT : valid(false) { } @@ -3939,7 +3939,7 @@ namespace etl //******************************************** #include "private/diagnostic_uninitialized_push.h" - message_packet() + ETL_CONSTEXPR message_packet() ETL_NOEXCEPT : valid(false) { } @@ -4226,7 +4226,7 @@ namespace etl //******************************************** #include "private/diagnostic_uninitialized_push.h" - message_packet() + ETL_CONSTEXPR message_packet() ETL_NOEXCEPT : valid(false) { } @@ -4507,7 +4507,7 @@ namespace etl //******************************************** #include "private/diagnostic_uninitialized_push.h" - message_packet() + ETL_CONSTEXPR message_packet() ETL_NOEXCEPT : valid(false) { } @@ -4785,7 +4785,7 @@ namespace etl //******************************************** #include "private/diagnostic_uninitialized_push.h" - message_packet() + ETL_CONSTEXPR message_packet() ETL_NOEXCEPT : valid(false) { } @@ -5060,7 +5060,7 @@ namespace etl //******************************************** #include "private/diagnostic_uninitialized_push.h" - message_packet() + ETL_CONSTEXPR message_packet() ETL_NOEXCEPT : valid(false) { } @@ -5331,7 +5331,7 @@ namespace etl using message_types = etl::type_list<>; #endif - message_packet() + ETL_CONSTEXPR message_packet() ETL_NOEXCEPT : valid(false) { } diff --git a/include/etl/message_router.h b/include/etl/message_router.h index 42735ab0..b53d9071 100644 --- a/include/etl/message_router.h +++ b/include/etl/message_router.h @@ -611,7 +611,7 @@ namespace etl //********************************************** using imessage_router::accepts; - bool accepts(etl::message_id_t /*id*/) const ETL_OVERRIDE + bool accepts(etl::message_id_t id) const ETL_OVERRIDE { if (has_successor()) { diff --git a/include/etl/type_list.h b/include/etl/type_list.h index 2d0dcdac..19eddc15 100644 --- a/include/etl/type_list.h +++ b/include/etl/type_list.h @@ -59,6 +59,11 @@ namespace etl template struct is_type_list> : etl::true_type {}; +#if ETL_USING_CPP17 + template + inline constexpr bool is_type_list_v = is_type_list::value; +#endif + //*************************************************************************** /// The empty type list. //*************************************************************************** diff --git a/test/test_message_router.cpp b/test/test_message_router.cpp index a6691297..cfe2e9b1 100644 --- a/test/test_message_router.cpp +++ b/test/test_message_router.cpp @@ -448,31 +448,6 @@ namespace CHECK_EQUAL(1, r1.message4_count); CHECK_EQUAL(0, r1.message_unknown_count); CHECK_EQUAL(4, r2.callback_count); - - //// Send from the null router. - //etl::send_message(r0, message1); - //CHECK_EQUAL(1, r2.message1_count); - //CHECK_EQUAL(0, r2.message2_count); - //CHECK_EQUAL(0, r2.message4_count); - //CHECK_EQUAL(0, r2.message_unknown_count); - - //etl::send_message(r0, message2); - //CHECK_EQUAL(1, r2.message1_count); - //CHECK_EQUAL(1, r2.message2_count); - //CHECK_EQUAL(0, r2.message4_count); - //CHECK_EQUAL(0, r2.message_unknown_count); - - //etl::send_message(r0, message3); - //CHECK_EQUAL(1, r2.message1_count); - //CHECK_EQUAL(1, r2.message2_count); - //CHECK_EQUAL(0, r2.message4_count); - //CHECK_EQUAL(1, r2.message_unknown_count); - - //etl::send_message(r0, message4); - //CHECK_EQUAL(1, r2.message1_count); - //CHECK_EQUAL(1, r2.message2_count); - //CHECK_EQUAL(1, r2.message4_count); - //CHECK_EQUAL(1, r2.message_unknown_count); } //************************************************************************* diff --git a/test/test_type_list.cpp b/test/test_type_list.cpp index cd53981c..b8124dee 100644 --- a/test/test_type_list.cpp +++ b/test/test_type_list.cpp @@ -37,6 +37,24 @@ namespace #if ETL_USING_CPP11 SUITE(test_type_list) { + //************************************************************************* + TEST(test_is_type_list) + { + using t0 = etl::type_list<>; + using t1 = etl::type_list; + using t2 = int; + + CHECK_TRUE((etl::is_type_list::value)); + CHECK_TRUE((etl::is_type_list::value)); + CHECK_FALSE((etl::is_type_list::value)); + +#if ETL_USING_CPP17 + CHECK_TRUE((etl::is_type_list_v)); + CHECK_TRUE((etl::is_type_list_v)); + CHECK_FALSE((etl::is_type_list_v)); +#endif + } + //************************************************************************* TEST(test_type_list_select) { From ca6bbd50d0cf53ab18096e9ae92060cba855e9b3 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 5 Feb 2026 11:01:51 +0000 Subject: [PATCH 146/298] PR review changes --- include/etl/private/variant_variadic.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/etl/private/variant_variadic.h b/include/etl/private/variant_variadic.h index afbf7243..4363ebfa 100644 --- a/include/etl/private/variant_variadic.h +++ b/include/etl/private/variant_variadic.h @@ -1255,7 +1255,7 @@ namespace etl get(etl::variant& v) { #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11) - static_assert(Index < etl::type_list_size>::value, "Index out of range"); + static_assert(Index < sizeof...(TTypes), "Index out of range"); #endif ETL_ASSERT(Index == v.index(), ETL_ERROR(etl::variant_incorrect_type_exception)); @@ -1428,7 +1428,7 @@ namespace etl template struct variant_size> - : etl::integral_constant>::value> + : etl::integral_constant { }; From 6cec4a39712e215e0334ecdd7ae23c46b8359dad Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 5 Feb 2026 11:42:09 +0000 Subject: [PATCH 147/298] Fixed internal constexptr flag in message_packet --- include/etl/generators/message_packet_generator.h | 2 +- include/etl/message_packet.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/etl/generators/message_packet_generator.h b/include/etl/generators/message_packet_generator.h index 354601b9..36430509 100644 --- a/include/etl/generators/message_packet_generator.h +++ b/include/etl/generators/message_packet_generator.h @@ -404,7 +404,7 @@ namespace etl private: template - static constexpr bool IsMessagePacket = etl::is_same_v>, etl::message_packet>; + static constexpr bool IsMessagePacket = etl::is_same_v>, etl::message_packet<>>; template static constexpr bool IsInMessageList = false; diff --git a/include/etl/message_packet.h b/include/etl/message_packet.h index a097d55c..24f1e157 100644 --- a/include/etl/message_packet.h +++ b/include/etl/message_packet.h @@ -392,7 +392,7 @@ namespace etl private: template - static constexpr bool IsMessagePacket = etl::is_same_v>, etl::message_packet>; + static constexpr bool IsMessagePacket = etl::is_same_v>, etl::message_packet<>>; template static constexpr bool IsInMessageList = false; From 82f168c96e2fef66dfc6a772147e1c6a1689fc9f Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 5 Feb 2026 20:57:54 +0000 Subject: [PATCH 148/298] Fixed unused variable in unti test --- test/test_message_packet.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/test/test_message_packet.cpp b/test/test_message_packet.cpp index 51b0712d..b28191fa 100644 --- a/test/test_message_packet.cpp +++ b/test/test_message_packet.cpp @@ -235,7 +235,6 @@ namespace #else Packet packet3(message3); #endif - NullPacket null_packet; // Should cause a static assert. //Packet packet4(message4); From 2a79845dd5f78043135bbfec3bc09da781d8f636 Mon Sep 17 00:00:00 2001 From: Drew Rife Date: Fri, 6 Feb 2026 04:32:54 -0500 Subject: [PATCH 149/298] Add ref-qualifiers to basic_format_spec (#1292) * Remove AppVeyor build status badge Removed AppVeyor build status badge from README. * Update README.md * Update CONTRIBUTING.md Updated the instructions for contributing. * Fix for issue 1276 "Data corruption in the etl::bip_buffer_spsc_atomic" (#1277) * Reproduce data corruption bug in the `etl::bip_buffer_spsc_atomic`. * Fix data corruption bug in the `etl::bip_buffer_spsc_atomic`. * feat: use ref-qualifiers for basic_format_spec Converted the l-value methods to ref-qualified and also added r-value ref-qualified methods. --------- Co-authored-by: John Wellbelove Co-authored-by: Sergei --- include/etl/basic_format_spec.h | 177 ++++++++++++++++++++++++++------ include/etl/platform.h | 2 + test/test_format_spec.cpp | 87 ++++++++++++++++ 3 files changed, 232 insertions(+), 34 deletions(-) diff --git a/include/etl/basic_format_spec.h b/include/etl/basic_format_spec.h index 36c2d74c..c374e35f 100644 --- a/include/etl/basic_format_spec.h +++ b/include/etl/basic_format_spec.h @@ -36,6 +36,7 @@ SOFTWARE. #include "platform.h" #include "type_traits.h" #include "static_assert.h" +#include "utility.h" namespace etl { @@ -206,7 +207,7 @@ namespace etl //*************************************************************************** /// Default constructor. //*************************************************************************** - ETL_CONSTEXPR basic_format_spec() + ETL_CONSTEXPR basic_format_spec() ETL_NOEXCEPT : base_(10U) , width_(0U) , precision_(0U) @@ -228,7 +229,7 @@ namespace etl bool left_justified__, bool boolalpha__, bool show_base__, - typename TString::value_type fill__) + typename TString::value_type fill__) ETL_NOEXCEPT : base_(base__) , width_(width__) , precision_(precision__) @@ -243,7 +244,7 @@ namespace etl //*************************************************************************** /// Clears the format spec back to default. //*************************************************************************** - ETL_CONSTEXPR14 void clear() + ETL_CONSTEXPR14 void clear() ETL_NOEXCEPT { base_ = 10U; width_ = 0U; @@ -259,56 +260,93 @@ namespace etl /// Sets the base. /// \return A reference to the basic_format_spec. //*************************************************************************** - ETL_CONSTEXPR14 basic_format_spec& base(uint32_t b) + ETL_CONSTEXPR14 basic_format_spec& base(uint32_t b) ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT { base_ = static_cast(b); return *this; } +#if ETL_USING_CPP11 + /// @overload + ETL_CONSTEXPR14 basic_format_spec&& base(uint32_t b) ETL_RVALUE_REF_QUALIFIER ETL_NOEXCEPT + { + base_ = static_cast(b); + return etl::move(*this); + } +#endif + //*************************************************************************** /// Sets the base to binary. /// \return A reference to the basic_format_spec. //*************************************************************************** - ETL_CONSTEXPR14 basic_format_spec& binary() + ETL_CONSTEXPR14 basic_format_spec& binary() ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT { - base(2); - return *this; + return base(2); } +#if ETL_USING_CPP11 + /// @overload + ETL_CONSTEXPR14 basic_format_spec&& binary() ETL_RVALUE_REF_QUALIFIER ETL_NOEXCEPT + { + return etl::move(base(2)); + } +#endif + //*************************************************************************** /// Sets the base to octal. /// \return A reference to the basic_format_spec. //*************************************************************************** - ETL_CONSTEXPR14 basic_format_spec& octal() + ETL_CONSTEXPR14 basic_format_spec& octal() ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT { - base(8); - return *this; + return base(8); } +#if ETL_USING_CPP11 + /// @overload + ETL_CONSTEXPR14 basic_format_spec&& octal() ETL_RVALUE_REF_QUALIFIER ETL_NOEXCEPT + { + return etl::move(base(8)); + } +#endif + //*************************************************************************** /// Sets the base to decimal. /// \return A reference to the basic_format_spec. //*************************************************************************** - ETL_CONSTEXPR14 basic_format_spec& decimal() + ETL_CONSTEXPR14 basic_format_spec& decimal() ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT { - base(10); - return *this; + return base(10); } +#if ETL_USING_CPP11 + /// @overload + ETL_CONSTEXPR14 basic_format_spec&& decimal() ETL_RVALUE_REF_QUALIFIER ETL_NOEXCEPT + { + return etl::move(base(10)); + } +#endif + //*************************************************************************** /// Sets the base to hex. /// \return A reference to the basic_format_spec. //*************************************************************************** - ETL_CONSTEXPR14 basic_format_spec& hex() + ETL_CONSTEXPR14 basic_format_spec& hex() ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT { - base(16); - return *this; + return base(16); } +#if ETL_USING_CPP11 + /// @overload + ETL_CONSTEXPR14 basic_format_spec&& hex() ETL_RVALUE_REF_QUALIFIER ETL_NOEXCEPT + { + return etl::move(base(16)); + } +#endif + //*************************************************************************** /// Gets the base. //*************************************************************************** - ETL_CONSTEXPR uint32_t get_base() const + ETL_CONSTEXPR uint32_t get_base() const ETL_NOEXCEPT { return base_; } @@ -317,16 +355,25 @@ namespace etl /// Sets the show base flag. /// \return A reference to the basic_format_spec. //*************************************************************************** - ETL_CONSTEXPR14 basic_format_spec& show_base(bool b) + ETL_CONSTEXPR14 basic_format_spec& show_base(bool b) ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT { show_base_ = b; return *this; } +#if ETL_USING_CPP11 + /// @overload + ETL_CONSTEXPR14 basic_format_spec&& show_base(bool b) ETL_RVALUE_REF_QUALIFIER ETL_NOEXCEPT + { + show_base_ = b; + return etl::move(*this); + } +#endif + //*************************************************************************** /// Gets the show base flag. //*************************************************************************** - ETL_CONSTEXPR bool is_show_base() const + ETL_CONSTEXPR bool is_show_base() const ETL_NOEXCEPT { return show_base_; } @@ -335,16 +382,25 @@ namespace etl /// Sets the width. /// \return A reference to the basic_format_spec. //*************************************************************************** - ETL_CONSTEXPR14 basic_format_spec& width(uint32_t w) + ETL_CONSTEXPR14 basic_format_spec& width(uint32_t w) ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT { width_ = static_cast(w); return *this; } +#if ETL_USING_CPP11 + /// @overload + ETL_CONSTEXPR14 basic_format_spec&& width(uint32_t w) ETL_RVALUE_REF_QUALIFIER ETL_NOEXCEPT + { + width_ = static_cast(w); + return etl::move(*this); + } +#endif + //*************************************************************************** /// Gets the width. //*************************************************************************** - ETL_CONSTEXPR uint32_t get_width() const + ETL_CONSTEXPR uint32_t get_width() const ETL_NOEXCEPT { return width_; } @@ -353,16 +409,25 @@ namespace etl /// Sets the precision. /// \return A reference to the basic_format_spec. //*************************************************************************** - ETL_CONSTEXPR14 basic_format_spec& precision(uint32_t p) + ETL_CONSTEXPR14 basic_format_spec& precision(uint32_t p) ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT { precision_ = static_cast(p); return *this; } +#if ETL_USING_CPP11 + /// @overload + ETL_CONSTEXPR14 basic_format_spec&& precision(uint32_t p) ETL_RVALUE_REF_QUALIFIER ETL_NOEXCEPT + { + precision_ = static_cast(p); + return etl::move(*this); + } +#endif + //*************************************************************************** /// Gets the precision. //*************************************************************************** - ETL_CONSTEXPR uint32_t get_precision() const + ETL_CONSTEXPR uint32_t get_precision() const ETL_NOEXCEPT { return precision_; } @@ -371,16 +436,25 @@ namespace etl /// Sets the upper case flag. /// \return A reference to the basic_format_spec. //*************************************************************************** - ETL_CONSTEXPR14 basic_format_spec& upper_case(bool u) + ETL_CONSTEXPR14 basic_format_spec& upper_case(bool u) ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT { upper_case_ = u; return *this; } +#if ETL_USING_CPP11 + /// @overload + ETL_CONSTEXPR14 basic_format_spec&& upper_case(bool u) ETL_RVALUE_REF_QUALIFIER ETL_NOEXCEPT + { + upper_case_ = u; + return etl::move(*this); + } +#endif + //*************************************************************************** /// Gets the upper case flag. //*************************************************************************** - ETL_CONSTEXPR bool is_upper_case() const + ETL_CONSTEXPR bool is_upper_case() const ETL_NOEXCEPT { return upper_case_; } @@ -389,16 +463,25 @@ namespace etl /// Sets the fill character. /// \return A reference to the basic_format_spec. //*************************************************************************** - ETL_CONSTEXPR14 basic_format_spec& fill(typename TString::value_type c) + ETL_CONSTEXPR14 basic_format_spec& fill(typename TString::value_type c) ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT { fill_ = c; return *this; } +#if ETL_USING_CPP11 + /// @overload + ETL_CONSTEXPR14 basic_format_spec&& fill(typename TString::value_type c) ETL_RVALUE_REF_QUALIFIER ETL_NOEXCEPT + { + fill_ = c; + return etl::move(*this); + } +#endif + //*************************************************************************** /// Gets the fill character. //*************************************************************************** - ETL_CONSTEXPR typename TString::value_type get_fill() const + ETL_CONSTEXPR typename TString::value_type get_fill() const ETL_NOEXCEPT { return fill_; } @@ -407,16 +490,25 @@ namespace etl /// Sets the left justify flag. /// \return A reference to the basic_format_spec. //*************************************************************************** - ETL_CONSTEXPR14 basic_format_spec& left() + ETL_CONSTEXPR14 basic_format_spec& left() ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT { left_justified_ = true; return *this; } +#if ETL_USING_CPP11 + /// @overload + ETL_CONSTEXPR14 basic_format_spec&& left() ETL_RVALUE_REF_QUALIFIER ETL_NOEXCEPT + { + left_justified_ = true; + return etl::move(*this); + } +#endif + //*************************************************************************** /// Gets the left justify flag. //*************************************************************************** - ETL_CONSTEXPR bool is_left() const + ETL_CONSTEXPR bool is_left() const ETL_NOEXCEPT { return left_justified_; } @@ -425,16 +517,25 @@ namespace etl /// Sets the right justify flag. /// \return A reference to the basic_format_spec. //*************************************************************************** - ETL_CONSTEXPR14 basic_format_spec& right() + ETL_CONSTEXPR14 basic_format_spec& right() ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT { left_justified_ = false; return *this; } +#if ETL_USING_CPP11 + /// @overload + ETL_CONSTEXPR14 basic_format_spec&& right() ETL_RVALUE_REF_QUALIFIER ETL_NOEXCEPT + { + left_justified_ = false; + return etl::move(*this); + } +#endif + //*************************************************************************** /// Gets the right justify flag. //*************************************************************************** - ETL_CONSTEXPR bool is_right() const + ETL_CONSTEXPR bool is_right() const ETL_NOEXCEPT { return !left_justified_; } @@ -443,16 +544,25 @@ namespace etl /// Sets the bool alpha flag. /// \return A reference to the basic_format_spec. //*************************************************************************** - ETL_CONSTEXPR14 basic_format_spec& boolalpha(bool b) + ETL_CONSTEXPR14 basic_format_spec& boolalpha(bool b) ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT { boolalpha_ = b; return *this; } +#if ETL_USING_CPP11 + /// @overload + ETL_CONSTEXPR14 basic_format_spec&& boolalpha(bool b) ETL_RVALUE_REF_QUALIFIER ETL_NOEXCEPT + { + boolalpha_ = b; + return etl::move(*this); + } +#endif + //*************************************************************************** /// Gets the boolalpha flag. //*************************************************************************** - ETL_CONSTEXPR bool is_boolalpha() const + ETL_CONSTEXPR bool is_boolalpha() const ETL_NOEXCEPT { return boolalpha_; } @@ -481,7 +591,6 @@ namespace etl } private: - uint_least8_t base_; uint_least8_t width_; uint_least8_t precision_; diff --git a/include/etl/platform.h b/include/etl/platform.h index 116daeb4..6db7c305 100644 --- a/include/etl/platform.h +++ b/include/etl/platform.h @@ -368,6 +368,7 @@ SOFTWARE. #define ETL_ENUM_CLASS(name) enum class name #define ETL_ENUM_CLASS_TYPE(name, type) enum class name : type #define ETL_LVALUE_REF_QUALIFIER & + #define ETL_RVALUE_REF_QUALIFIER && #if ETL_USING_EXCEPTIONS #define ETL_NOEXCEPT noexcept #define ETL_NOEXCEPT_EXPR(...) noexcept(__VA_ARGS__) @@ -393,6 +394,7 @@ SOFTWARE. #define ETL_ENUM_CLASS(name) enum name #define ETL_ENUM_CLASS_TYPE(name, type) enum name #define ETL_LVALUE_REF_QUALIFIER + #define ETL_RVALUE_REF_QUALIFIER #endif //************************************* diff --git a/test/test_format_spec.cpp b/test/test_format_spec.cpp index 57eb0841..d242dd79 100644 --- a/test/test_format_spec.cpp +++ b/test/test_format_spec.cpp @@ -91,6 +91,93 @@ namespace CHECK_EQUAL(true, format.is_upper_case()); } + //************************************************************************* +#if ETL_USING_CPP11 + TEST(test_format_rvalue_ref_qualifiers) + { + // Test chaining on temporary (rvalue) + auto format = etl::format_spec() + .base(16) + .boolalpha(true) + .fill('*') + .left() + .precision(3) + .show_base(true) + .upper_case(true) + .width(8); + + CHECK_EQUAL(16, format.get_base()); + CHECK_EQUAL('*', format.get_fill()); + CHECK_EQUAL(3, format.get_precision()); + CHECK_EQUAL(8, format.get_width()); + CHECK_EQUAL(true, format.is_boolalpha()); + CHECK_EQUAL(true, format.is_left()); + CHECK_EQUAL(false, format.is_right()); + CHECK_EQUAL(true, format.is_show_base()); + CHECK_EQUAL(true, format.is_upper_case()); + } + + //************************************************************************* + TEST(test_format_lvalue_ref_qualifiers) + { + // Test chaining on lvalue + etl::format_spec format; + + format.hex().boolalpha(true).fill('#').right().precision(5).show_base(false).upper_case(false).width(12); + + CHECK_EQUAL(16, format.get_base()); + CHECK_EQUAL('#', format.get_fill()); + CHECK_EQUAL(5, format.get_precision()); + CHECK_EQUAL(12, format.get_width()); + CHECK_EQUAL(true, format.is_boolalpha()); + CHECK_EQUAL(false, format.is_left()); + CHECK_EQUAL(true, format.is_right()); + CHECK_EQUAL(false, format.is_show_base()); + CHECK_EQUAL(false, format.is_upper_case()); + } + + //************************************************************************* + TEST(test_format_base_methods) + { + // Test binary + auto format_bin = etl::format_spec().binary().width(8).fill('0'); + CHECK_EQUAL(2, format_bin.get_base()); + CHECK_EQUAL(8, format_bin.get_width()); + CHECK_EQUAL('0', format_bin.get_fill()); + + // Test octal + auto format_oct = etl::format_spec().octal().width(6); + CHECK_EQUAL(8, format_oct.get_base()); + CHECK_EQUAL(6, format_oct.get_width()); + + // Test decimal + auto format_dec = etl::format_spec().decimal().precision(2); + CHECK_EQUAL(10, format_dec.get_base()); + CHECK_EQUAL(2, format_dec.get_precision()); + + // Test hex + auto format_hex = etl::format_spec().hex().upper_case(true); + CHECK_EQUAL(16, format_hex.get_base()); + CHECK_EQUAL(true, format_hex.is_upper_case()); + } + + //************************************************************************* + TEST(test_format_mixed_lvalue_rvalue) + { + // Create as rvalue, then use as lvalue + auto format = etl::format_spec().hex().width(8); + + // Continue chaining on lvalue + format.fill('0').upper_case(true).show_base(true); + + CHECK_EQUAL(16, format.get_base()); + CHECK_EQUAL('0', format.get_fill()); + CHECK_EQUAL(8, format.get_width()); + CHECK_EQUAL(true, format.is_upper_case()); + CHECK_EQUAL(true, format.is_show_base()); + } +#endif + //************************************************************************* #if ETL_USING_CPP14 TEST(test_format_constexpr) From 10fd81c2be8de595bf5ba326359c1c20484f4b64 Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Fri, 6 Feb 2026 11:08:17 +0100 Subject: [PATCH 150/298] Add support for size_t and unsigned long to etl::format (#1290) * Remove AppVeyor build status badge Removed AppVeyor build status badge from README. * Update README.md * Update CONTRIBUTING.md Updated the instructions for contributing. * Fix for issue 1276 "Data corruption in the etl::bip_buffer_spsc_atomic" (#1277) * Reproduce data corruption bug in the `etl::bip_buffer_spsc_atomic`. * Fix data corruption bug in the `etl::bip_buffer_spsc_atomic`. * Add support for size_t and unsigned long to etl::format * Document list of supported types in etl::supported_format_types * Add further types and tests for etl::format --------- Co-authored-by: John Wellbelove Co-authored-by: Sergei --- include/etl/format.h | 40 ++++++++++++- test/test_format.cpp | 138 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 175 insertions(+), 3 deletions(-) diff --git a/include/etl/format.h b/include/etl/format.h index 95dafc8d..3268f43b 100644 --- a/include/etl/format.h +++ b/include/etl/format.h @@ -123,7 +123,13 @@ namespace etl template using format_string = basic_format_string...>; - // supported types to format + // Supported types to format + // + // This is the limited number of types as defined in std::basic_format_arg + // https://en.cppreference.com/w/cpp/utility/format/basic_format_arg.html + // + // Further types to be supported are added via converting constructors in + // etl::basic_format_arg using supported_format_types = etl::variant< etl::monostate, bool, @@ -239,6 +245,21 @@ namespace etl { } + basic_format_arg(const short v) + : data(static_cast(v)) + { + } + + basic_format_arg(const unsigned short v) + : data(static_cast(v)) + { + } + + basic_format_arg(const long int v) + : data(static_cast(v)) + { + } + basic_format_arg(const unsigned int v) : data(v) { @@ -254,6 +275,13 @@ namespace etl { } + // Additional type to list of basic types as defined for std::basic_format_arg: + // Mapping unsigned long to unsigned long long int + basic_format_arg(const unsigned long v) + : data(static_cast(v)) + { + } + basic_format_arg(const char* v) : data(v) { @@ -264,6 +292,16 @@ namespace etl { } + basic_format_arg(const signed char v) + : data(static_cast(v)) + { + } + + basic_format_arg(const unsigned char v) + : data(static_cast(v)) + { + } + basic_format_arg(const float v) : data(v) { diff --git a/test/test_format.cpp b/test/test_format.cpp index 2e148bb4..a6c25eab 100644 --- a/test/test_format.cpp +++ b/test/test_format.cpp @@ -86,6 +86,62 @@ namespace CHECK_EQUAL("-1", test_format(s, "{}", -1)); } + //************************************************************************* + TEST(test_format_short) + { + etl::string<100> s; + + CHECK_EQUAL("1", test_format(s, "{}", static_cast(1))); + CHECK_EQUAL("123", test_format(s, "{}", static_cast(123))); + CHECK_EQUAL("4123", test_format(s, "{}", static_cast(4123))); + CHECK_EQUAL("1 2", test_format(s, "{} {}", static_cast(1), static_cast(2))); + CHECK_EQUAL("-123", test_format(s, "{}", static_cast(-123))); + CHECK_EQUAL("0", test_format(s, "{}", static_cast(0))); + CHECK_EQUAL("-1", test_format(s, "{}", static_cast(-1))); + } + + //************************************************************************* + TEST(test_format_unsigned_short) + { + etl::string<100> s; + + CHECK_EQUAL("1", test_format(s, "{}", static_cast(1))); + CHECK_EQUAL("123", test_format(s, "{}", static_cast(123))); + CHECK_EQUAL("4123", test_format(s, "{}", static_cast(4123))); + CHECK_EQUAL("1 2", test_format(s, "{} {}", static_cast(1), static_cast(2))); + CHECK_EQUAL("60123", test_format(s, "{}", static_cast(60123))); + CHECK_EQUAL("0", test_format(s, "{}", static_cast(0))); + CHECK_EQUAL("65500", test_format(s, "{}", static_cast(65500))); + } + + //************************************************************************* + TEST(test_format_long_int) + { + etl::string<100> s; + + CHECK_EQUAL("1", test_format(s, "{}", static_cast(1))); + CHECK_EQUAL("123", test_format(s, "{}", static_cast(123))); + CHECK_EQUAL("4123", test_format(s, "{}", static_cast(4123))); + CHECK_EQUAL("1 2", test_format(s, "{} {}", static_cast(1), static_cast(2))); + CHECK_EQUAL("-123", test_format(s, "{}", static_cast(-123))); + CHECK_EQUAL("0", test_format(s, "{}", static_cast(0))); + CHECK_EQUAL("-1", test_format(s, "{}", static_cast(-1))); + } + + //************************************************************************* + TEST(test_format_unsigned_long_int) + { + etl::string<100> s; + + CHECK_EQUAL("1", test_format(s, "{}", static_cast(1))); + CHECK_EQUAL("123", test_format(s, "{}", static_cast(123))); + CHECK_EQUAL("4123", test_format(s, "{}", static_cast(4123))); + CHECK_EQUAL("1 2", test_format(s, "{} {}", static_cast(1), static_cast(2))); + CHECK_EQUAL("60123", test_format(s, "{}", static_cast(60123))); + CHECK_EQUAL("0", test_format(s, "{}", static_cast(0))); + CHECK_EQUAL("65500", test_format(s, "{}", static_cast(65500))); + } + //************************************************************************* TEST(test_format_unsigned_int) { @@ -131,8 +187,10 @@ namespace { etl::string<100> s; - CHECK_EQUAL("34", test_format(s, "{}", static_cast(34))); - CHECK_EQUAL("-14", test_format(s, "{}", static_cast(-14))); + // mapped to unsigned char + //CHECK_EQUAL("34", test_format(s, "{}", static_cast(34))); + // mapped to signed char + //CHECK_EQUAL("-14", test_format(s, "{}", static_cast(-14))); CHECK_EQUAL("6534", test_format(s, "{}", static_cast(6534))); CHECK_EQUAL("-9414", test_format(s, "{}", static_cast(-9414))); CHECK_EQUAL("236534", test_format(s, "{}", static_cast(236534))); @@ -398,6 +456,82 @@ namespace } } + //************************************************************************* + TEST(test_format_size_t) + { + etl::string<100> s; + + CHECK_EQUAL("0", test_format(s, "{}", static_cast(0LL))); + CHECK_EQUAL("1", test_format(s, "{}", static_cast(1LL))); + CHECK_EQUAL("12345678", test_format(s, "{}", static_cast(12345678LL))); + CHECK_EQUAL("4123456780", test_format(s, "{}", static_cast(4123456780LL))); +#if ETL_PLATFORM_64BIT + static_assert(sizeof(size_t) == 8, "size_t is expected to be 64 bit on 64 bit platforms"); + CHECK_EQUAL("18446744073709551615", test_format(s, "{}", static_cast(18446744073709551615ULL))); + CHECK_EQUAL("1311768467463790320", test_format(s, "{}", static_cast(0x123456789ABCDEF0ULL))); +#endif + } + + //************************************************************************* + TEST(test_format_unsigned_long) + { + etl::string<100> s; + + CHECK_EQUAL("0", test_format(s, "{}", static_cast(0LL))); + CHECK_EQUAL("1", test_format(s, "{}", static_cast(1LL))); + CHECK_EQUAL("12345678", test_format(s, "{}", static_cast(12345678LL))); + CHECK_EQUAL("4123456780", test_format(s, "{}", static_cast(4123456780LL))); +#if ETL_PLATFORM_64BIT + static_assert(sizeof(unsigned long) == 8, "size_t is expected to be 64 bit on 64 bit platforms"); + CHECK_EQUAL("18446744073709551615", test_format(s, "{}", static_cast(18446744073709551615ULL))); + CHECK_EQUAL("1311768467463790320", test_format(s, "{}", static_cast(0x123456789ABCDEF0ULL))); +#endif + } + + //************************************************************************* + TEST(test_format_signed_char) + { + etl::string<100> s; + + CHECK_EQUAL("a s b", test_format(s, "a {} b", static_cast('s'))); + CHECK_EQUAL("a s b", test_format(s, "a {:c} b", static_cast('s'))); + CHECK_EQUAL("a 's' b", test_format(s, "a {:?} b", static_cast('s'))); + CHECK_EQUAL("a \t b", test_format(s, "a {} b", static_cast('\t'))); + CHECK_EQUAL("a '\\t' b", test_format(s, "a {:?} b", static_cast('\t'))); + CHECK_EQUAL("a '\\n' b", test_format(s, "a {:?} b", static_cast('\n'))); + CHECK_EQUAL("a '\\r' b", test_format(s, "a {:?} b", static_cast('\r'))); + CHECK_EQUAL("a '\\\"' b", test_format(s, "a {:?} b", static_cast('"'))); + CHECK_EQUAL("a '\\'' b", test_format(s, "a {:?} b", static_cast('\''))); + CHECK_EQUAL("a '\\\\' b", test_format(s, "a {:?} b", static_cast('\\'))); + CHECK_EQUAL("a '\\\\' b", test_format(s, "a {:?} b", static_cast('\\'))); + CHECK_EQUAL("a 97 b", test_format(s, "a {:d} b", static_cast('a'))); + CHECK_EQUAL("a 61 b", test_format(s, "a {:X} b", static_cast('a'))); + CHECK_EQUAL("a 61 b", test_format(s, "a {:x} b", static_cast('a'))); + CHECK_EQUAL("a 0x61 b", test_format(s, "a {:#x} b", static_cast('a'))); + } + + //************************************************************************* + TEST(test_format_unsigned_char) + { + etl::string<100> s; + + CHECK_EQUAL("a s b", test_format(s, "a {} b", static_cast('s'))); + CHECK_EQUAL("a s b", test_format(s, "a {:c} b", static_cast('s'))); + CHECK_EQUAL("a 's' b", test_format(s, "a {:?} b", static_cast('s'))); + CHECK_EQUAL("a \t b", test_format(s, "a {} b", static_cast('\t'))); + CHECK_EQUAL("a '\\t' b", test_format(s, "a {:?} b", static_cast('\t'))); + CHECK_EQUAL("a '\\n' b", test_format(s, "a {:?} b", static_cast('\n'))); + CHECK_EQUAL("a '\\r' b", test_format(s, "a {:?} b", static_cast('\r'))); + CHECK_EQUAL("a '\\\"' b", test_format(s, "a {:?} b", static_cast('"'))); + CHECK_EQUAL("a '\\'' b", test_format(s, "a {:?} b", static_cast('\''))); + CHECK_EQUAL("a '\\\\' b", test_format(s, "a {:?} b", static_cast('\\'))); + CHECK_EQUAL("a '\\\\' b", test_format(s, "a {:?} b", static_cast('\\'))); + CHECK_EQUAL("a 97 b", test_format(s, "a {:d} b", static_cast('a'))); + CHECK_EQUAL("a 61 b", test_format(s, "a {:X} b", static_cast('a'))); + CHECK_EQUAL("a 61 b", test_format(s, "a {:x} b", static_cast('a'))); + CHECK_EQUAL("a 0x61 b", test_format(s, "a {:#x} b", static_cast('a'))); + } + //************************************************************************* TEST(test_format_limit) { From fe1f19ce4dc6b763b4190049043c204e46e15030 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 8 Feb 2026 10:42:03 +0000 Subject: [PATCH 151/298] Added new type_list features Added make_index_sequence_with_offset --- include/etl/type_list.h | 273 +++++++++++++++++++++++++++++++++++++++- include/etl/utility.h | 17 +++ test/test_type_list.cpp | 119 ++++++++++++++++++ 3 files changed, 404 insertions(+), 5 deletions(-) diff --git a/include/etl/type_list.h b/include/etl/type_list.h index 19eddc15..667e2a06 100644 --- a/include/etl/type_list.h +++ b/include/etl/type_list.h @@ -48,11 +48,14 @@ namespace etl static ETL_CONSTANT size_t type_list_npos = etl::integral_limits::max; //*************************************************************************** - /// Type list forward declaration. + // Type list forward declaration. //*************************************************************************** template struct type_list; + //*************************************************************************** + /// Check if a type is an etl::type_list. + //*************************************************************************** template struct is_type_list : etl::false_type {}; @@ -154,8 +157,8 @@ namespace etl template struct type_list_type_at_index { - ETL_STATIC_ASSERT(Index < type_list_size::value, "etl::type_list_type_at_index out of range"); - ETL_STATIC_ASSERT((etl::is_base_of, TTypeList>::value), "TTypeList must be an etl::type_list"); + ETL_STATIC_ASSERT(Index < type_list_size::value, "etl::type_list_type_at_index out of range"); + ETL_STATIC_ASSERT((etl::is_type_list::value), "TTypeList must be an etl::type_list"); using type = typename type_list_type_at_index::type; }; @@ -163,6 +166,8 @@ namespace etl template struct type_list_type_at_index { + ETL_STATIC_ASSERT((etl::is_type_list::value), "TTypeList must be an etl::type_list"); + using type = typename TTypeList::head; }; @@ -179,7 +184,7 @@ namespace etl (type_list_index_of_type::value == etl::type_list_npos ? etl::type_list_npos : type_list_index_of_type::value + 1)> { - ETL_STATIC_ASSERT((etl::is_base_of, TTypeList>::value), "TTypeList must be an etl::type_list"); + ETL_STATIC_ASSERT((etl::is_type_list::value), "TTypeList must be an etl::type_list"); }; template @@ -316,7 +321,7 @@ namespace etl template struct type_list_select { - ETL_STATIC_ASSERT((etl::is_base_of, TTypeList>::value), "TTypeList must be an etl::type_list"); + ETL_STATIC_ASSERT((etl::is_type_list::value), "TTypeList must be an etl::type_list"); using type = type_list...>; }; @@ -324,6 +329,23 @@ namespace etl template using type_list_select_t = typename type_list_select::type; + //*************************************************************************** + /// Declares a new type_list by selecting types from a given type_list, according to an index sequence. + //*************************************************************************** + template + struct type_list_select_from_sequence; + + template + struct type_list_select_from_sequence> + { + using type = etl::type_list_select_t; + }; + +#if ETL_USING_CPP11 + template + using type_list_select_from_sequence_t = typename type_list_select_from_sequence::type; +#endif + //*************************************************************************** /// Concatenates two or more type_lists. //*************************************************************************** @@ -345,6 +367,78 @@ namespace etl template using type_list_cat_t = typename type_list_cat::type; + //*************************************************************************** + /// Prepend a type to a type_list. + //*************************************************************************** + template + struct type_list_prepend; + + template + struct type_list_prepend, T> + { + using type = type_list; + }; + + template + struct type_list_prepend + { + using type = etl::type_list; + }; + + template + using type_list_prepend_t = typename type_list_prepend::type; + + //*************************************************************************** + /// Append a type to a type_list. + //*************************************************************************** + template + struct type_list_append; + + template + struct type_list_append, T> + { + using type = type_list; + }; + + template + struct type_list_append + { + using type = etl::type_list; + }; + + template + using type_list_append_t = typename type_list_append::type; + + //*************************************************************************** + /// Insert a type at an index in a type_list. + /// Inserts before the type currently at Index. + /// If Index == size of the type_list, the type is appended. + //*************************************************************************** + template + struct type_list_insert + { + private: + + ETL_STATIC_ASSERT((etl::is_type_list::value), "TTypeList must be an etl::type_list"); + ETL_STATIC_ASSERT(Index <= etl::type_list_size::value, "Index out of range"); + + using index_sequence_for_prefix = etl::make_index_sequence; + using index_sequence_for_suffix = etl::make_index_sequence_with_offset::value - Index>; + + using prefix = etl::type_list_select_from_sequence_t; + using suffix = etl::type_list_select_from_sequence_t; + + public: + + // Concatenate the prefix, new type, and suffix to create the new type list with T inserted at the correct position. + using type = etl::type_list_cat_t, suffix>; + }; + +#if ETL_USING_CPP11 + template + using type_list_insert_t = typename etl::type_list_insert::type; +#endif + //*************************************************************************** /// Checks that two type lists are convertible. /// Static asserts if the type lists are not the same length. @@ -373,6 +467,175 @@ namespace etl template inline constexpr bool type_lists_are_convertible_v = etl::type_lists_are_convertible::value; #endif + + namespace private_type_list + { + //********************************* + template class TCompare> + struct type_list_is_sorted_impl; + + //********************************* + // Empty list is sorted + template