From 9c046b710c7b3ec51bbb6cb3991da0c376e77ff2 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Fri, 15 Aug 2025 10:27:35 +0100 Subject: [PATCH 01/22] Initial implementation --- include/etl/not_null.h | 188 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 include/etl/not_null.h diff --git a/include/etl/not_null.h b/include/etl/not_null.h new file mode 100644 index 00000000..941a3ec8 --- /dev/null +++ b/include/etl/not_null.h @@ -0,0 +1,188 @@ +///\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_NOT_NULL_INCLUDED +#define ETL_NOT_NULL_INCLUDED + +#include "platform.h" +#include "error_handler.h" +#include "exception.h" +#include "ETL_STATIC_ASSERT.h" +#include "unique_ptr.h" +#include "type_traits.h" + +namespace etl +{ + //*************************************************************************** + /// The base class for not_null exceptions. + //*************************************************************************** + class not_null_exception : public exception + { + public: + + not_null_exception(string_type reason_, string_type file_name_, numeric_type line_number_) + : exception(reason_, file_name_, line_number_) + { + } + }; + + //*************************************************************************** + /// The exception when the not_null contains a null. + //*************************************************************************** + class not_null_contains_null : public not_null_exception + { + public: + + not_null_contains_null(string_type file_name_, numeric_type line_number_) + : delegate_exception(ETL_ERROR_TEXT("not_null:contains null", ETL_NOT_NULL_FILE_ID"A"), file_name_, line_number_) + { + } + }; + + // Primary template + template + class not_null; + + // Specialisation for T* + template + class not_null + { + public: + + explicit not_null(T* ptr_) + : ptr(ptr_) + { + ETL_ASSERT(ptr != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); + } + + not_null(const etl::not_null& other) + : ptr(other.get()) + { + } + + not_null& operator =(const etl::not_null& other) + { + ptr = other.get(); + + return *this; + } + + not_null& operator =(T* ptr_) + { + ETL_ASSERT(ptr_ != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); + + ptr = ptr_; + + return *this; + } + + T* get() const + { + return ptr; + } + + operator T*() const + { + return ptr; + } + + typename etl::remove_pointer::type& operator*() const + { + return *ptr; + } + + T operator->() const + { + return ptr; + } + + private: + + T* ptr; + }; + + // Partial specialisation for etl::unique_ptr + template + class not_null> + { + public: + + explicit not_null(etl::unique_ptr&& ptr_) + : ptr(etl::move(ptr_)) + { + ETL_ASSERT(ptr != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); + } + +#if ETL_USING_CPP11 + not_null& operator =(etl::unique_ptr&& ptr_) + { + ETL_ASSERT(ptr_ != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); + + ptr = etl::move(ptr_); + + return *this; + } +#endif + + T* get() const + { + return ptr.get(); + } + + operator T*() const + { + return ptr.get(); + } + + T& operator*() const + { + return *ptr; + } + + T* operator->() const + { + return ptr.get(); + } + + etl::unique_ptr& unique() + { + return ptr; + } + + const etl::unique_ptr& unique() const + { + return ptr; + } + + private: + + etl::unique_ptr ptr; + }; +} From 20f5c0402e5fc54e9e02261036307a96a1b12e75 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Fri, 15 Aug 2025 17:18:15 +0100 Subject: [PATCH 02/22] Initial implementation --- include/etl/not_null.h | 226 ++++++++++++++++++-------- test/test_not_null_pointer.cpp | 152 +++++++++++++++++ test/test_not_null_unique_pointer.cpp | 174 ++++++++++++++++++++ test/vs2022/etl.vcxproj | 2 + test/vs2022/etl.vcxproj.filters | 6 + 5 files changed, 491 insertions(+), 69 deletions(-) create mode 100644 test/test_not_null_pointer.cpp create mode 100644 test/test_not_null_unique_pointer.cpp diff --git a/include/etl/not_null.h b/include/etl/not_null.h index 941a3ec8..54a4f565 100644 --- a/include/etl/not_null.h +++ b/include/etl/not_null.h @@ -34,8 +34,8 @@ SOFTWARE. #include "platform.h" #include "error_handler.h" #include "exception.h" -#include "ETL_STATIC_ASSERT.h" -#include "unique_ptr.h" +#include "static_assert.h" +#include "memory.h" #include "type_traits.h" namespace etl @@ -61,128 +61,216 @@ namespace etl public: not_null_contains_null(string_type file_name_, numeric_type line_number_) - : delegate_exception(ETL_ERROR_TEXT("not_null:contains null", ETL_NOT_NULL_FILE_ID"A"), file_name_, line_number_) + : not_null_exception(ETL_ERROR_TEXT("not_null:contains null", ETL_NOT_NULL_FILE_ID"A"), file_name_, line_number_) { } }; + //*************************************************************************** + // not_null // Primary template + //*************************************************************************** template class not_null; + //*************************************************************************** // Specialisation for T* + // A container for pointers that are not allowed to be null. + //*************************************************************************** template class not_null { public: + //********************************* + /// Constructs a not_null from a pointer. + /// Asserts if the pointer is null. + //********************************* explicit not_null(T* ptr_) : ptr(ptr_) { - ETL_ASSERT(ptr != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); + ETL_ASSERT(ptr_ != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); } - not_null(const etl::not_null& other) + //********************************* + /// Copy constructor from a not_null pointer. + //********************************* + not_null(const etl::not_null& other) : ptr(other.get()) { } - not_null& operator =(const etl::not_null& other) + //********************************* + /// Assignment from a not_null. + //********************************* + not_null& operator =(const etl::not_null& rhs) { - ptr = other.get(); + ptr = rhs.get(); return *this; } - not_null& operator =(T* ptr_) + //********************************* + /// Assignment from a pointer. + /// Asserts if the pointer is null. + //********************************* + not_null& operator =(T* rhs) { - ETL_ASSERT(ptr_ != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); + ETL_ASSERT_OR_RETURN_VALUE(rhs != ETL_NULLPTR, ETL_ERROR(not_null_contains_null), *this); - ptr = ptr_; + ptr = rhs; return *this; } + //********************************* + /// Gets the underlying pointer. + //********************************* T* get() const { return ptr; } + //********************************* + /// Implicit conversion to T*. + //********************************* operator T*() const { return ptr; } - typename etl::remove_pointer::type& operator*() const - { - return *ptr; - } - - T operator->() const - { - return ptr; - } - - private: - - T* ptr; - }; - - // Partial specialisation for etl::unique_ptr - template - class not_null> - { - public: - - explicit not_null(etl::unique_ptr&& ptr_) - : ptr(etl::move(ptr_)) - { - ETL_ASSERT(ptr != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); - } - -#if ETL_USING_CPP11 - not_null& operator =(etl::unique_ptr&& ptr_) - { - ETL_ASSERT(ptr_ != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); - - ptr = etl::move(ptr_); - - return *this; - } -#endif - - T* get() const - { - return ptr.get(); - } - - operator T*() const - { - return ptr.get(); - } - + //********************************* + /// Dereference operator. + //********************************* T& operator*() const { return *ptr; } + //********************************* + /// Arrow operator. + //********************************* T* operator->() const - { - return ptr.get(); - } - - etl::unique_ptr& unique() - { - return ptr; - } - - const etl::unique_ptr& unique() const { return ptr; } private: + + /// The underlying pointer. + T* ptr; + }; + + //*************************************************************************** + // Partial specialisation for etl::unique_ptr + // A container for unique_ptr that are not allowed to be null. + //*************************************************************************** + template + class not_null> + { + private: + + // The unique_ptr type. + typedef etl::unique_ptr unique_ptr_type; + + public: + + //********************************* + /// Constructs a not_null from a unique_ptr. + /// Asserts if the unique_ptr is null. + //********************************* + explicit not_null(unique_ptr_type&& u_ptr_) + : u_ptr(etl::move(u_ptr_)) + { + ETL_ASSERT(u_ptr.get() != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); + } + +#if ETL_USING_CPP11 + //********************************* + /// Constructs a not_null from a unique_ptr. + //********************************* + not_null(etl::not_null&& other) + : u_ptr(etl::move(other.u_ptr)) + { + } + + //********************************* + /// Assign from a unique_ptr. + /// Asserts if the unique_ptr is null. + //********************************* + not_null& operator =(unique_ptr_type&& rhs) + { + ETL_ASSERT_OR_RETURN_VALUE(rhs.get() != ETL_NULLPTR, ETL_ERROR(not_null_contains_null), *this); + + u_ptr = etl::move(rhs); + + return *this; + } + + //********************************* + /// Assign from a not_null. + //********************************* + not_null& operator =(etl::not_null&& rhs) + { + u_ptr = etl::move(rhs.u_ptr); + + return *this; + } +#endif + + //********************************* + /// Gets the underlying unique_ptr. + //********************************* + T* get() const + { + return u_ptr.get(); + } + + //********************************* + /// Implicit conversion to T*. + //********************************* + operator T*() const + { + return u_ptr.get(); + } - etl::unique_ptr ptr; + //********************************* + /// Dereference operator. + //********************************* + T& operator*() const + { + return *u_ptr; + } + + //********************************* + /// Arrow operator. + //********************************* + T* operator->() const + { + return u_ptr.get(); + } + + //********************************* + /// Gets the underlying unique_ptr. + //********************************* + unique_ptr_type& unique() + { + return u_ptr; + } + + //********************************* + /// Gets the underlying unique_ptr. + //********************************* + const unique_ptr_type& unique() const + { + return u_ptr; + } + + private: + + /// The underlying unique_ptr. + unique_ptr_type u_ptr; }; } + +#endif diff --git a/test/test_not_null_pointer.cpp b/test/test_not_null_pointer.cpp new file mode 100644 index 00000000..fd9d1683 --- /dev/null +++ b/test/test_not_null_pointer.cpp @@ -0,0 +1,152 @@ +/****************************************************************************** +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/not_null.h" + +namespace +{ + SUITE(test_not_null_pointer) + { + //************************************************************************* + TEST(test_construct_from_non_null_pointer) + { + int value = 42; + etl::not_null nn(&value); + CHECK_EQUAL(&value, nn.get()); + CHECK_EQUAL(42, *nn); + } + + //************************************************************************* + TEST(test_copy_construct) + { + int value = 123; + etl::not_null nn1(&value); + etl::not_null nn2(nn1); // Copy constructor + CHECK_EQUAL(&value, nn2.get()); + CHECK_EQUAL(123, *nn2); + } + + //************************************************************************* + TEST(test_assign_from_pointer) + { + int value1 = 123; + etl::not_null nn1(&value1); + + int value2 = 456; + + nn1 = &value2; + CHECK_EQUAL(&value2, nn1.get()); + CHECK_EQUAL(456, *nn1); + } + + //************************************************************************* + TEST(test_assign_from_not_null) + { + int value1 = 123; + etl::not_null nn1(&value1); + + int value2 = 456; + etl::not_null nn2(&value2); + + nn1 = nn2; + CHECK_EQUAL(&value2, nn2.get()); + CHECK_EQUAL(456, *nn2); + } + + //************************************************************************* + TEST(test_implicit_conversion) + { + struct S + { + int x; + }; + + S s{77}; + etl::not_null nn(&s); + + S* raw = nn; + CHECK_EQUAL(&s, raw); + } + + //************************************************************************* + TEST(test_arrow_operator) + { + struct S + { + int x; + + int get() const + { + return x; + } + }; + + S s{77}; + etl::not_null nn(&s); + + CHECK_EQUAL(s.x, nn->x); + CHECK_EQUAL(s.get(), nn->get()); + } + + //************************************************************************* + TEST(test_dereference_operator) + { + struct S + { + int x; + + int get() const + { + return x; + } + }; + + S s{77}; + etl::not_null nn(&s); + + CHECK_EQUAL(s.x, (*nn).x); + CHECK_EQUAL(s.get(), (*nn).get()); + } + + //************************************************************************* + TEST(test_construct_from_null_pointer_asserts) + { + CHECK_THROW(etl::not_null nn(nullptr), etl::not_null_contains_null); + } + + //************************************************************************* + TEST(test_assign_null_pointer_asserts) + { + int value = 1; + etl::not_null nn(&value); + + CHECK_THROW(nn = nullptr, etl::not_null_contains_null); + } + }; +} \ No newline at end of file diff --git a/test/test_not_null_unique_pointer.cpp b/test/test_not_null_unique_pointer.cpp new file mode 100644 index 00000000..8ad0f4b4 --- /dev/null +++ b/test/test_not_null_unique_pointer.cpp @@ -0,0 +1,174 @@ +/****************************************************************************** +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/not_null.h" + +namespace +{ + struct S + { + int x; + + int get() const + { + return x; + } + }; + + SUITE(test_not_null_unique_pointer) + { + //************************************************************************* + TEST(test_construct_from_non_null_unique_ptr) + { + using up_t = etl::unique_ptr; + up_t up(new int{ 123 }); + etl::not_null nn(etl::move(up)); + + CHECK_EQUAL(123, *nn); + CHECK_EQUAL(123, *nn.get()); + } + + //************************************************************************* + TEST(test_unique) + { + using up_t = etl::unique_ptr; + up_t up1(new int{ 123 }); + etl::not_null nn(etl::move(up1)); + + up_t up2 = etl::move(nn.unique()); + + CHECK_EQUAL(123, *up2.get()); + } + + //************************************************************************* + TEST(test_unique_const) + { + using up_t = etl::unique_ptr; + up_t up1(new int{ 123 }); + const etl::not_null nn(etl::move(up1)); + + const up_t& up2 = nn.unique(); + + CHECK_EQUAL(123, *up2.get()); + } + + //************************************************************************* + TEST(test_move_construct) + { + using up_t = etl::unique_ptr; + up_t up(new int{ 123 }); + + etl::not_null nn1(etl::move(up)); + etl::not_null nn2(etl::move(nn1)); // Move constructor + + CHECK_TRUE(nn1.get() == nullptr); + CHECK_EQUAL(123, *nn2.get()); + CHECK_EQUAL(123, *nn2); + } + + //************************************************************************* + TEST(test_assign_from_unique_ptr) + { + using up_t = etl::unique_ptr; + up_t up1(new int{ 123 }); + etl::not_null nn1(etl::move(up1)); + + using up_t = etl::unique_ptr; + up_t up2(new int); + *up2 = 456; + + nn1 = etl::move(up2); + + CHECK_EQUAL(456, *nn1.get()); + } + + //************************************************************************* + TEST(test_assign_from_not_null) + { + using up_t = etl::unique_ptr; + up_t up1(new int{ 123 }); + etl::not_null nn1(etl::move(up1)); + + up_t up2(new int{ 456 }); + etl::not_null nn2(etl::move(up2)); + + nn1 = etl::move(nn2); + + CHECK_TRUE(nn2.get() == nullptr); + CHECK_EQUAL(456, *nn1.get()); + } + + //************************************************************************* + TEST(test_implicit_conversion) + { + using up_t = etl::unique_ptr; + up_t up1(new S{ 123 }); + etl::not_null nn1(etl::move(up1)); + + S s = *nn1; + + CHECK_EQUAL(123, s.x); + } + + //************************************************************************* + TEST(test_arrow_operator) + { + S s{ 123 }; + + using up_t = etl::unique_ptr; + up_t up1(new S{ 123 }); + etl::not_null nn1(etl::move(up1)); + + CHECK_EQUAL(s.x, nn1->x); + CHECK_EQUAL(s.get(), nn1->get()); + } + + //************************************************************************* + TEST(test_dereference_operator) + { + S s{ 123 }; + + using up_t = etl::unique_ptr; + up_t up1(new S{ 123 }); + etl::not_null nn1(etl::move(up1)); + + CHECK_EQUAL(s.x, (*nn1).x); + CHECK_EQUAL(s.get(), (*nn1).get()); + } + + //************************************************************************* + TEST(test_construct_from_null_pointer_asserts) + { + using up_t = etl::unique_ptr; + up_t up1(nullptr); + + CHECK_THROW(etl::not_null nn1(etl::move(up1)), etl::not_null_contains_null); + } + } +} \ No newline at end of file diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 7473133a..226b83ac 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -9400,6 +9400,8 @@ + + diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index 5bdf23fe..281ff201 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -3701,6 +3701,12 @@ Tests\Maths + + Tests\Misc + + + Tests\Misc + From 08ed69bac7b6562da60609a4d3dc0a52482f4ce8 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Fri, 15 Aug 2025 18:04:50 +0100 Subject: [PATCH 03/22] Fixed file Id error Updated CMakeLists.txt for tests and syntax checks --- include/etl/file_error_numbers.h | 1 + include/etl/not_null.h | 51 ++++++++++++++++++------------ test/CMakeLists.txt | 2 ++ test/syntax_check/CMakeLists.txt | 1 + test/syntax_check/not_null.h.t.cpp | 29 +++++++++++++++++ test/vs2022/etl.vcxproj | 18 +++++++++++ test/vs2022/etl.vcxproj.filters | 18 ++--------- 7 files changed, 84 insertions(+), 36 deletions(-) create mode 100644 test/syntax_check/not_null.h.t.cpp diff --git a/include/etl/file_error_numbers.h b/include/etl/file_error_numbers.h index 5404828a..51a009e7 100644 --- a/include/etl/file_error_numbers.h +++ b/include/etl/file_error_numbers.h @@ -107,4 +107,5 @@ SOFTWARE. #define ETL_UNALIGNED_TYPE_FILE_ID "74" #define ETL_SPAN_FILE_ID "75" #define ETL_ALGORITHM_FILE_ID "76" +#define ETL_NOT_NULL_FILE_ID "77" #endif diff --git a/include/etl/not_null.h b/include/etl/not_null.h index 54a4f565..0387a35c 100644 --- a/include/etl/not_null.h +++ b/include/etl/not_null.h @@ -82,11 +82,17 @@ namespace etl { public: + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + //********************************* /// Constructs a not_null from a pointer. /// Asserts if the pointer is null. //********************************* - explicit not_null(T* ptr_) + explicit not_null(pointer ptr_) : ptr(ptr_) { ETL_ASSERT(ptr_ != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); @@ -114,7 +120,7 @@ namespace etl /// Assignment from a pointer. /// Asserts if the pointer is null. //********************************* - not_null& operator =(T* rhs) + not_null& operator =(pointer rhs) { ETL_ASSERT_OR_RETURN_VALUE(rhs != ETL_NULLPTR, ETL_ERROR(not_null_contains_null), *this); @@ -126,15 +132,15 @@ namespace etl //********************************* /// Gets the underlying pointer. //********************************* - T* get() const + pointer get() const { return ptr; } //********************************* - /// Implicit conversion to T*. + /// Implicit conversion to pointer. //********************************* - operator T*() const + operator pointer() const { return ptr; } @@ -142,7 +148,7 @@ namespace etl //********************************* /// Dereference operator. //********************************* - T& operator*() const + reference operator*() const { return *ptr; } @@ -150,7 +156,7 @@ namespace etl //********************************* /// Arrow operator. //********************************* - T* operator->() const + pointer operator->() const { return ptr; } @@ -158,7 +164,7 @@ namespace etl private: /// The underlying pointer. - T* ptr; + pointer ptr; }; //*************************************************************************** @@ -166,15 +172,19 @@ namespace etl // A container for unique_ptr that are not allowed to be null. //*************************************************************************** template - class not_null> + class not_null > { - private: - - // The unique_ptr type. - typedef etl::unique_ptr unique_ptr_type; - public: + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + + typedef etl::unique_ptr unique_ptr_type; + +#if ETL_USING_CPP11 //********************************* /// Constructs a not_null from a unique_ptr. /// Asserts if the unique_ptr is null. @@ -185,7 +195,6 @@ namespace etl ETL_ASSERT(u_ptr.get() != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); } -#if ETL_USING_CPP11 //********************************* /// Constructs a not_null from a unique_ptr. //********************************* @@ -219,17 +228,17 @@ namespace etl #endif //********************************* - /// Gets the underlying unique_ptr. + /// Gets the underlying ptr. //********************************* - T* get() const + pointer get() const { return u_ptr.get(); } //********************************* - /// Implicit conversion to T*. + /// Implicit conversion to pointer. //********************************* - operator T*() const + operator pointer() const { return u_ptr.get(); } @@ -237,7 +246,7 @@ namespace etl //********************************* /// Dereference operator. //********************************* - T& operator*() const + reference operator*() const { return *u_ptr; } @@ -245,7 +254,7 @@ namespace etl //********************************* /// Arrow operator. //********************************* - T* operator->() const + pointer operator->() const { return u_ptr.get(); } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a60856f7..5b3564f1 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -229,6 +229,8 @@ add_executable(etl_tests test_multi_span.cpp test_multi_vector.cpp test_murmur3.cpp + test_not_null_pointer.cpp + test_not_null_unique_pointer.cpp test_nth_type.cpp test_numeric.cpp test_observer.cpp diff --git a/test/syntax_check/CMakeLists.txt b/test/syntax_check/CMakeLists.txt index 62d864c9..6c7eb194 100644 --- a/test/syntax_check/CMakeLists.txt +++ b/test/syntax_check/CMakeLists.txt @@ -242,6 +242,7 @@ target_sources(tests PRIVATE murmur3.h.t.cpp mutex.h.t.cpp negative.h.t.cpp + not_null.h.t.cpp nth_type.h.t.cpp nullptr.h.t.cpp null_type.h.t.cpp diff --git a/test/syntax_check/not_null.h.t.cpp b/test/syntax_check/not_null.h.t.cpp new file mode 100644 index 00000000..8f44b76c --- /dev/null +++ b/test/syntax_check/not_null.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/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 226b83ac..294096af 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -7390,6 +7390,24 @@ true true + + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true true diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index 281ff201..5c6910c2 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -196,27 +196,12 @@ {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} {a05ae045-3218-4ca2-9f25-08cc977898df} - - {3336d15c-7c22-4df0-a6b2-1eb605099a1a} - {c75cedd3-8b6c-4662-b965-aecbe7fd5d1c} @@ -3707,6 +3692,9 @@ Tests\Misc + + Tests\Syntax Checks\Source + From 109ba9350d8225bbb29a7926531d61316390eccc Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Fri, 15 Aug 2025 19:26:18 +0100 Subject: [PATCH 04/22] Updated syntax check tests --- test/syntax_check/CMakeLists.txt | 4 ++ test/syntax_check/crc16_opensafety_a.h.t.cpp | 29 ++++++++ test/syntax_check/crc16_opensafety_b.h.t.cpp | 29 ++++++++ test/syntax_check/crc8_opensafety.h.t.cpp | 29 ++++++++ test/syntax_check/delegate_observable.h.t.cpp | 28 ++++++++ test/vs2022/etl.vcxproj | 72 +++++++++++++++++++ 6 files changed, 191 insertions(+) create mode 100644 test/syntax_check/crc16_opensafety_a.h.t.cpp create mode 100644 test/syntax_check/crc16_opensafety_b.h.t.cpp create mode 100644 test/syntax_check/crc8_opensafety.h.t.cpp create mode 100644 test/syntax_check/delegate_observable.h.t.cpp diff --git a/test/syntax_check/CMakeLists.txt b/test/syntax_check/CMakeLists.txt index 62d864c9..eb0deadf 100644 --- a/test/syntax_check/CMakeLists.txt +++ b/test/syntax_check/CMakeLists.txt @@ -126,6 +126,8 @@ target_sources(tests PRIVATE crc16_maxim.h.t.cpp crc16_mcrf4xx.h.t.cpp crc16_modbus.h.t.cpp + crc16_opensafety_a.h.t.cpp + crc16_opensafety_b.h.t.cpp crc16_profibus.h.t.cpp crc16_riello.h.t.cpp crc16_t10dif.h.t.cpp @@ -154,12 +156,14 @@ target_sources(tests PRIVATE crc8_j1850.h.t.cpp crc8_j1850_zero.h.t.cpp crc8_maxim.h.t.cpp + crc8_opensafety.h.t.cpp crc8_rohc.h.t.cpp crc8_wcdma.h.t.cpp cyclic_value.h.t.cpp debounce.h.t.cpp debug_count.h.t.cpp delegate.h.t.cpp + delegate_observable.h.t.cpp delegate_service.h.t.cpp deque.h.t.cpp endianness.h.t.cpp diff --git a/test/syntax_check/crc16_opensafety_a.h.t.cpp b/test/syntax_check/crc16_opensafety_a.h.t.cpp new file mode 100644 index 00000000..21d774fd --- /dev/null +++ b/test/syntax_check/crc16_opensafety_a.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/crc16_opensafety_b.h.t.cpp b/test/syntax_check/crc16_opensafety_b.h.t.cpp new file mode 100644 index 00000000..5b38caf6 --- /dev/null +++ b/test/syntax_check/crc16_opensafety_b.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/crc8_opensafety.h.t.cpp b/test/syntax_check/crc8_opensafety.h.t.cpp new file mode 100644 index 00000000..35d26937 --- /dev/null +++ b/test/syntax_check/crc8_opensafety.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/delegate_observable.h.t.cpp b/test/syntax_check/delegate_observable.h.t.cpp new file mode 100644 index 00000000..4ef4112e --- /dev/null +++ b/test/syntax_check/delegate_observable.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 7473133a..4639af36 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -5268,6 +5268,42 @@ true true + + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + + + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true true @@ -5772,6 +5808,24 @@ true true + + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true true @@ -5898,6 +5952,24 @@ true true + + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true true From d7585508da860616403ec0e2b84fbcf0877b6244 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 16 Aug 2025 10:12:41 +0100 Subject: [PATCH 05/22] Changed unique() to underlying_type() Added underlying_type() to etl::not_null --- include/etl/not_null.h | 45 ++++++++++++++++++--------- test/test_not_null_pointer.cpp | 34 ++++++++++++++++++++ test/test_not_null_unique_pointer.cpp | 8 ++--- test/vs2022/etl.vcxproj | 1 + 4 files changed, 70 insertions(+), 18 deletions(-) diff --git a/include/etl/not_null.h b/include/etl/not_null.h index 0387a35c..54a5be6d 100644 --- a/include/etl/not_null.h +++ b/include/etl/not_null.h @@ -87,12 +87,13 @@ namespace etl typedef const T* const_pointer; typedef T& reference; typedef const T& const_reference; + typedef pointer underlying_type; //********************************* /// Constructs a not_null from a pointer. /// Asserts if the pointer is null. //********************************* - explicit not_null(pointer ptr_) + explicit not_null(underlying_type ptr_) : ptr(ptr_) { ETL_ASSERT(ptr_ != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); @@ -120,7 +121,7 @@ namespace etl /// Assignment from a pointer. /// Asserts if the pointer is null. //********************************* - not_null& operator =(pointer rhs) + not_null& operator =(underlying_type rhs) { ETL_ASSERT_OR_RETURN_VALUE(rhs != ETL_NULLPTR, ETL_ERROR(not_null_contains_null), *this); @@ -161,6 +162,22 @@ namespace etl return ptr; } + //********************************* + /// Gets a reference to the underlying pointer. + //********************************* + underlying_type& underlying() + { + return ptr; + } + + //********************************* + /// Gets a const_reference to the underlying pointer. + //********************************* + const underlying_type& underlying() const + { + return ptr; + } + private: /// The underlying pointer. @@ -182,14 +199,14 @@ namespace etl typedef T& reference; typedef const T& const_reference; - typedef etl::unique_ptr unique_ptr_type; + typedef etl::unique_ptr underlying_type;; #if ETL_USING_CPP11 //********************************* /// Constructs a not_null from a unique_ptr. /// Asserts if the unique_ptr is null. //********************************* - explicit not_null(unique_ptr_type&& u_ptr_) + explicit not_null(underlying_type&& u_ptr_) : u_ptr(etl::move(u_ptr_)) { ETL_ASSERT(u_ptr.get() != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); @@ -198,7 +215,7 @@ namespace etl //********************************* /// Constructs a not_null from a unique_ptr. //********************************* - not_null(etl::not_null&& other) + not_null(etl::not_null&& other) : u_ptr(etl::move(other.u_ptr)) { } @@ -207,7 +224,7 @@ namespace etl /// Assign from a unique_ptr. /// Asserts if the unique_ptr is null. //********************************* - not_null& operator =(unique_ptr_type&& rhs) + not_null& operator =(underlying_type&& rhs) { ETL_ASSERT_OR_RETURN_VALUE(rhs.get() != ETL_NULLPTR, ETL_ERROR(not_null_contains_null), *this); @@ -219,7 +236,7 @@ namespace etl //********************************* /// Assign from a not_null. //********************************* - not_null& operator =(etl::not_null&& rhs) + not_null& operator =(etl::not_null&& rhs) { u_ptr = etl::move(rhs.u_ptr); @@ -260,25 +277,25 @@ namespace etl } //********************************* - /// Gets the underlying unique_ptr. + /// Gets a reference to the underlying unique_ptr. //********************************* - unique_ptr_type& unique() + underlying_type& underlying() { - return u_ptr; + return etl::move(u_ptr); } //********************************* - /// Gets the underlying unique_ptr. + /// Gets a const_reference to the underlying unique_ptr. //********************************* - const unique_ptr_type& unique() const + const underlying_type& underlying() const { - return u_ptr; + return etl::move(u_ptr); } private: /// The underlying unique_ptr. - unique_ptr_type u_ptr; + underlying_type u_ptr; }; } diff --git a/test/test_not_null_pointer.cpp b/test/test_not_null_pointer.cpp index fd9d1683..59a34038 100644 --- a/test/test_not_null_pointer.cpp +++ b/test/test_not_null_pointer.cpp @@ -79,6 +79,40 @@ namespace CHECK_EQUAL(456, *nn2); } + //************************************************************************* + TEST(test_underlying) + { + int value1 = 123; + etl::not_null nn1(&value1); + + int* p = nn1.underlying(); + + CHECK_EQUAL(123, *p); + } + + //************************************************************************* + TEST(test_underlying_const) + { + int value1 = 123; + const etl::not_null nn1(&value1); + + const int* p = nn1.underlying(); + + CHECK_EQUAL(123, *p); + } + + //************************************************************************* + TEST(test_unique_const) + { + using up_t = etl::unique_ptr; + up_t up1(new int{ 123 }); + const etl::not_null nn(etl::move(up1)); + + const up_t& up2 = nn.underlying(); + + CHECK_EQUAL(123, *up2.get()); + } + //************************************************************************* TEST(test_implicit_conversion) { diff --git a/test/test_not_null_unique_pointer.cpp b/test/test_not_null_unique_pointer.cpp index 8ad0f4b4..eef5fc00 100644 --- a/test/test_not_null_unique_pointer.cpp +++ b/test/test_not_null_unique_pointer.cpp @@ -55,25 +55,25 @@ namespace } //************************************************************************* - TEST(test_unique) + TEST(test_underlying) { using up_t = etl::unique_ptr; up_t up1(new int{ 123 }); etl::not_null nn(etl::move(up1)); - up_t up2 = etl::move(nn.unique()); + up_t up2 = etl::move(nn.underlying()); CHECK_EQUAL(123, *up2.get()); } //************************************************************************* - TEST(test_unique_const) + TEST(test_underlying_const) { using up_t = etl::unique_ptr; up_t up1(new int{ 123 }); const etl::not_null nn(etl::move(up1)); - const up_t& up2 = nn.unique(); + const up_t& up2 = etl::move(nn.underlying()); CHECK_EQUAL(123, *up2.get()); } diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 294096af..7e15bc66 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -3362,6 +3362,7 @@ + From 94f7d9956def83b65fc3c4c2c7724cbf32f6f2b3 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 16 Aug 2025 10:12:41 +0100 Subject: [PATCH 06/22] Changed unique() to underlying_type() Added underlying_type() to etl::not_null --- include/etl/not_null.h | 41 +++++++++++++++++++-------- test/test_not_null_pointer.cpp | 34 ++++++++++++++++++++++ test/test_not_null_unique_pointer.cpp | 8 +++--- test/vs2022/etl.vcxproj | 1 + 4 files changed, 68 insertions(+), 16 deletions(-) diff --git a/include/etl/not_null.h b/include/etl/not_null.h index 0387a35c..12cbf2e2 100644 --- a/include/etl/not_null.h +++ b/include/etl/not_null.h @@ -87,12 +87,13 @@ namespace etl typedef const T* const_pointer; typedef T& reference; typedef const T& const_reference; + typedef pointer underlying_type; //********************************* /// Constructs a not_null from a pointer. /// Asserts if the pointer is null. //********************************* - explicit not_null(pointer ptr_) + explicit not_null(underlying_type ptr_) : ptr(ptr_) { ETL_ASSERT(ptr_ != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); @@ -120,7 +121,7 @@ namespace etl /// Assignment from a pointer. /// Asserts if the pointer is null. //********************************* - not_null& operator =(pointer rhs) + not_null& operator =(underlying_type rhs) { ETL_ASSERT_OR_RETURN_VALUE(rhs != ETL_NULLPTR, ETL_ERROR(not_null_contains_null), *this); @@ -161,6 +162,22 @@ namespace etl return ptr; } + //********************************* + /// Gets a reference to the underlying pointer. + //********************************* + underlying_type& underlying() + { + return ptr; + } + + //********************************* + /// Gets a const_reference to the underlying pointer. + //********************************* + const underlying_type& underlying() const + { + return ptr; + } + private: /// The underlying pointer. @@ -182,14 +199,14 @@ namespace etl typedef T& reference; typedef const T& const_reference; - typedef etl::unique_ptr unique_ptr_type; + typedef etl::unique_ptr underlying_type;; #if ETL_USING_CPP11 //********************************* /// Constructs a not_null from a unique_ptr. /// Asserts if the unique_ptr is null. //********************************* - explicit not_null(unique_ptr_type&& u_ptr_) + explicit not_null(underlying_type&& u_ptr_) : u_ptr(etl::move(u_ptr_)) { ETL_ASSERT(u_ptr.get() != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); @@ -198,7 +215,7 @@ namespace etl //********************************* /// Constructs a not_null from a unique_ptr. //********************************* - not_null(etl::not_null&& other) + not_null(etl::not_null&& other) : u_ptr(etl::move(other.u_ptr)) { } @@ -207,7 +224,7 @@ namespace etl /// Assign from a unique_ptr. /// Asserts if the unique_ptr is null. //********************************* - not_null& operator =(unique_ptr_type&& rhs) + not_null& operator =(underlying_type&& rhs) { ETL_ASSERT_OR_RETURN_VALUE(rhs.get() != ETL_NULLPTR, ETL_ERROR(not_null_contains_null), *this); @@ -219,7 +236,7 @@ namespace etl //********************************* /// Assign from a not_null. //********************************* - not_null& operator =(etl::not_null&& rhs) + not_null& operator =(etl::not_null&& rhs) { u_ptr = etl::move(rhs.u_ptr); @@ -260,17 +277,17 @@ namespace etl } //********************************* - /// Gets the underlying unique_ptr. + /// Gets a reference to the underlying unique_ptr. //********************************* - unique_ptr_type& unique() + underlying_type& underlying() { return u_ptr; } //********************************* - /// Gets the underlying unique_ptr. + /// Gets a const_reference to the underlying unique_ptr. //********************************* - const unique_ptr_type& unique() const + const underlying_type& underlying() const { return u_ptr; } @@ -278,7 +295,7 @@ namespace etl private: /// The underlying unique_ptr. - unique_ptr_type u_ptr; + underlying_type u_ptr; }; } diff --git a/test/test_not_null_pointer.cpp b/test/test_not_null_pointer.cpp index fd9d1683..59a34038 100644 --- a/test/test_not_null_pointer.cpp +++ b/test/test_not_null_pointer.cpp @@ -79,6 +79,40 @@ namespace CHECK_EQUAL(456, *nn2); } + //************************************************************************* + TEST(test_underlying) + { + int value1 = 123; + etl::not_null nn1(&value1); + + int* p = nn1.underlying(); + + CHECK_EQUAL(123, *p); + } + + //************************************************************************* + TEST(test_underlying_const) + { + int value1 = 123; + const etl::not_null nn1(&value1); + + const int* p = nn1.underlying(); + + CHECK_EQUAL(123, *p); + } + + //************************************************************************* + TEST(test_unique_const) + { + using up_t = etl::unique_ptr; + up_t up1(new int{ 123 }); + const etl::not_null nn(etl::move(up1)); + + const up_t& up2 = nn.underlying(); + + CHECK_EQUAL(123, *up2.get()); + } + //************************************************************************* TEST(test_implicit_conversion) { diff --git a/test/test_not_null_unique_pointer.cpp b/test/test_not_null_unique_pointer.cpp index 8ad0f4b4..eef5fc00 100644 --- a/test/test_not_null_unique_pointer.cpp +++ b/test/test_not_null_unique_pointer.cpp @@ -55,25 +55,25 @@ namespace } //************************************************************************* - TEST(test_unique) + TEST(test_underlying) { using up_t = etl::unique_ptr; up_t up1(new int{ 123 }); etl::not_null nn(etl::move(up1)); - up_t up2 = etl::move(nn.unique()); + up_t up2 = etl::move(nn.underlying()); CHECK_EQUAL(123, *up2.get()); } //************************************************************************* - TEST(test_unique_const) + TEST(test_underlying_const) { using up_t = etl::unique_ptr; up_t up1(new int{ 123 }); const etl::not_null nn(etl::move(up1)); - const up_t& up2 = nn.unique(); + const up_t& up2 = etl::move(nn.underlying()); CHECK_EQUAL(123, *up2.get()); } diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 294096af..7e15bc66 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -3362,6 +3362,7 @@ + From 037029ea844e56d2b83d473c328dbeaa2f2106a7 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 17 Aug 2025 10:37:27 +0100 Subject: [PATCH 07/22] Added constexpr. Removed some member functions. Removed 'move' member functions for etl::not_null> --- include/etl/not_null.h | 131 +++++++------------ include/etl/platform.h | 12 +- test/CMakeLists.txt | 1 + test/test_not_null_pointer.cpp | 79 +++--------- test/test_not_null_pointer_constexpr.cpp | 154 +++++++++++++++++++++++ test/test_not_null_unique_pointer.cpp | 54 -------- test/vs2022/cpp.hint | 22 ++++ test/vs2022/etl.vcxproj | 1 + test/vs2022/etl.vcxproj.filters | 6 + 9 files changed, 253 insertions(+), 207 deletions(-) create mode 100644 test/test_not_null_pointer_constexpr.cpp diff --git a/include/etl/not_null.h b/include/etl/not_null.h index 12cbf2e2..f92de6e5 100644 --- a/include/etl/not_null.h +++ b/include/etl/not_null.h @@ -47,7 +47,7 @@ namespace etl { public: - not_null_exception(string_type reason_, string_type file_name_, numeric_type line_number_) + not_null_exception(string_type reason_, string_type file_name_, numeric_type line_number_) ETL_NOEXCEPT_IF_NO_THROW : exception(reason_, file_name_, line_number_) { } @@ -60,7 +60,7 @@ namespace etl { public: - not_null_contains_null(string_type file_name_, numeric_type line_number_) + not_null_contains_null(string_type file_name_, numeric_type line_number_) ETL_NOEXCEPT_IF_NO_THROW : not_null_exception(ETL_ERROR_TEXT("not_null:contains null", ETL_NOT_NULL_FILE_ID"A"), file_name_, line_number_) { } @@ -93,47 +93,47 @@ namespace etl /// Constructs a not_null from a pointer. /// Asserts if the pointer is null. //********************************* - explicit not_null(underlying_type ptr_) + ETL_CONSTEXPR14 explicit not_null(underlying_type ptr_) ETL_NOEXCEPT_IF_NO_THROW : ptr(ptr_) { ETL_ASSERT(ptr_ != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); } //********************************* - /// Copy constructor from a not_null pointer. + /// Copy construct from a not_null pointer. //********************************* - not_null(const etl::not_null& other) + ETL_CONSTEXPR14 not_null(const etl::not_null& other) ETL_NOEXCEPT : ptr(other.get()) { } + //********************************* + /// Assignment from a pointer. + /// Asserts if the pointer is null. + //********************************* + ETL_CONSTEXPR14 not_null& operator =(underlying_type rhs) ETL_NOEXCEPT_IF_NO_THROW + { + ETL_ASSERT_OR_RETURN_VALUE(rhs != ETL_NULLPTR, ETL_ERROR(not_null_contains_null), *this); + + ptr = rhs; + + return *this; + } + //********************************* /// Assignment from a not_null. //********************************* - not_null& operator =(const etl::not_null& rhs) + ETL_CONSTEXPR14 not_null& operator =(const etl::not_null& rhs) ETL_NOEXCEPT { ptr = rhs.get(); return *this; } - //********************************* - /// Assignment from a pointer. - /// Asserts if the pointer is null. - //********************************* - not_null& operator =(underlying_type rhs) - { - ETL_ASSERT_OR_RETURN_VALUE(rhs != ETL_NULLPTR, ETL_ERROR(not_null_contains_null), *this); - - ptr = rhs; - - return *this; - } - //********************************* /// Gets the underlying pointer. //********************************* - pointer get() const + ETL_CONSTEXPR14 pointer get() const ETL_NOEXCEPT { return ptr; } @@ -141,7 +141,7 @@ namespace etl //********************************* /// Implicit conversion to pointer. //********************************* - operator pointer() const + ETL_CONSTEXPR14 operator pointer() const ETL_NOEXCEPT { return ptr; } @@ -149,31 +149,15 @@ namespace etl //********************************* /// Dereference operator. //********************************* - reference operator*() const + ETL_CONSTEXPR14 reference operator*() const ETL_NOEXCEPT { return *ptr; } - + //********************************* /// Arrow operator. //********************************* - pointer operator->() const - { - return ptr; - } - - //********************************* - /// Gets a reference to the underlying pointer. - //********************************* - underlying_type& underlying() - { - return ptr; - } - - //********************************* - /// Gets a const_reference to the underlying pointer. - //********************************* - const underlying_type& underlying() const + ETL_CONSTEXPR14 pointer operator->() const ETL_NOEXCEPT { return ptr; } @@ -191,6 +175,11 @@ namespace etl template class not_null > { + private: + + typedef etl::not_null > this_type; + typedef etl::unique_ptr underlying_type; + public: typedef T value_type; @@ -199,32 +188,24 @@ namespace etl typedef T& reference; typedef const T& const_reference; - typedef etl::unique_ptr underlying_type;; - #if ETL_USING_CPP11 //********************************* /// Constructs a not_null from a unique_ptr. - /// Asserts if the unique_ptr is null. + /// Asserts if the unique_ptr contains null. + /// Moves from the unique_ptr. //********************************* - explicit not_null(underlying_type&& u_ptr_) + ETL_CONSTEXPR14 explicit not_null(underlying_type&& u_ptr_) ETL_NOEXCEPT_IF_NO_THROW : u_ptr(etl::move(u_ptr_)) { ETL_ASSERT(u_ptr.get() != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); } - //********************************* - /// Constructs a not_null from a unique_ptr. - //********************************* - not_null(etl::not_null&& other) - : u_ptr(etl::move(other.u_ptr)) - { - } - //********************************* /// Assign from a unique_ptr. - /// Asserts if the unique_ptr is null. + /// Asserts if the unique_ptr contains null. + /// Moves from the unique_ptr. //********************************* - not_null& operator =(underlying_type&& rhs) + ETL_CONSTEXPR14 not_null& operator =(underlying_type&& rhs) ETL_NOEXCEPT_IF_NO_THROW { ETL_ASSERT_OR_RETURN_VALUE(rhs.get() != ETL_NULLPTR, ETL_ERROR(not_null_contains_null), *this); @@ -232,22 +213,12 @@ namespace etl return *this; } - - //********************************* - /// Assign from a not_null. - //********************************* - not_null& operator =(etl::not_null&& rhs) - { - u_ptr = etl::move(rhs.u_ptr); - - return *this; - } #endif //********************************* /// Gets the underlying ptr. //********************************* - pointer get() const + ETL_CONSTEXPR14 pointer get() const ETL_NOEXCEPT { return u_ptr.get(); } @@ -255,7 +226,7 @@ namespace etl //********************************* /// Implicit conversion to pointer. //********************************* - operator pointer() const + ETL_CONSTEXPR14 operator pointer() const ETL_NOEXCEPT { return u_ptr.get(); } @@ -263,7 +234,7 @@ namespace etl //********************************* /// Dereference operator. //********************************* - reference operator*() const + ETL_CONSTEXPR14 reference operator*() const ETL_NOEXCEPT { return *u_ptr; } @@ -271,29 +242,21 @@ namespace etl //********************************* /// Arrow operator. //********************************* - pointer operator->() const + ETL_CONSTEXPR14 pointer operator->() const ETL_NOEXCEPT { return u_ptr.get(); } - //********************************* - /// Gets a reference to the underlying unique_ptr. - //********************************* - underlying_type& underlying() - { - return u_ptr; - } - - //********************************* - /// Gets a const_reference to the underlying unique_ptr. - //********************************* - const underlying_type& underlying() const - { - return u_ptr; - } - private: + ETL_CONSTEXPR14 explicit not_null(const this_type& u_ptr_) ETL_NOEXCEPT ETL_DELETE; + ETL_CONSTEXPR14 not_null& operator=(const this_type& rhs) ETL_NOEXCEPT ETL_DELETE; + +#if ETL_USING_CPP11 + ETL_CONSTEXPR14 explicit not_null(this_type&& u_ptr_) ETL_NOEXCEPT = delete; + ETL_CONSTEXPR14 not_null& operator=(this_type&& rhs) ETL_NOEXCEPT = delete; +#endif + /// The underlying unique_ptr. underlying_type u_ptr; }; diff --git a/include/etl/platform.h b/include/etl/platform.h index 248a19f4..bcebdf89 100644 --- a/include/etl/platform.h +++ b/include/etl/platform.h @@ -331,13 +331,15 @@ 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_NOEXCEPT noexcept + #define ETL_NOEXCEPT_EXPR(...) noexcept(__VA_ARGS__) - #if ETL_USING_EXCEPTIONS - #define ETL_NOEXCEPT noexcept - #define ETL_NOEXCEPT_EXPR(...) noexcept(__VA_ARGS__) + #if ETL_NOT_USING_EXCEPTIONS + #define ETL_NOEXCEPT_IF_NO_THROW noexcept + #define ETL_NOEXCEPT_IF_NO_THROW_EXPR(...) noexcept(__VA_ARGS__) #else - #define ETL_NOEXCEPT - #define ETL_NOEXCEPT_EXPR(...) + #define ETL_NOEXCEPT_IF_NO_THROW + #define ETL_NOEXCEPT_IF_NO_THROW_EXPR(...) #endif #else #define ETL_CONSTEXPR diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5b3564f1..61c01e47 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -230,6 +230,7 @@ add_executable(etl_tests test_multi_vector.cpp test_murmur3.cpp test_not_null_pointer.cpp + test_not_null_pointer_constexpr.cpp test_not_null_unique_pointer.cpp test_nth_type.cpp test_numeric.cpp diff --git a/test/test_not_null_pointer.cpp b/test/test_not_null_pointer.cpp index 59a34038..546a6098 100644 --- a/test/test_not_null_pointer.cpp +++ b/test/test_not_null_pointer.cpp @@ -31,15 +31,25 @@ SOFTWARE. namespace { + struct S + { + int x; + + int get() const + { + return x; + } + }; + SUITE(test_not_null_pointer) { //************************************************************************* TEST(test_construct_from_non_null_pointer) { - int value = 42; + int value = 123; etl::not_null nn(&value); CHECK_EQUAL(&value, nn.get()); - CHECK_EQUAL(42, *nn); + CHECK_EQUAL(123, *nn); } //************************************************************************* @@ -79,49 +89,10 @@ namespace CHECK_EQUAL(456, *nn2); } - //************************************************************************* - TEST(test_underlying) - { - int value1 = 123; - etl::not_null nn1(&value1); - - int* p = nn1.underlying(); - - CHECK_EQUAL(123, *p); - } - - //************************************************************************* - TEST(test_underlying_const) - { - int value1 = 123; - const etl::not_null nn1(&value1); - - const int* p = nn1.underlying(); - - CHECK_EQUAL(123, *p); - } - - //************************************************************************* - TEST(test_unique_const) - { - using up_t = etl::unique_ptr; - up_t up1(new int{ 123 }); - const etl::not_null nn(etl::move(up1)); - - const up_t& up2 = nn.underlying(); - - CHECK_EQUAL(123, *up2.get()); - } - //************************************************************************* TEST(test_implicit_conversion) { - struct S - { - int x; - }; - - S s{77}; + S s{123}; etl::not_null nn(&s); S* raw = nn; @@ -131,17 +102,7 @@ namespace //************************************************************************* TEST(test_arrow_operator) { - struct S - { - int x; - - int get() const - { - return x; - } - }; - - S s{77}; + S s{123}; etl::not_null nn(&s); CHECK_EQUAL(s.x, nn->x); @@ -151,17 +112,7 @@ namespace //************************************************************************* TEST(test_dereference_operator) { - struct S - { - int x; - - int get() const - { - return x; - } - }; - - S s{77}; + S s{123}; etl::not_null nn(&s); CHECK_EQUAL(s.x, (*nn).x); diff --git a/test/test_not_null_pointer_constexpr.cpp b/test/test_not_null_pointer_constexpr.cpp new file mode 100644 index 00000000..5cf53881 --- /dev/null +++ b/test/test_not_null_pointer_constexpr.cpp @@ -0,0 +1,154 @@ +/****************************************************************************** +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/not_null.h" + +#if ETL_USING_CPP14 +namespace +{ + struct S + { + int x; + + constexpr int get() const + { + return x; + } + }; + + //************************************************************************* + constexpr etl::not_null CreateNotNullAssignFromPointer(const int* p1, const int* p2) + { + // Create a not_null pointer from a pointer. + etl::not_null nn(p1); + + // Assign a different pointer to the not_null. + nn = p2; + + return nn; + } + + //************************************************************************* + constexpr etl::not_null CreateNotNullAssignFromNotNull(const int* p1, const int* p2) + { + // Create a not_null pointer from a pointer. + etl::not_null nn1(p1); + etl::not_null nn2(p2); + + nn1 = nn2; + + return nn1; + } + + SUITE(test_not_null_pointer) + { + //************************************************************************* + TEST(test_construct_from_non_null_pointer) + { + static constexpr const int value = 123; + static constexpr etl::not_null nn(&value); + static constexpr const int* p = nn.get(); + static constexpr const int v = *nn; + CHECK_EQUAL(&value, p); + CHECK_EQUAL(123, v); + } + + //************************************************************************* + TEST(test_copy_construct) + { + static constexpr const int value = 123; + static constexpr etl::not_null nn1(&value); + static constexpr etl::not_null nn2(nn1); // Copy constructor + static constexpr const int* p = nn2.get(); + static constexpr const int v = *nn2; + CHECK_EQUAL(&value, p); + CHECK_EQUAL(123, v); + } + + //************************************************************************* + TEST(test_assign_from_pointer) + { + static constexpr const int value1 = 123; + static constexpr const int value2 = 456; + static constexpr etl::not_null nn(CreateNotNullAssignFromPointer(&value1, &value2)); + + CHECK_EQUAL(&value2, nn.get()); + CHECK_EQUAL(456, *nn); + } + + //************************************************************************* + TEST(test_assign_from_not_null) + { + static constexpr const int value1 = 123; + static constexpr const int value2 = 456; + static constexpr etl::not_null nn(CreateNotNullAssignFromNotNull(&value1, &value2)); + + CHECK_EQUAL(&value2, nn.get()); + CHECK_EQUAL(456, *nn); + } + + //************************************************************************* + TEST(test_implicit_conversion) + { + static constexpr const S s{123}; + static constexpr etl::not_null nn(&s); + + static constexpr const S* raw = nn; + CHECK_EQUAL(&s, raw); + } + + //************************************************************************* + TEST(test_arrow_operator) + { + static constexpr const S s{123}; + static constexpr etl::not_null nn(&s); + + static constexpr int x1 = nn->x; + static constexpr int x2 = nn->get(); + + CHECK_EQUAL(s.x, x1); + CHECK_EQUAL(s.get(), x2); + } + + //************************************************************************* + TEST(test_dereference_operator) + { + static constexpr const S s{123}; + static constexpr etl::not_null nn(&s); + + static constexpr int x1 = (*nn).x; + static constexpr int x2 = (*nn).get(); + + CHECK_EQUAL(s.x, x1); + CHECK_EQUAL(s.get(), x2); + } + }; +} + +#endif diff --git a/test/test_not_null_unique_pointer.cpp b/test/test_not_null_unique_pointer.cpp index eef5fc00..b707b5a4 100644 --- a/test/test_not_null_unique_pointer.cpp +++ b/test/test_not_null_unique_pointer.cpp @@ -54,44 +54,6 @@ namespace CHECK_EQUAL(123, *nn.get()); } - //************************************************************************* - TEST(test_underlying) - { - using up_t = etl::unique_ptr; - up_t up1(new int{ 123 }); - etl::not_null nn(etl::move(up1)); - - up_t up2 = etl::move(nn.underlying()); - - CHECK_EQUAL(123, *up2.get()); - } - - //************************************************************************* - TEST(test_underlying_const) - { - using up_t = etl::unique_ptr; - up_t up1(new int{ 123 }); - const etl::not_null nn(etl::move(up1)); - - const up_t& up2 = etl::move(nn.underlying()); - - CHECK_EQUAL(123, *up2.get()); - } - - //************************************************************************* - TEST(test_move_construct) - { - using up_t = etl::unique_ptr; - up_t up(new int{ 123 }); - - etl::not_null nn1(etl::move(up)); - etl::not_null nn2(etl::move(nn1)); // Move constructor - - CHECK_TRUE(nn1.get() == nullptr); - CHECK_EQUAL(123, *nn2.get()); - CHECK_EQUAL(123, *nn2); - } - //************************************************************************* TEST(test_assign_from_unique_ptr) { @@ -108,22 +70,6 @@ namespace CHECK_EQUAL(456, *nn1.get()); } - //************************************************************************* - TEST(test_assign_from_not_null) - { - using up_t = etl::unique_ptr; - up_t up1(new int{ 123 }); - etl::not_null nn1(etl::move(up1)); - - up_t up2(new int{ 456 }); - etl::not_null nn2(etl::move(up2)); - - nn1 = etl::move(nn2); - - CHECK_TRUE(nn2.get() == nullptr); - CHECK_EQUAL(456, *nn1.get()); - } - //************************************************************************* TEST(test_implicit_conversion) { diff --git a/test/vs2022/cpp.hint b/test/vs2022/cpp.hint index 6aeae32e..0169bdca 100644 --- a/test/vs2022/cpp.hint +++ b/test/vs2022/cpp.hint @@ -38,3 +38,25 @@ #define CHECK_ARRAY_EQUAL #define CHECK_CLOSE #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_NOEXCEPT_IF_NO_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_NOEXCEPT +// 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_UNLIKELY {etl::error_handler::error((e)); throw((e));}} +#define ETL_ASSERT(b, e) {if (!(b)) ETL_UNLIKELY {throw((e));}} +#define ETL_ASSERT(b, e) {if (!(b)) ETL_UNLIKELY {etl::error_handler::error((e));}} +#define ETL_ASSERT(b, e) assert((b)) +#define ETL_ASSERT(b, e) {if (!(b)) ETL_UNLIKELY {etl::private_error_handler::assert_handler<0>::assert_function_ptr((e));}} +// 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_ERROR(e) (e(__FILE__, __LINE__)) +#define ETL_ERROR(e) (e("", __LINE__)) diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 7e15bc66..3159a94a 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -9420,6 +9420,7 @@ + diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index 5c6910c2..7e7037be 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -1521,6 +1521,9 @@ ETL\Frameworks + + ETL\Utilities + @@ -3695,6 +3698,9 @@ Tests\Syntax Checks\Source + + Tests\Misc + From 450948933f32d657c5330dc0638355959b77c7dc Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 18 Aug 2025 14:20:45 +0100 Subject: [PATCH 08/22] Added example of the use of etl::unique_ptr with etl::pool --- .gitignore | 5 + examples/UniquePtrWithPool/CmakeLists.txt | 10 ++ examples/UniquePtrWithPool/Main.cpp | 51 +++++++ .../UniquePtrWithPool/UniquePtrWithPool.sln | 31 ++++ .../UniquePtrWithPool.vcxproj | 133 ++++++++++++++++++ 5 files changed, 230 insertions(+) create mode 100644 examples/UniquePtrWithPool/CmakeLists.txt create mode 100644 examples/UniquePtrWithPool/Main.cpp create mode 100644 examples/UniquePtrWithPool/UniquePtrWithPool.sln create mode 100644 examples/UniquePtrWithPool/UniquePtrWithPool.vcxproj diff --git a/.gitignore b/.gitignore index a1decab8..67e5983d 100644 --- a/.gitignore +++ b/.gitignore @@ -403,3 +403,8 @@ test/syntax_check/bgcc test/vs2022/Debug MSVC C++23 test/vs2022/Debug MSVC C++23 - No STL .vs +examples/UniquePtrWithPool/CMakeFiles +examples/UniquePtrWithPool/cmake_install.cmake +examples/UniquePtrWithPool/Makefile +examples/UniquePtrWithPool/CMakeCache.txt +examples/UniquePtrWithPool/UniquePtrWithPool diff --git a/examples/UniquePtrWithPool/CmakeLists.txt b/examples/UniquePtrWithPool/CmakeLists.txt new file mode 100644 index 00000000..a7e41b0a --- /dev/null +++ b/examples/UniquePtrWithPool/CmakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.10) +project(UniquePtrWithPool LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# Add source files +add_executable(UniquePtrWithPool Main.cpp) + +target_include_directories(UniquePtrWithPool PRIVATE ../../include) diff --git a/examples/UniquePtrWithPool/Main.cpp b/examples/UniquePtrWithPool/Main.cpp new file mode 100644 index 00000000..1b267c48 --- /dev/null +++ b/examples/UniquePtrWithPool/Main.cpp @@ -0,0 +1,51 @@ +#include + +#include "etl/memory.h" +#include "etl/pool.h" + +struct S +{ + S(int a_, double b_) + : a(a_), b(b_) + { + } + + int a; + double b; +}; + +// Custom deleter that returns S* to the pool +struct Deleter +{ + Deleter(etl::pool& p) + : pool(&p) {} + + void operator()(S* ptr) const + { + if (ptr) + { + std::cout << "Releasing S(" << ptr->a << ", " << ptr->b << ") back to pool." << std::endl; + pool->release(ptr); + } + } + + etl::pool* pool; +}; + +int main() +{ + etl::pool pool; + Deleter pool_deleter(pool); + using Unique = etl::unique_ptr; + + Unique us1(pool.create(1, 2), pool_deleter); + std::cout << "Created S(" << us1->a << ", " << us1->b << ") from pool." << std::endl; + + { + Unique us2(pool.create(3, 4), pool_deleter); + std::cout << "Created S(" << us2->a << ", " << us2->b << ") from pool." << std::endl; + } + + Unique us3(pool.create(5, 6), pool_deleter); + std::cout << "Created S(" << us3->a << ", " << us3->b << ") from pool." << std::endl; +} diff --git a/examples/UniquePtrWithPool/UniquePtrWithPool.sln b/examples/UniquePtrWithPool/UniquePtrWithPool.sln new file mode 100644 index 00000000..24a9e577 --- /dev/null +++ b/examples/UniquePtrWithPool/UniquePtrWithPool.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.36408.4 d17.14 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UniquePtrWithPool", "UniquePtrWithPool.vcxproj", "{B9ED2FDF-2529-4315-9AEF-02A98B804DEC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B9ED2FDF-2529-4315-9AEF-02A98B804DEC}.Debug|x64.ActiveCfg = Debug|x64 + {B9ED2FDF-2529-4315-9AEF-02A98B804DEC}.Debug|x64.Build.0 = Debug|x64 + {B9ED2FDF-2529-4315-9AEF-02A98B804DEC}.Debug|x86.ActiveCfg = Debug|Win32 + {B9ED2FDF-2529-4315-9AEF-02A98B804DEC}.Debug|x86.Build.0 = Debug|Win32 + {B9ED2FDF-2529-4315-9AEF-02A98B804DEC}.Release|x64.ActiveCfg = Release|x64 + {B9ED2FDF-2529-4315-9AEF-02A98B804DEC}.Release|x64.Build.0 = Release|x64 + {B9ED2FDF-2529-4315-9AEF-02A98B804DEC}.Release|x86.ActiveCfg = Release|Win32 + {B9ED2FDF-2529-4315-9AEF-02A98B804DEC}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D21FA849-65C8-4A81-BD9D-B38BFBD73494} + EndGlobalSection +EndGlobal diff --git a/examples/UniquePtrWithPool/UniquePtrWithPool.vcxproj b/examples/UniquePtrWithPool/UniquePtrWithPool.vcxproj new file mode 100644 index 00000000..184bf5b3 --- /dev/null +++ b/examples/UniquePtrWithPool/UniquePtrWithPool.vcxproj @@ -0,0 +1,133 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 17.0 + Win32Proj + {b9ed2fdf-2529-4315-9aef-02a98b804dec} + UniquePtrWithPool + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + ../../include/;%(AdditionalIncludeDirectories) + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + ../../include/;%(AdditionalIncludeDirectories) + + + Console + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + + + + + \ No newline at end of file From 63d74706850f056d63d5b19465c4cee8d6eab3a7 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 18 Aug 2025 14:22:33 +0100 Subject: [PATCH 09/22] Added etl::nontype_t, with C++11 and C++17 alternatives --- include/etl/utility.h | 20 ++++++++++++++++++++ test/test_utility.cpp | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/include/etl/utility.h b/include/etl/utility.h index 43852e72..c3ea993d 100644 --- a/include/etl/utility.h +++ b/include/etl/utility.h @@ -818,6 +818,26 @@ namespace etl TReturn(*ptr)(TArgs...); }; #endif + +#if ETL_USING_CPP17 && !defined(ETL_FORCE_CPP11_NONTYPE) + //***************************************************************************** + // Wraps a non-type template parameter as a type. + //***************************************************************************** + template + struct nontype_t + { + static constexpr decltype(Value) value = Value; + }; +#elif ETL_USING_CPP11 + //***************************************************************************** + // Wraps a non-type template parameter as a type. + //***************************************************************************** + template + struct nontype_t + { + static constexpr T value = Value; + }; +#endif } #endif diff --git a/test/test_utility.cpp b/test/test_utility.cpp index 4b378625..0a9559e6 100644 --- a/test/test_utility.cpp +++ b/test/test_utility.cpp @@ -789,4 +789,42 @@ namespace } #endif }; + +#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 with bool + CHECK_TRUE(true == etl::nontype_t::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); + } +#elif ETL_USING_CPP11 + 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 with bool + CHECK_TRUE(true == (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)); + } +#endif } From f6fd44a096cab108a38be7cc385150fe99861253 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Fri, 15 Aug 2025 10:27:35 +0100 Subject: [PATCH 10/22] Initial implementation --- include/etl/not_null.h | 188 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 include/etl/not_null.h diff --git a/include/etl/not_null.h b/include/etl/not_null.h new file mode 100644 index 00000000..941a3ec8 --- /dev/null +++ b/include/etl/not_null.h @@ -0,0 +1,188 @@ +///\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_NOT_NULL_INCLUDED +#define ETL_NOT_NULL_INCLUDED + +#include "platform.h" +#include "error_handler.h" +#include "exception.h" +#include "ETL_STATIC_ASSERT.h" +#include "unique_ptr.h" +#include "type_traits.h" + +namespace etl +{ + //*************************************************************************** + /// The base class for not_null exceptions. + //*************************************************************************** + class not_null_exception : public exception + { + public: + + not_null_exception(string_type reason_, string_type file_name_, numeric_type line_number_) + : exception(reason_, file_name_, line_number_) + { + } + }; + + //*************************************************************************** + /// The exception when the not_null contains a null. + //*************************************************************************** + class not_null_contains_null : public not_null_exception + { + public: + + not_null_contains_null(string_type file_name_, numeric_type line_number_) + : delegate_exception(ETL_ERROR_TEXT("not_null:contains null", ETL_NOT_NULL_FILE_ID"A"), file_name_, line_number_) + { + } + }; + + // Primary template + template + class not_null; + + // Specialisation for T* + template + class not_null + { + public: + + explicit not_null(T* ptr_) + : ptr(ptr_) + { + ETL_ASSERT(ptr != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); + } + + not_null(const etl::not_null& other) + : ptr(other.get()) + { + } + + not_null& operator =(const etl::not_null& other) + { + ptr = other.get(); + + return *this; + } + + not_null& operator =(T* ptr_) + { + ETL_ASSERT(ptr_ != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); + + ptr = ptr_; + + return *this; + } + + T* get() const + { + return ptr; + } + + operator T*() const + { + return ptr; + } + + typename etl::remove_pointer::type& operator*() const + { + return *ptr; + } + + T operator->() const + { + return ptr; + } + + private: + + T* ptr; + }; + + // Partial specialisation for etl::unique_ptr + template + class not_null> + { + public: + + explicit not_null(etl::unique_ptr&& ptr_) + : ptr(etl::move(ptr_)) + { + ETL_ASSERT(ptr != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); + } + +#if ETL_USING_CPP11 + not_null& operator =(etl::unique_ptr&& ptr_) + { + ETL_ASSERT(ptr_ != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); + + ptr = etl::move(ptr_); + + return *this; + } +#endif + + T* get() const + { + return ptr.get(); + } + + operator T*() const + { + return ptr.get(); + } + + T& operator*() const + { + return *ptr; + } + + T* operator->() const + { + return ptr.get(); + } + + etl::unique_ptr& unique() + { + return ptr; + } + + const etl::unique_ptr& unique() const + { + return ptr; + } + + private: + + etl::unique_ptr ptr; + }; +} From 28d90aa80c7414a6cc9b92f0e1bbae0a6d781b5d Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Fri, 15 Aug 2025 17:18:15 +0100 Subject: [PATCH 11/22] Initial implementation --- include/etl/not_null.h | 226 ++++++++++++++++++-------- test/test_not_null_pointer.cpp | 152 +++++++++++++++++ test/test_not_null_unique_pointer.cpp | 174 ++++++++++++++++++++ test/vs2022/etl.vcxproj | 2 + test/vs2022/etl.vcxproj.filters | 6 + 5 files changed, 491 insertions(+), 69 deletions(-) create mode 100644 test/test_not_null_pointer.cpp create mode 100644 test/test_not_null_unique_pointer.cpp diff --git a/include/etl/not_null.h b/include/etl/not_null.h index 941a3ec8..54a4f565 100644 --- a/include/etl/not_null.h +++ b/include/etl/not_null.h @@ -34,8 +34,8 @@ SOFTWARE. #include "platform.h" #include "error_handler.h" #include "exception.h" -#include "ETL_STATIC_ASSERT.h" -#include "unique_ptr.h" +#include "static_assert.h" +#include "memory.h" #include "type_traits.h" namespace etl @@ -61,128 +61,216 @@ namespace etl public: not_null_contains_null(string_type file_name_, numeric_type line_number_) - : delegate_exception(ETL_ERROR_TEXT("not_null:contains null", ETL_NOT_NULL_FILE_ID"A"), file_name_, line_number_) + : not_null_exception(ETL_ERROR_TEXT("not_null:contains null", ETL_NOT_NULL_FILE_ID"A"), file_name_, line_number_) { } }; + //*************************************************************************** + // not_null // Primary template + //*************************************************************************** template class not_null; + //*************************************************************************** // Specialisation for T* + // A container for pointers that are not allowed to be null. + //*************************************************************************** template class not_null { public: + //********************************* + /// Constructs a not_null from a pointer. + /// Asserts if the pointer is null. + //********************************* explicit not_null(T* ptr_) : ptr(ptr_) { - ETL_ASSERT(ptr != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); + ETL_ASSERT(ptr_ != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); } - not_null(const etl::not_null& other) + //********************************* + /// Copy constructor from a not_null pointer. + //********************************* + not_null(const etl::not_null& other) : ptr(other.get()) { } - not_null& operator =(const etl::not_null& other) + //********************************* + /// Assignment from a not_null. + //********************************* + not_null& operator =(const etl::not_null& rhs) { - ptr = other.get(); + ptr = rhs.get(); return *this; } - not_null& operator =(T* ptr_) + //********************************* + /// Assignment from a pointer. + /// Asserts if the pointer is null. + //********************************* + not_null& operator =(T* rhs) { - ETL_ASSERT(ptr_ != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); + ETL_ASSERT_OR_RETURN_VALUE(rhs != ETL_NULLPTR, ETL_ERROR(not_null_contains_null), *this); - ptr = ptr_; + ptr = rhs; return *this; } + //********************************* + /// Gets the underlying pointer. + //********************************* T* get() const { return ptr; } + //********************************* + /// Implicit conversion to T*. + //********************************* operator T*() const { return ptr; } - typename etl::remove_pointer::type& operator*() const - { - return *ptr; - } - - T operator->() const - { - return ptr; - } - - private: - - T* ptr; - }; - - // Partial specialisation for etl::unique_ptr - template - class not_null> - { - public: - - explicit not_null(etl::unique_ptr&& ptr_) - : ptr(etl::move(ptr_)) - { - ETL_ASSERT(ptr != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); - } - -#if ETL_USING_CPP11 - not_null& operator =(etl::unique_ptr&& ptr_) - { - ETL_ASSERT(ptr_ != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); - - ptr = etl::move(ptr_); - - return *this; - } -#endif - - T* get() const - { - return ptr.get(); - } - - operator T*() const - { - return ptr.get(); - } - + //********************************* + /// Dereference operator. + //********************************* T& operator*() const { return *ptr; } + //********************************* + /// Arrow operator. + //********************************* T* operator->() const - { - return ptr.get(); - } - - etl::unique_ptr& unique() - { - return ptr; - } - - const etl::unique_ptr& unique() const { return ptr; } private: + + /// The underlying pointer. + T* ptr; + }; + + //*************************************************************************** + // Partial specialisation for etl::unique_ptr + // A container for unique_ptr that are not allowed to be null. + //*************************************************************************** + template + class not_null> + { + private: + + // The unique_ptr type. + typedef etl::unique_ptr unique_ptr_type; + + public: + + //********************************* + /// Constructs a not_null from a unique_ptr. + /// Asserts if the unique_ptr is null. + //********************************* + explicit not_null(unique_ptr_type&& u_ptr_) + : u_ptr(etl::move(u_ptr_)) + { + ETL_ASSERT(u_ptr.get() != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); + } + +#if ETL_USING_CPP11 + //********************************* + /// Constructs a not_null from a unique_ptr. + //********************************* + not_null(etl::not_null&& other) + : u_ptr(etl::move(other.u_ptr)) + { + } + + //********************************* + /// Assign from a unique_ptr. + /// Asserts if the unique_ptr is null. + //********************************* + not_null& operator =(unique_ptr_type&& rhs) + { + ETL_ASSERT_OR_RETURN_VALUE(rhs.get() != ETL_NULLPTR, ETL_ERROR(not_null_contains_null), *this); + + u_ptr = etl::move(rhs); + + return *this; + } + + //********************************* + /// Assign from a not_null. + //********************************* + not_null& operator =(etl::not_null&& rhs) + { + u_ptr = etl::move(rhs.u_ptr); + + return *this; + } +#endif + + //********************************* + /// Gets the underlying unique_ptr. + //********************************* + T* get() const + { + return u_ptr.get(); + } + + //********************************* + /// Implicit conversion to T*. + //********************************* + operator T*() const + { + return u_ptr.get(); + } - etl::unique_ptr ptr; + //********************************* + /// Dereference operator. + //********************************* + T& operator*() const + { + return *u_ptr; + } + + //********************************* + /// Arrow operator. + //********************************* + T* operator->() const + { + return u_ptr.get(); + } + + //********************************* + /// Gets the underlying unique_ptr. + //********************************* + unique_ptr_type& unique() + { + return u_ptr; + } + + //********************************* + /// Gets the underlying unique_ptr. + //********************************* + const unique_ptr_type& unique() const + { + return u_ptr; + } + + private: + + /// The underlying unique_ptr. + unique_ptr_type u_ptr; }; } + +#endif diff --git a/test/test_not_null_pointer.cpp b/test/test_not_null_pointer.cpp new file mode 100644 index 00000000..fd9d1683 --- /dev/null +++ b/test/test_not_null_pointer.cpp @@ -0,0 +1,152 @@ +/****************************************************************************** +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/not_null.h" + +namespace +{ + SUITE(test_not_null_pointer) + { + //************************************************************************* + TEST(test_construct_from_non_null_pointer) + { + int value = 42; + etl::not_null nn(&value); + CHECK_EQUAL(&value, nn.get()); + CHECK_EQUAL(42, *nn); + } + + //************************************************************************* + TEST(test_copy_construct) + { + int value = 123; + etl::not_null nn1(&value); + etl::not_null nn2(nn1); // Copy constructor + CHECK_EQUAL(&value, nn2.get()); + CHECK_EQUAL(123, *nn2); + } + + //************************************************************************* + TEST(test_assign_from_pointer) + { + int value1 = 123; + etl::not_null nn1(&value1); + + int value2 = 456; + + nn1 = &value2; + CHECK_EQUAL(&value2, nn1.get()); + CHECK_EQUAL(456, *nn1); + } + + //************************************************************************* + TEST(test_assign_from_not_null) + { + int value1 = 123; + etl::not_null nn1(&value1); + + int value2 = 456; + etl::not_null nn2(&value2); + + nn1 = nn2; + CHECK_EQUAL(&value2, nn2.get()); + CHECK_EQUAL(456, *nn2); + } + + //************************************************************************* + TEST(test_implicit_conversion) + { + struct S + { + int x; + }; + + S s{77}; + etl::not_null nn(&s); + + S* raw = nn; + CHECK_EQUAL(&s, raw); + } + + //************************************************************************* + TEST(test_arrow_operator) + { + struct S + { + int x; + + int get() const + { + return x; + } + }; + + S s{77}; + etl::not_null nn(&s); + + CHECK_EQUAL(s.x, nn->x); + CHECK_EQUAL(s.get(), nn->get()); + } + + //************************************************************************* + TEST(test_dereference_operator) + { + struct S + { + int x; + + int get() const + { + return x; + } + }; + + S s{77}; + etl::not_null nn(&s); + + CHECK_EQUAL(s.x, (*nn).x); + CHECK_EQUAL(s.get(), (*nn).get()); + } + + //************************************************************************* + TEST(test_construct_from_null_pointer_asserts) + { + CHECK_THROW(etl::not_null nn(nullptr), etl::not_null_contains_null); + } + + //************************************************************************* + TEST(test_assign_null_pointer_asserts) + { + int value = 1; + etl::not_null nn(&value); + + CHECK_THROW(nn = nullptr, etl::not_null_contains_null); + } + }; +} \ No newline at end of file diff --git a/test/test_not_null_unique_pointer.cpp b/test/test_not_null_unique_pointer.cpp new file mode 100644 index 00000000..8ad0f4b4 --- /dev/null +++ b/test/test_not_null_unique_pointer.cpp @@ -0,0 +1,174 @@ +/****************************************************************************** +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/not_null.h" + +namespace +{ + struct S + { + int x; + + int get() const + { + return x; + } + }; + + SUITE(test_not_null_unique_pointer) + { + //************************************************************************* + TEST(test_construct_from_non_null_unique_ptr) + { + using up_t = etl::unique_ptr; + up_t up(new int{ 123 }); + etl::not_null nn(etl::move(up)); + + CHECK_EQUAL(123, *nn); + CHECK_EQUAL(123, *nn.get()); + } + + //************************************************************************* + TEST(test_unique) + { + using up_t = etl::unique_ptr; + up_t up1(new int{ 123 }); + etl::not_null nn(etl::move(up1)); + + up_t up2 = etl::move(nn.unique()); + + CHECK_EQUAL(123, *up2.get()); + } + + //************************************************************************* + TEST(test_unique_const) + { + using up_t = etl::unique_ptr; + up_t up1(new int{ 123 }); + const etl::not_null nn(etl::move(up1)); + + const up_t& up2 = nn.unique(); + + CHECK_EQUAL(123, *up2.get()); + } + + //************************************************************************* + TEST(test_move_construct) + { + using up_t = etl::unique_ptr; + up_t up(new int{ 123 }); + + etl::not_null nn1(etl::move(up)); + etl::not_null nn2(etl::move(nn1)); // Move constructor + + CHECK_TRUE(nn1.get() == nullptr); + CHECK_EQUAL(123, *nn2.get()); + CHECK_EQUAL(123, *nn2); + } + + //************************************************************************* + TEST(test_assign_from_unique_ptr) + { + using up_t = etl::unique_ptr; + up_t up1(new int{ 123 }); + etl::not_null nn1(etl::move(up1)); + + using up_t = etl::unique_ptr; + up_t up2(new int); + *up2 = 456; + + nn1 = etl::move(up2); + + CHECK_EQUAL(456, *nn1.get()); + } + + //************************************************************************* + TEST(test_assign_from_not_null) + { + using up_t = etl::unique_ptr; + up_t up1(new int{ 123 }); + etl::not_null nn1(etl::move(up1)); + + up_t up2(new int{ 456 }); + etl::not_null nn2(etl::move(up2)); + + nn1 = etl::move(nn2); + + CHECK_TRUE(nn2.get() == nullptr); + CHECK_EQUAL(456, *nn1.get()); + } + + //************************************************************************* + TEST(test_implicit_conversion) + { + using up_t = etl::unique_ptr; + up_t up1(new S{ 123 }); + etl::not_null nn1(etl::move(up1)); + + S s = *nn1; + + CHECK_EQUAL(123, s.x); + } + + //************************************************************************* + TEST(test_arrow_operator) + { + S s{ 123 }; + + using up_t = etl::unique_ptr; + up_t up1(new S{ 123 }); + etl::not_null nn1(etl::move(up1)); + + CHECK_EQUAL(s.x, nn1->x); + CHECK_EQUAL(s.get(), nn1->get()); + } + + //************************************************************************* + TEST(test_dereference_operator) + { + S s{ 123 }; + + using up_t = etl::unique_ptr; + up_t up1(new S{ 123 }); + etl::not_null nn1(etl::move(up1)); + + CHECK_EQUAL(s.x, (*nn1).x); + CHECK_EQUAL(s.get(), (*nn1).get()); + } + + //************************************************************************* + TEST(test_construct_from_null_pointer_asserts) + { + using up_t = etl::unique_ptr; + up_t up1(nullptr); + + CHECK_THROW(etl::not_null nn1(etl::move(up1)), etl::not_null_contains_null); + } + } +} \ No newline at end of file diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 4639af36..13d90f26 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -9472,6 +9472,8 @@ + + diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index 5bdf23fe..281ff201 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -3701,6 +3701,12 @@ Tests\Maths + + Tests\Misc + + + Tests\Misc + From 877ef005eafd49af38c032db8274858cd97496a3 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Fri, 15 Aug 2025 18:04:50 +0100 Subject: [PATCH 12/22] Fixed file Id error Updated CMakeLists.txt for tests and syntax checks --- include/etl/file_error_numbers.h | 1 + include/etl/not_null.h | 51 ++++++++++++++++++------------ test/CMakeLists.txt | 2 ++ test/syntax_check/CMakeLists.txt | 1 + test/syntax_check/not_null.h.t.cpp | 29 +++++++++++++++++ test/vs2022/etl.vcxproj | 18 +++++++++++ test/vs2022/etl.vcxproj.filters | 18 ++--------- 7 files changed, 84 insertions(+), 36 deletions(-) create mode 100644 test/syntax_check/not_null.h.t.cpp diff --git a/include/etl/file_error_numbers.h b/include/etl/file_error_numbers.h index 5404828a..51a009e7 100644 --- a/include/etl/file_error_numbers.h +++ b/include/etl/file_error_numbers.h @@ -107,4 +107,5 @@ SOFTWARE. #define ETL_UNALIGNED_TYPE_FILE_ID "74" #define ETL_SPAN_FILE_ID "75" #define ETL_ALGORITHM_FILE_ID "76" +#define ETL_NOT_NULL_FILE_ID "77" #endif diff --git a/include/etl/not_null.h b/include/etl/not_null.h index 54a4f565..0387a35c 100644 --- a/include/etl/not_null.h +++ b/include/etl/not_null.h @@ -82,11 +82,17 @@ namespace etl { public: + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + //********************************* /// Constructs a not_null from a pointer. /// Asserts if the pointer is null. //********************************* - explicit not_null(T* ptr_) + explicit not_null(pointer ptr_) : ptr(ptr_) { ETL_ASSERT(ptr_ != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); @@ -114,7 +120,7 @@ namespace etl /// Assignment from a pointer. /// Asserts if the pointer is null. //********************************* - not_null& operator =(T* rhs) + not_null& operator =(pointer rhs) { ETL_ASSERT_OR_RETURN_VALUE(rhs != ETL_NULLPTR, ETL_ERROR(not_null_contains_null), *this); @@ -126,15 +132,15 @@ namespace etl //********************************* /// Gets the underlying pointer. //********************************* - T* get() const + pointer get() const { return ptr; } //********************************* - /// Implicit conversion to T*. + /// Implicit conversion to pointer. //********************************* - operator T*() const + operator pointer() const { return ptr; } @@ -142,7 +148,7 @@ namespace etl //********************************* /// Dereference operator. //********************************* - T& operator*() const + reference operator*() const { return *ptr; } @@ -150,7 +156,7 @@ namespace etl //********************************* /// Arrow operator. //********************************* - T* operator->() const + pointer operator->() const { return ptr; } @@ -158,7 +164,7 @@ namespace etl private: /// The underlying pointer. - T* ptr; + pointer ptr; }; //*************************************************************************** @@ -166,15 +172,19 @@ namespace etl // A container for unique_ptr that are not allowed to be null. //*************************************************************************** template - class not_null> + class not_null > { - private: - - // The unique_ptr type. - typedef etl::unique_ptr unique_ptr_type; - public: + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + + typedef etl::unique_ptr unique_ptr_type; + +#if ETL_USING_CPP11 //********************************* /// Constructs a not_null from a unique_ptr. /// Asserts if the unique_ptr is null. @@ -185,7 +195,6 @@ namespace etl ETL_ASSERT(u_ptr.get() != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); } -#if ETL_USING_CPP11 //********************************* /// Constructs a not_null from a unique_ptr. //********************************* @@ -219,17 +228,17 @@ namespace etl #endif //********************************* - /// Gets the underlying unique_ptr. + /// Gets the underlying ptr. //********************************* - T* get() const + pointer get() const { return u_ptr.get(); } //********************************* - /// Implicit conversion to T*. + /// Implicit conversion to pointer. //********************************* - operator T*() const + operator pointer() const { return u_ptr.get(); } @@ -237,7 +246,7 @@ namespace etl //********************************* /// Dereference operator. //********************************* - T& operator*() const + reference operator*() const { return *u_ptr; } @@ -245,7 +254,7 @@ namespace etl //********************************* /// Arrow operator. //********************************* - T* operator->() const + pointer operator->() const { return u_ptr.get(); } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a60856f7..5b3564f1 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -229,6 +229,8 @@ add_executable(etl_tests test_multi_span.cpp test_multi_vector.cpp test_murmur3.cpp + test_not_null_pointer.cpp + test_not_null_unique_pointer.cpp test_nth_type.cpp test_numeric.cpp test_observer.cpp diff --git a/test/syntax_check/CMakeLists.txt b/test/syntax_check/CMakeLists.txt index eb0deadf..e664a3a2 100644 --- a/test/syntax_check/CMakeLists.txt +++ b/test/syntax_check/CMakeLists.txt @@ -246,6 +246,7 @@ target_sources(tests PRIVATE murmur3.h.t.cpp mutex.h.t.cpp negative.h.t.cpp + not_null.h.t.cpp nth_type.h.t.cpp nullptr.h.t.cpp null_type.h.t.cpp diff --git a/test/syntax_check/not_null.h.t.cpp b/test/syntax_check/not_null.h.t.cpp new file mode 100644 index 00000000..8f44b76c --- /dev/null +++ b/test/syntax_check/not_null.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/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 13d90f26..6ae0e148 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -7462,6 +7462,24 @@ true true + + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true true diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index 281ff201..5c6910c2 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -196,27 +196,12 @@ {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} {a05ae045-3218-4ca2-9f25-08cc977898df} - - {3336d15c-7c22-4df0-a6b2-1eb605099a1a} - {c75cedd3-8b6c-4662-b965-aecbe7fd5d1c} @@ -3707,6 +3692,9 @@ Tests\Misc + + Tests\Syntax Checks\Source + From 2d22dfe23681c79f913e832f3d16fc366b4a4a04 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 16 Aug 2025 10:12:41 +0100 Subject: [PATCH 13/22] Changed unique() to underlying_type() Added underlying_type() to etl::not_null --- include/etl/not_null.h | 41 +++++++++++++++++++-------- test/test_not_null_pointer.cpp | 34 ++++++++++++++++++++++ test/test_not_null_unique_pointer.cpp | 8 +++--- test/vs2022/etl.vcxproj | 1 + 4 files changed, 68 insertions(+), 16 deletions(-) diff --git a/include/etl/not_null.h b/include/etl/not_null.h index 0387a35c..12cbf2e2 100644 --- a/include/etl/not_null.h +++ b/include/etl/not_null.h @@ -87,12 +87,13 @@ namespace etl typedef const T* const_pointer; typedef T& reference; typedef const T& const_reference; + typedef pointer underlying_type; //********************************* /// Constructs a not_null from a pointer. /// Asserts if the pointer is null. //********************************* - explicit not_null(pointer ptr_) + explicit not_null(underlying_type ptr_) : ptr(ptr_) { ETL_ASSERT(ptr_ != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); @@ -120,7 +121,7 @@ namespace etl /// Assignment from a pointer. /// Asserts if the pointer is null. //********************************* - not_null& operator =(pointer rhs) + not_null& operator =(underlying_type rhs) { ETL_ASSERT_OR_RETURN_VALUE(rhs != ETL_NULLPTR, ETL_ERROR(not_null_contains_null), *this); @@ -161,6 +162,22 @@ namespace etl return ptr; } + //********************************* + /// Gets a reference to the underlying pointer. + //********************************* + underlying_type& underlying() + { + return ptr; + } + + //********************************* + /// Gets a const_reference to the underlying pointer. + //********************************* + const underlying_type& underlying() const + { + return ptr; + } + private: /// The underlying pointer. @@ -182,14 +199,14 @@ namespace etl typedef T& reference; typedef const T& const_reference; - typedef etl::unique_ptr unique_ptr_type; + typedef etl::unique_ptr underlying_type;; #if ETL_USING_CPP11 //********************************* /// Constructs a not_null from a unique_ptr. /// Asserts if the unique_ptr is null. //********************************* - explicit not_null(unique_ptr_type&& u_ptr_) + explicit not_null(underlying_type&& u_ptr_) : u_ptr(etl::move(u_ptr_)) { ETL_ASSERT(u_ptr.get() != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); @@ -198,7 +215,7 @@ namespace etl //********************************* /// Constructs a not_null from a unique_ptr. //********************************* - not_null(etl::not_null&& other) + not_null(etl::not_null&& other) : u_ptr(etl::move(other.u_ptr)) { } @@ -207,7 +224,7 @@ namespace etl /// Assign from a unique_ptr. /// Asserts if the unique_ptr is null. //********************************* - not_null& operator =(unique_ptr_type&& rhs) + not_null& operator =(underlying_type&& rhs) { ETL_ASSERT_OR_RETURN_VALUE(rhs.get() != ETL_NULLPTR, ETL_ERROR(not_null_contains_null), *this); @@ -219,7 +236,7 @@ namespace etl //********************************* /// Assign from a not_null. //********************************* - not_null& operator =(etl::not_null&& rhs) + not_null& operator =(etl::not_null&& rhs) { u_ptr = etl::move(rhs.u_ptr); @@ -260,17 +277,17 @@ namespace etl } //********************************* - /// Gets the underlying unique_ptr. + /// Gets a reference to the underlying unique_ptr. //********************************* - unique_ptr_type& unique() + underlying_type& underlying() { return u_ptr; } //********************************* - /// Gets the underlying unique_ptr. + /// Gets a const_reference to the underlying unique_ptr. //********************************* - const unique_ptr_type& unique() const + const underlying_type& underlying() const { return u_ptr; } @@ -278,7 +295,7 @@ namespace etl private: /// The underlying unique_ptr. - unique_ptr_type u_ptr; + underlying_type u_ptr; }; } diff --git a/test/test_not_null_pointer.cpp b/test/test_not_null_pointer.cpp index fd9d1683..59a34038 100644 --- a/test/test_not_null_pointer.cpp +++ b/test/test_not_null_pointer.cpp @@ -79,6 +79,40 @@ namespace CHECK_EQUAL(456, *nn2); } + //************************************************************************* + TEST(test_underlying) + { + int value1 = 123; + etl::not_null nn1(&value1); + + int* p = nn1.underlying(); + + CHECK_EQUAL(123, *p); + } + + //************************************************************************* + TEST(test_underlying_const) + { + int value1 = 123; + const etl::not_null nn1(&value1); + + const int* p = nn1.underlying(); + + CHECK_EQUAL(123, *p); + } + + //************************************************************************* + TEST(test_unique_const) + { + using up_t = etl::unique_ptr; + up_t up1(new int{ 123 }); + const etl::not_null nn(etl::move(up1)); + + const up_t& up2 = nn.underlying(); + + CHECK_EQUAL(123, *up2.get()); + } + //************************************************************************* TEST(test_implicit_conversion) { diff --git a/test/test_not_null_unique_pointer.cpp b/test/test_not_null_unique_pointer.cpp index 8ad0f4b4..eef5fc00 100644 --- a/test/test_not_null_unique_pointer.cpp +++ b/test/test_not_null_unique_pointer.cpp @@ -55,25 +55,25 @@ namespace } //************************************************************************* - TEST(test_unique) + TEST(test_underlying) { using up_t = etl::unique_ptr; up_t up1(new int{ 123 }); etl::not_null nn(etl::move(up1)); - up_t up2 = etl::move(nn.unique()); + up_t up2 = etl::move(nn.underlying()); CHECK_EQUAL(123, *up2.get()); } //************************************************************************* - TEST(test_unique_const) + TEST(test_underlying_const) { using up_t = etl::unique_ptr; up_t up1(new int{ 123 }); const etl::not_null nn(etl::move(up1)); - const up_t& up2 = nn.unique(); + const up_t& up2 = etl::move(nn.underlying()); CHECK_EQUAL(123, *up2.get()); } diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 6ae0e148..3f5b01e7 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -3362,6 +3362,7 @@ + From 3bc87f1045ed09f818c1a5ad52705adfbc56ab62 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 16 Aug 2025 10:12:41 +0100 Subject: [PATCH 14/22] Changed unique() to underlying_type() Added underlying_type() to etl::not_null --- include/etl/not_null.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/etl/not_null.h b/include/etl/not_null.h index 12cbf2e2..54a5be6d 100644 --- a/include/etl/not_null.h +++ b/include/etl/not_null.h @@ -281,7 +281,7 @@ namespace etl //********************************* underlying_type& underlying() { - return u_ptr; + return etl::move(u_ptr); } //********************************* @@ -289,7 +289,7 @@ namespace etl //********************************* const underlying_type& underlying() const { - return u_ptr; + return etl::move(u_ptr); } private: From 3a25d5934ab52c63918f27edbf6d73659cb82427 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 17 Aug 2025 10:37:27 +0100 Subject: [PATCH 15/22] Added constexpr. Removed some member functions. Removed 'move' member functions for etl::not_null> --- include/etl/not_null.h | 131 +++++++------------ include/etl/platform.h | 12 +- test/CMakeLists.txt | 1 + test/test_not_null_pointer.cpp | 79 +++--------- test/test_not_null_pointer_constexpr.cpp | 154 +++++++++++++++++++++++ test/test_not_null_unique_pointer.cpp | 54 -------- test/vs2022/cpp.hint | 22 ++++ test/vs2022/etl.vcxproj | 1 + test/vs2022/etl.vcxproj.filters | 6 + 9 files changed, 253 insertions(+), 207 deletions(-) create mode 100644 test/test_not_null_pointer_constexpr.cpp diff --git a/include/etl/not_null.h b/include/etl/not_null.h index 54a5be6d..f92de6e5 100644 --- a/include/etl/not_null.h +++ b/include/etl/not_null.h @@ -47,7 +47,7 @@ namespace etl { public: - not_null_exception(string_type reason_, string_type file_name_, numeric_type line_number_) + not_null_exception(string_type reason_, string_type file_name_, numeric_type line_number_) ETL_NOEXCEPT_IF_NO_THROW : exception(reason_, file_name_, line_number_) { } @@ -60,7 +60,7 @@ namespace etl { public: - not_null_contains_null(string_type file_name_, numeric_type line_number_) + not_null_contains_null(string_type file_name_, numeric_type line_number_) ETL_NOEXCEPT_IF_NO_THROW : not_null_exception(ETL_ERROR_TEXT("not_null:contains null", ETL_NOT_NULL_FILE_ID"A"), file_name_, line_number_) { } @@ -93,47 +93,47 @@ namespace etl /// Constructs a not_null from a pointer. /// Asserts if the pointer is null. //********************************* - explicit not_null(underlying_type ptr_) + ETL_CONSTEXPR14 explicit not_null(underlying_type ptr_) ETL_NOEXCEPT_IF_NO_THROW : ptr(ptr_) { ETL_ASSERT(ptr_ != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); } //********************************* - /// Copy constructor from a not_null pointer. + /// Copy construct from a not_null pointer. //********************************* - not_null(const etl::not_null& other) + ETL_CONSTEXPR14 not_null(const etl::not_null& other) ETL_NOEXCEPT : ptr(other.get()) { } + //********************************* + /// Assignment from a pointer. + /// Asserts if the pointer is null. + //********************************* + ETL_CONSTEXPR14 not_null& operator =(underlying_type rhs) ETL_NOEXCEPT_IF_NO_THROW + { + ETL_ASSERT_OR_RETURN_VALUE(rhs != ETL_NULLPTR, ETL_ERROR(not_null_contains_null), *this); + + ptr = rhs; + + return *this; + } + //********************************* /// Assignment from a not_null. //********************************* - not_null& operator =(const etl::not_null& rhs) + ETL_CONSTEXPR14 not_null& operator =(const etl::not_null& rhs) ETL_NOEXCEPT { ptr = rhs.get(); return *this; } - //********************************* - /// Assignment from a pointer. - /// Asserts if the pointer is null. - //********************************* - not_null& operator =(underlying_type rhs) - { - ETL_ASSERT_OR_RETURN_VALUE(rhs != ETL_NULLPTR, ETL_ERROR(not_null_contains_null), *this); - - ptr = rhs; - - return *this; - } - //********************************* /// Gets the underlying pointer. //********************************* - pointer get() const + ETL_CONSTEXPR14 pointer get() const ETL_NOEXCEPT { return ptr; } @@ -141,7 +141,7 @@ namespace etl //********************************* /// Implicit conversion to pointer. //********************************* - operator pointer() const + ETL_CONSTEXPR14 operator pointer() const ETL_NOEXCEPT { return ptr; } @@ -149,31 +149,15 @@ namespace etl //********************************* /// Dereference operator. //********************************* - reference operator*() const + ETL_CONSTEXPR14 reference operator*() const ETL_NOEXCEPT { return *ptr; } - + //********************************* /// Arrow operator. //********************************* - pointer operator->() const - { - return ptr; - } - - //********************************* - /// Gets a reference to the underlying pointer. - //********************************* - underlying_type& underlying() - { - return ptr; - } - - //********************************* - /// Gets a const_reference to the underlying pointer. - //********************************* - const underlying_type& underlying() const + ETL_CONSTEXPR14 pointer operator->() const ETL_NOEXCEPT { return ptr; } @@ -191,6 +175,11 @@ namespace etl template class not_null > { + private: + + typedef etl::not_null > this_type; + typedef etl::unique_ptr underlying_type; + public: typedef T value_type; @@ -199,32 +188,24 @@ namespace etl typedef T& reference; typedef const T& const_reference; - typedef etl::unique_ptr underlying_type;; - #if ETL_USING_CPP11 //********************************* /// Constructs a not_null from a unique_ptr. - /// Asserts if the unique_ptr is null. + /// Asserts if the unique_ptr contains null. + /// Moves from the unique_ptr. //********************************* - explicit not_null(underlying_type&& u_ptr_) + ETL_CONSTEXPR14 explicit not_null(underlying_type&& u_ptr_) ETL_NOEXCEPT_IF_NO_THROW : u_ptr(etl::move(u_ptr_)) { ETL_ASSERT(u_ptr.get() != ETL_NULLPTR, ETL_ERROR(not_null_contains_null)); } - //********************************* - /// Constructs a not_null from a unique_ptr. - //********************************* - not_null(etl::not_null&& other) - : u_ptr(etl::move(other.u_ptr)) - { - } - //********************************* /// Assign from a unique_ptr. - /// Asserts if the unique_ptr is null. + /// Asserts if the unique_ptr contains null. + /// Moves from the unique_ptr. //********************************* - not_null& operator =(underlying_type&& rhs) + ETL_CONSTEXPR14 not_null& operator =(underlying_type&& rhs) ETL_NOEXCEPT_IF_NO_THROW { ETL_ASSERT_OR_RETURN_VALUE(rhs.get() != ETL_NULLPTR, ETL_ERROR(not_null_contains_null), *this); @@ -232,22 +213,12 @@ namespace etl return *this; } - - //********************************* - /// Assign from a not_null. - //********************************* - not_null& operator =(etl::not_null&& rhs) - { - u_ptr = etl::move(rhs.u_ptr); - - return *this; - } #endif //********************************* /// Gets the underlying ptr. //********************************* - pointer get() const + ETL_CONSTEXPR14 pointer get() const ETL_NOEXCEPT { return u_ptr.get(); } @@ -255,7 +226,7 @@ namespace etl //********************************* /// Implicit conversion to pointer. //********************************* - operator pointer() const + ETL_CONSTEXPR14 operator pointer() const ETL_NOEXCEPT { return u_ptr.get(); } @@ -263,7 +234,7 @@ namespace etl //********************************* /// Dereference operator. //********************************* - reference operator*() const + ETL_CONSTEXPR14 reference operator*() const ETL_NOEXCEPT { return *u_ptr; } @@ -271,29 +242,21 @@ namespace etl //********************************* /// Arrow operator. //********************************* - pointer operator->() const + ETL_CONSTEXPR14 pointer operator->() const ETL_NOEXCEPT { return u_ptr.get(); } - //********************************* - /// Gets a reference to the underlying unique_ptr. - //********************************* - underlying_type& underlying() - { - return etl::move(u_ptr); - } - - //********************************* - /// Gets a const_reference to the underlying unique_ptr. - //********************************* - const underlying_type& underlying() const - { - return etl::move(u_ptr); - } - private: + ETL_CONSTEXPR14 explicit not_null(const this_type& u_ptr_) ETL_NOEXCEPT ETL_DELETE; + ETL_CONSTEXPR14 not_null& operator=(const this_type& rhs) ETL_NOEXCEPT ETL_DELETE; + +#if ETL_USING_CPP11 + ETL_CONSTEXPR14 explicit not_null(this_type&& u_ptr_) ETL_NOEXCEPT = delete; + ETL_CONSTEXPR14 not_null& operator=(this_type&& rhs) ETL_NOEXCEPT = delete; +#endif + /// The underlying unique_ptr. underlying_type u_ptr; }; diff --git a/include/etl/platform.h b/include/etl/platform.h index 248a19f4..bcebdf89 100644 --- a/include/etl/platform.h +++ b/include/etl/platform.h @@ -331,13 +331,15 @@ 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_NOEXCEPT noexcept + #define ETL_NOEXCEPT_EXPR(...) noexcept(__VA_ARGS__) - #if ETL_USING_EXCEPTIONS - #define ETL_NOEXCEPT noexcept - #define ETL_NOEXCEPT_EXPR(...) noexcept(__VA_ARGS__) + #if ETL_NOT_USING_EXCEPTIONS + #define ETL_NOEXCEPT_IF_NO_THROW noexcept + #define ETL_NOEXCEPT_IF_NO_THROW_EXPR(...) noexcept(__VA_ARGS__) #else - #define ETL_NOEXCEPT - #define ETL_NOEXCEPT_EXPR(...) + #define ETL_NOEXCEPT_IF_NO_THROW + #define ETL_NOEXCEPT_IF_NO_THROW_EXPR(...) #endif #else #define ETL_CONSTEXPR diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5b3564f1..61c01e47 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -230,6 +230,7 @@ add_executable(etl_tests test_multi_vector.cpp test_murmur3.cpp test_not_null_pointer.cpp + test_not_null_pointer_constexpr.cpp test_not_null_unique_pointer.cpp test_nth_type.cpp test_numeric.cpp diff --git a/test/test_not_null_pointer.cpp b/test/test_not_null_pointer.cpp index 59a34038..546a6098 100644 --- a/test/test_not_null_pointer.cpp +++ b/test/test_not_null_pointer.cpp @@ -31,15 +31,25 @@ SOFTWARE. namespace { + struct S + { + int x; + + int get() const + { + return x; + } + }; + SUITE(test_not_null_pointer) { //************************************************************************* TEST(test_construct_from_non_null_pointer) { - int value = 42; + int value = 123; etl::not_null nn(&value); CHECK_EQUAL(&value, nn.get()); - CHECK_EQUAL(42, *nn); + CHECK_EQUAL(123, *nn); } //************************************************************************* @@ -79,49 +89,10 @@ namespace CHECK_EQUAL(456, *nn2); } - //************************************************************************* - TEST(test_underlying) - { - int value1 = 123; - etl::not_null nn1(&value1); - - int* p = nn1.underlying(); - - CHECK_EQUAL(123, *p); - } - - //************************************************************************* - TEST(test_underlying_const) - { - int value1 = 123; - const etl::not_null nn1(&value1); - - const int* p = nn1.underlying(); - - CHECK_EQUAL(123, *p); - } - - //************************************************************************* - TEST(test_unique_const) - { - using up_t = etl::unique_ptr; - up_t up1(new int{ 123 }); - const etl::not_null nn(etl::move(up1)); - - const up_t& up2 = nn.underlying(); - - CHECK_EQUAL(123, *up2.get()); - } - //************************************************************************* TEST(test_implicit_conversion) { - struct S - { - int x; - }; - - S s{77}; + S s{123}; etl::not_null nn(&s); S* raw = nn; @@ -131,17 +102,7 @@ namespace //************************************************************************* TEST(test_arrow_operator) { - struct S - { - int x; - - int get() const - { - return x; - } - }; - - S s{77}; + S s{123}; etl::not_null nn(&s); CHECK_EQUAL(s.x, nn->x); @@ -151,17 +112,7 @@ namespace //************************************************************************* TEST(test_dereference_operator) { - struct S - { - int x; - - int get() const - { - return x; - } - }; - - S s{77}; + S s{123}; etl::not_null nn(&s); CHECK_EQUAL(s.x, (*nn).x); diff --git a/test/test_not_null_pointer_constexpr.cpp b/test/test_not_null_pointer_constexpr.cpp new file mode 100644 index 00000000..5cf53881 --- /dev/null +++ b/test/test_not_null_pointer_constexpr.cpp @@ -0,0 +1,154 @@ +/****************************************************************************** +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/not_null.h" + +#if ETL_USING_CPP14 +namespace +{ + struct S + { + int x; + + constexpr int get() const + { + return x; + } + }; + + //************************************************************************* + constexpr etl::not_null CreateNotNullAssignFromPointer(const int* p1, const int* p2) + { + // Create a not_null pointer from a pointer. + etl::not_null nn(p1); + + // Assign a different pointer to the not_null. + nn = p2; + + return nn; + } + + //************************************************************************* + constexpr etl::not_null CreateNotNullAssignFromNotNull(const int* p1, const int* p2) + { + // Create a not_null pointer from a pointer. + etl::not_null nn1(p1); + etl::not_null nn2(p2); + + nn1 = nn2; + + return nn1; + } + + SUITE(test_not_null_pointer) + { + //************************************************************************* + TEST(test_construct_from_non_null_pointer) + { + static constexpr const int value = 123; + static constexpr etl::not_null nn(&value); + static constexpr const int* p = nn.get(); + static constexpr const int v = *nn; + CHECK_EQUAL(&value, p); + CHECK_EQUAL(123, v); + } + + //************************************************************************* + TEST(test_copy_construct) + { + static constexpr const int value = 123; + static constexpr etl::not_null nn1(&value); + static constexpr etl::not_null nn2(nn1); // Copy constructor + static constexpr const int* p = nn2.get(); + static constexpr const int v = *nn2; + CHECK_EQUAL(&value, p); + CHECK_EQUAL(123, v); + } + + //************************************************************************* + TEST(test_assign_from_pointer) + { + static constexpr const int value1 = 123; + static constexpr const int value2 = 456; + static constexpr etl::not_null nn(CreateNotNullAssignFromPointer(&value1, &value2)); + + CHECK_EQUAL(&value2, nn.get()); + CHECK_EQUAL(456, *nn); + } + + //************************************************************************* + TEST(test_assign_from_not_null) + { + static constexpr const int value1 = 123; + static constexpr const int value2 = 456; + static constexpr etl::not_null nn(CreateNotNullAssignFromNotNull(&value1, &value2)); + + CHECK_EQUAL(&value2, nn.get()); + CHECK_EQUAL(456, *nn); + } + + //************************************************************************* + TEST(test_implicit_conversion) + { + static constexpr const S s{123}; + static constexpr etl::not_null nn(&s); + + static constexpr const S* raw = nn; + CHECK_EQUAL(&s, raw); + } + + //************************************************************************* + TEST(test_arrow_operator) + { + static constexpr const S s{123}; + static constexpr etl::not_null nn(&s); + + static constexpr int x1 = nn->x; + static constexpr int x2 = nn->get(); + + CHECK_EQUAL(s.x, x1); + CHECK_EQUAL(s.get(), x2); + } + + //************************************************************************* + TEST(test_dereference_operator) + { + static constexpr const S s{123}; + static constexpr etl::not_null nn(&s); + + static constexpr int x1 = (*nn).x; + static constexpr int x2 = (*nn).get(); + + CHECK_EQUAL(s.x, x1); + CHECK_EQUAL(s.get(), x2); + } + }; +} + +#endif diff --git a/test/test_not_null_unique_pointer.cpp b/test/test_not_null_unique_pointer.cpp index eef5fc00..b707b5a4 100644 --- a/test/test_not_null_unique_pointer.cpp +++ b/test/test_not_null_unique_pointer.cpp @@ -54,44 +54,6 @@ namespace CHECK_EQUAL(123, *nn.get()); } - //************************************************************************* - TEST(test_underlying) - { - using up_t = etl::unique_ptr; - up_t up1(new int{ 123 }); - etl::not_null nn(etl::move(up1)); - - up_t up2 = etl::move(nn.underlying()); - - CHECK_EQUAL(123, *up2.get()); - } - - //************************************************************************* - TEST(test_underlying_const) - { - using up_t = etl::unique_ptr; - up_t up1(new int{ 123 }); - const etl::not_null nn(etl::move(up1)); - - const up_t& up2 = etl::move(nn.underlying()); - - CHECK_EQUAL(123, *up2.get()); - } - - //************************************************************************* - TEST(test_move_construct) - { - using up_t = etl::unique_ptr; - up_t up(new int{ 123 }); - - etl::not_null nn1(etl::move(up)); - etl::not_null nn2(etl::move(nn1)); // Move constructor - - CHECK_TRUE(nn1.get() == nullptr); - CHECK_EQUAL(123, *nn2.get()); - CHECK_EQUAL(123, *nn2); - } - //************************************************************************* TEST(test_assign_from_unique_ptr) { @@ -108,22 +70,6 @@ namespace CHECK_EQUAL(456, *nn1.get()); } - //************************************************************************* - TEST(test_assign_from_not_null) - { - using up_t = etl::unique_ptr; - up_t up1(new int{ 123 }); - etl::not_null nn1(etl::move(up1)); - - up_t up2(new int{ 456 }); - etl::not_null nn2(etl::move(up2)); - - nn1 = etl::move(nn2); - - CHECK_TRUE(nn2.get() == nullptr); - CHECK_EQUAL(456, *nn1.get()); - } - //************************************************************************* TEST(test_implicit_conversion) { diff --git a/test/vs2022/cpp.hint b/test/vs2022/cpp.hint index 6aeae32e..0169bdca 100644 --- a/test/vs2022/cpp.hint +++ b/test/vs2022/cpp.hint @@ -38,3 +38,25 @@ #define CHECK_ARRAY_EQUAL #define CHECK_CLOSE #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_NOEXCEPT_IF_NO_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_NOEXCEPT +// 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_UNLIKELY {etl::error_handler::error((e)); throw((e));}} +#define ETL_ASSERT(b, e) {if (!(b)) ETL_UNLIKELY {throw((e));}} +#define ETL_ASSERT(b, e) {if (!(b)) ETL_UNLIKELY {etl::error_handler::error((e));}} +#define ETL_ASSERT(b, e) assert((b)) +#define ETL_ASSERT(b, e) {if (!(b)) ETL_UNLIKELY {etl::private_error_handler::assert_handler<0>::assert_function_ptr((e));}} +// 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_ERROR(e) (e(__FILE__, __LINE__)) +#define ETL_ERROR(e) (e("", __LINE__)) diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 3f5b01e7..bd18afdf 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -9492,6 +9492,7 @@ + diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index 5c6910c2..7e7037be 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -1521,6 +1521,9 @@ ETL\Frameworks + + ETL\Utilities + @@ -3695,6 +3698,9 @@ Tests\Syntax Checks\Source + + Tests\Misc + From ac1d2c82d17f15e06961c647835b68ee7018ad6a Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 18 Aug 2025 17:13:07 +0100 Subject: [PATCH 16/22] Added not_null comparison tests --- test/test_not_null_pointer.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/test_not_null_pointer.cpp b/test/test_not_null_pointer.cpp index 546a6098..d9835846 100644 --- a/test/test_not_null_pointer.cpp +++ b/test/test_not_null_pointer.cpp @@ -133,5 +133,32 @@ namespace CHECK_THROW(nn = nullptr, etl::not_null_contains_null); } + + //************************************************************************* + TEST(test_non_null_comparisons) + { + int value[2] = { 123, 456 }; + etl::not_null nn1(&value[0]); + etl::not_null nn2(&value[1]); + CHECK_TRUE(nn1 == nn1); + CHECK_TRUE(nn1 != nn2); + CHECK_TRUE(nn2 != nn1); + + CHECK_FALSE(nn1 < nn1); + CHECK_TRUE(nn1 < nn2); + CHECK_FALSE(nn2 < nn1); + + CHECK_TRUE(nn1 <= nn1); + CHECK_TRUE(nn1 <= nn2); + CHECK_FALSE(nn2 <= nn1); + + CHECK_FALSE(nn1 > nn1); + CHECK_FALSE(nn1 > nn2); + CHECK_TRUE(nn2 > nn1); + + CHECK_TRUE(nn1 >= nn1); + CHECK_FALSE(nn1 >= nn2); + CHECK_TRUE(nn2 >= nn1); + } }; } \ No newline at end of file From 44ec1e4f25110e5144df2106f82dd4827df0d3c4 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 18 Aug 2025 17:34:53 +0100 Subject: [PATCH 17/22] Updated release notes --- support/Release notes.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/support/Release notes.txt b/support/Release notes.txt index 7264cd87..cc75c3cb 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -5,6 +5,8 @@ Updates: Added 'emplace' constructor to etl::optional Added etl::delegate_observable Added return_type and argument_types to etl::delegate +Added etl::nontype_t<> +Added etl::not_null<> #1054 Using #pragma once #1159 etl::fsm helper to check states id sequence at compile time #1160 Feature request: rounded division (similar to scaled rounding) From 5f37af3f83e07bf4ada30df31ca385b5af00fabc Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 18 Aug 2025 19:44:51 +0100 Subject: [PATCH 18/22] Changed release() to destroy() to match create() --- examples/UniquePtrWithPool/Main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/UniquePtrWithPool/Main.cpp b/examples/UniquePtrWithPool/Main.cpp index 1b267c48..2fc7e4bd 100644 --- a/examples/UniquePtrWithPool/Main.cpp +++ b/examples/UniquePtrWithPool/Main.cpp @@ -25,7 +25,7 @@ struct Deleter if (ptr) { std::cout << "Releasing S(" << ptr->a << ", " << ptr->b << ") back to pool." << std::endl; - pool->release(ptr); + pool->destroy(ptr); } } From fb6c42ec789464c26a4c813e867785bf2912f600 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 18 Aug 2025 19:45:40 +0100 Subject: [PATCH 19/22] Fixed ETL_NOEXCEPT_IF_NO_THROW and #define ETL_NOEXCEPT_IF_NO_THROW_EXPR(...) for C++03 --- include/etl/platform.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/etl/platform.h b/include/etl/platform.h index bcebdf89..84480311 100644 --- a/include/etl/platform.h +++ b/include/etl/platform.h @@ -356,6 +356,8 @@ SOFTWARE. #define ETL_ENUM_CLASS(name) enum name #define ETL_ENUM_CLASS_TYPE(name, type) enum name #define ETL_LVALUE_REF_QUALIFIER + #define ETL_NOEXCEPT_IF_NO_THROW + #define ETL_NOEXCEPT_IF_NO_THROW_EXPR(...) #endif //************************************* From 4d5cb98d29a54c5e2b523cd6d470a606a69c946c Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 18 Aug 2025 19:45:40 +0100 Subject: [PATCH 20/22] Fixed ETL_NOEXCEPT_IF_NO_THROW and #define ETL_NOEXCEPT_IF_NO_THROW_EXPR(...) for C++03 Updated example Added releaser and destroyer functors to etl::ipool to simplify integration with etl::unique_ptr --- examples/UniquePtrWithPool/Main.cpp | 2 + include/etl/generic_pool.h | 6 +- include/etl/ipool.h | 52 ++++++++++++ include/etl/platform.h | 2 + test/test_pool.cpp | 123 ++++++++++++++++++++++++++++ 5 files changed, 181 insertions(+), 4 deletions(-) diff --git a/examples/UniquePtrWithPool/Main.cpp b/examples/UniquePtrWithPool/Main.cpp index 2fc7e4bd..1ac0d04a 100644 --- a/examples/UniquePtrWithPool/Main.cpp +++ b/examples/UniquePtrWithPool/Main.cpp @@ -15,6 +15,8 @@ struct S }; // Custom deleter that returns S* to the pool +// This class is defined to be able to log the release of objects back to the pool. +// Normally, you would use the predefined etl::ipool::destroyer struct Deleter { Deleter(etl::pool& p) diff --git a/include/etl/generic_pool.h b/include/etl/generic_pool.h index ef393597..759ee7e5 100644 --- a/include/etl/generic_pool.h +++ b/include/etl/generic_pool.h @@ -170,8 +170,7 @@ namespace etl { ETL_STATIC_ASSERT(etl::alignment_of::value <= VAlignment, "Type has incompatible alignment"); ETL_STATIC_ASSERT(sizeof(U) <= VTypeSize, "Type too large for pool"); - p_object->~U(); - ipool::release(p_object); + ipool::destroy(p_object); } private: @@ -338,8 +337,7 @@ namespace etl { ETL_STATIC_ASSERT(etl::alignment_of::value <= VAlignment, "Type has incompatible alignment"); ETL_STATIC_ASSERT(sizeof(U) <= VTypeSize, "Type too large for pool"); - p_object->~U(); - ipool::release(p_object); + ipool::destroy(p_object); } private: diff --git a/include/etl/ipool.h b/include/etl/ipool.h index 43e5f5bd..2fe066bb 100644 --- a/include/etl/ipool.h +++ b/include/etl/ipool.h @@ -271,6 +271,58 @@ namespace etl const_iterator(value_type p, pool_type* pool_) : ipool_iterator(p, pool_) {} }; + //*************************************************************************** + /// A releaser is a functor that releases an object back to the pool. + //*************************************************************************** + class releaser + { + public: + + releaser(etl::ipool& p) + : pool(&p) + { + } + + template + void operator()(const T* const p_object) const + { + if (p_object) + { + pool->release(p_object); + } + } + + private: + + etl::ipool* pool; + }; + + //*************************************************************************** + /// A destroyer is a functor that destroys an object and releases it back to the pool. + //*************************************************************************** + class destroyer + { + public: + + destroyer(etl::ipool& p) + : pool(&p) + { + } + + template + void operator()(const T* const p_object) const + { + if (p_object) + { + pool->destroy(p_object); + } + } + + private: + + etl::ipool* pool; + }; + //*************************************************************************** iterator begin() { diff --git a/include/etl/platform.h b/include/etl/platform.h index bcebdf89..84480311 100644 --- a/include/etl/platform.h +++ b/include/etl/platform.h @@ -356,6 +356,8 @@ SOFTWARE. #define ETL_ENUM_CLASS(name) enum name #define ETL_ENUM_CLASS_TYPE(name, type) enum name #define ETL_LVALUE_REF_QUALIFIER + #define ETL_NOEXCEPT_IF_NO_THROW + #define ETL_NOEXCEPT_IF_NO_THROW_EXPR(...) #endif //************************************* diff --git a/test/test_pool.cpp b/test/test_pool.cpp index 1cf1da7f..5f6d76ab 100644 --- a/test/test_pool.cpp +++ b/test/test_pool.cpp @@ -37,6 +37,7 @@ SOFTWARE. #include "etl/unaligned_type.h" #include "etl/pool.h" #include "etl/largest.h" +#include "etl/memory.h" typedef TestDataDC Test_Data; typedef TestDataNDC Test_Data2; @@ -156,6 +157,39 @@ namespace return os; } + struct S + { + S() + : a(7), b(8) + { + ++instance_count; + } + + S(int a_, double b_) + : a(a_), b(b_) + { + ++instance_count; + } + + S(const S& other) + : a(other.a), b(other.b) + { + ++instance_count; + } + + ~S() + { + --instance_count; + } + + int a; + double b; + + static int instance_count; + }; + + int S::instance_count = 0; + SUITE(test_pool) { //************************************************************************* @@ -735,4 +769,93 @@ namespace CHECK(!(begin != end)); CHECK_EQUAL(etl::distance(begin, end), 0); } + + //************************************************************************* + TEST(test_releaser_functor_with_unique_ptr) + { + etl::pool pool; + using Deleter = etl::ipool::releaser; + Deleter pool_deleter(pool); + 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()); + + { + 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(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; + using Deleter = etl::ipool::destroyer; + Deleter pool_deleter(pool); + 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(0, S::instance_count); + CHECK_EQUAL(10, pool.available()); + } } From 2a970134dad98240ea83cf37d6ef32404c64c274 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 19 Aug 2025 16:01:46 +0100 Subject: [PATCH 21/22] Removed releaser and destroyer in favour of lambdas and similar --- examples/UniquePtrWithPool/Main.cpp | 28 ++++------------ include/etl/ipool.h | 52 ----------------------------- test/test_pool.cpp | 10 +++--- 3 files changed, 10 insertions(+), 80 deletions(-) diff --git a/examples/UniquePtrWithPool/Main.cpp b/examples/UniquePtrWithPool/Main.cpp index 1ac0d04a..c3172ff9 100644 --- a/examples/UniquePtrWithPool/Main.cpp +++ b/examples/UniquePtrWithPool/Main.cpp @@ -14,31 +14,15 @@ struct S double b; }; -// Custom deleter that returns S* to the pool -// This class is defined to be able to log the release of objects back to the pool. -// Normally, you would use the predefined etl::ipool::destroyer -struct Deleter -{ - Deleter(etl::pool& p) - : pool(&p) {} - - void operator()(S* ptr) const - { - if (ptr) - { - std::cout << "Releasing S(" << ptr->a << ", " << ptr->b << ") back to pool." << std::endl; - pool->destroy(ptr); - } - } - - etl::pool* pool; -}; - int main() { etl::pool pool; - Deleter pool_deleter(pool); - using Unique = etl::unique_ptr; + auto pool_deleter = [&pool](auto ptr) + { + std::cout << "Releasing S(" << ptr->a << ", " << ptr->b << ") back to pool." << std::endl; + pool.destroy(ptr); + }; + using Unique = etl::unique_ptr; Unique us1(pool.create(1, 2), pool_deleter); std::cout << "Created S(" << us1->a << ", " << us1->b << ") from pool." << std::endl; diff --git a/include/etl/ipool.h b/include/etl/ipool.h index 2fe066bb..43e5f5bd 100644 --- a/include/etl/ipool.h +++ b/include/etl/ipool.h @@ -271,58 +271,6 @@ namespace etl const_iterator(value_type p, pool_type* pool_) : ipool_iterator(p, pool_) {} }; - //*************************************************************************** - /// A releaser is a functor that releases an object back to the pool. - //*************************************************************************** - class releaser - { - public: - - releaser(etl::ipool& p) - : pool(&p) - { - } - - template - void operator()(const T* const p_object) const - { - if (p_object) - { - pool->release(p_object); - } - } - - private: - - etl::ipool* pool; - }; - - //*************************************************************************** - /// A destroyer is a functor that destroys an object and releases it back to the pool. - //*************************************************************************** - class destroyer - { - public: - - destroyer(etl::ipool& p) - : pool(&p) - { - } - - template - void operator()(const T* const p_object) const - { - if (p_object) - { - pool->destroy(p_object); - } - } - - private: - - etl::ipool* pool; - }; - //*************************************************************************** iterator begin() { diff --git a/test/test_pool.cpp b/test/test_pool.cpp index 5f6d76ab..df9b088c 100644 --- a/test/test_pool.cpp +++ b/test/test_pool.cpp @@ -774,9 +774,8 @@ namespace TEST(test_releaser_functor_with_unique_ptr) { etl::pool pool; - using Deleter = etl::ipool::releaser; - Deleter pool_deleter(pool); - using Unique = etl::unique_ptr; + auto pool_deleter = [&pool](S* ptr) { pool.release(ptr); }; + using Unique = etl::unique_ptr; S::instance_count = 0; @@ -823,9 +822,8 @@ namespace TEST(test_destroyer_functor_with_unique_ptr) { etl::pool pool; - using Deleter = etl::ipool::destroyer; - Deleter pool_deleter(pool); - using Unique = etl::unique_ptr; + auto pool_deleter = [&pool](S* ptr) { pool.destroy(ptr); }; + using Unique = etl::unique_ptr; S::instance_count = 0; From cde5bcff69fa471093b4d868a379e35a7a69e6d1 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 19 Aug 2025 18:50:57 +0100 Subject: [PATCH 22/22] Updated release notes and version --- arduino/library-arduino.json | 2 +- arduino/library-arduino.properties | 2 +- include/etl/version.h | 4 ++-- library.json | 2 +- library.properties | 2 +- scripts/update_release.bat | 2 +- scripts/update_version.bat | 2 +- version.txt | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/arduino/library-arduino.json b/arduino/library-arduino.json index de1489c8..7ffd4913 100644 --- a/arduino/library-arduino.json +++ b/arduino/library-arduino.json @@ -1,6 +1,6 @@ { "name": "Embedded Template Library ETL", - "version": "20.42.2", + "version": "20.43.0", "authors": { "name": "John Wellbelove", "email": "john.wellbelove@etlcpp.com" diff --git a/arduino/library-arduino.properties b/arduino/library-arduino.properties index 94f7f45d..2b38100f 100644 --- a/arduino/library-arduino.properties +++ b/arduino/library-arduino.properties @@ -1,5 +1,5 @@ name=Embedded Template Library ETL -version=20.42.2 +version=20.43.0 author= John Wellbelove maintainer=John Wellbelove license=MIT diff --git a/include/etl/version.h b/include/etl/version.h index bf700e40..d435a5e3 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 42 -#define ETL_VERSION_PATCH 2 +#define ETL_VERSION_MINOR 43 +#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 f1eb7c56..792e9e37 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "Embedded Template Library", - "version": "20.42.2", + "version": "20.43.0", "authors": { "name": "John Wellbelove", "email": "john.wellbelove@etlcpp.com" diff --git a/library.properties b/library.properties index 0e68abaf..d328465c 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library -version=20.42.2 +version=20.43.0 author= John Wellbelove maintainer=John Wellbelove license=MIT diff --git a/scripts/update_release.bat b/scripts/update_release.bat index 26baad0a..51a96247 100644 --- a/scripts/update_release.bat +++ b/scripts/update_release.bat @@ -1 +1 @@ -python .\update_release.py +python3 ./update_release.py diff --git a/scripts/update_version.bat b/scripts/update_version.bat index 73bf64fb..61824e5a 100644 --- a/scripts/update_version.bat +++ b/scripts/update_version.bat @@ -1 +1 @@ -python .\update_version.py +python3 ./update_version.py diff --git a/version.txt b/version.txt index ba8bfd08..36452a4c 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -20.42.2 +20.43.0