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 +