From 9c046b710c7b3ec51bbb6cb3991da0c376e77ff2 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Fri, 15 Aug 2025 10:27:35 +0100 Subject: [PATCH 1/6] 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 2/6] 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 3/6] 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 d7585508da860616403ec0e2b84fbcf0877b6244 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 16 Aug 2025 10:12:41 +0100 Subject: [PATCH 4/6] 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 5/6] 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 6/6] 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 +