From b96c2a9ecd5e38d946af21d4e990ee87e817d87a Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Mon, 27 Apr 2026 22:49:39 +0200 Subject: [PATCH 1/8] Consolidate Dockerfile non-root user to vscode (#1417) Previously, we had differently named default users in the containers. --- .devcontainer/armhf/Dockerfile | 2 +- .devcontainer/i386/Dockerfile | 2 +- .devcontainer/powerpc/Dockerfile | 2 +- .devcontainer/riscv64/Dockerfile | 2 +- .devcontainer/s390x/Dockerfile | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.devcontainer/armhf/Dockerfile b/.devcontainer/armhf/Dockerfile index 7d5632a6..7d555f36 100644 --- a/.devcontainer/armhf/Dockerfile +++ b/.devcontainer/armhf/Dockerfile @@ -24,7 +24,7 @@ RUN dpkg --add-architecture armhf && \ && rm -rf /var/lib/apt/lists/* # Create non-root user with stable UID/GID -ARG USERNAME=devuser +ARG USERNAME=vscode ARG USER_UID=1000 ARG USER_GID=1000 diff --git a/.devcontainer/i386/Dockerfile b/.devcontainer/i386/Dockerfile index 99223eb9..bace68cd 100644 --- a/.devcontainer/i386/Dockerfile +++ b/.devcontainer/i386/Dockerfile @@ -24,7 +24,7 @@ RUN dpkg --add-architecture i386 && \ && rm -rf /var/lib/apt/lists/* # Create non-root user with stable UID/GID -ARG USERNAME=devuser +ARG USERNAME=vscode ARG USER_UID=1000 ARG USER_GID=1000 diff --git a/.devcontainer/powerpc/Dockerfile b/.devcontainer/powerpc/Dockerfile index a74cb690..faa94096 100644 --- a/.devcontainer/powerpc/Dockerfile +++ b/.devcontainer/powerpc/Dockerfile @@ -49,7 +49,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ && rm -rf /var/lib/apt/lists/* # Create non-root user with stable UID/GID -ARG USERNAME=devuser +ARG USERNAME=vscode ARG USER_UID=1000 ARG USER_GID=1000 diff --git a/.devcontainer/riscv64/Dockerfile b/.devcontainer/riscv64/Dockerfile index 081e42ed..7d07cdda 100644 --- a/.devcontainer/riscv64/Dockerfile +++ b/.devcontainer/riscv64/Dockerfile @@ -24,7 +24,7 @@ RUN dpkg --add-architecture riscv64 && \ && rm -rf /var/lib/apt/lists/* # Create non-root user with stable UID/GID -ARG USERNAME=devuser +ARG USERNAME=vscode ARG USER_UID=1000 ARG USER_GID=1000 diff --git a/.devcontainer/s390x/Dockerfile b/.devcontainer/s390x/Dockerfile index f8c6ff87..5656bc1d 100644 --- a/.devcontainer/s390x/Dockerfile +++ b/.devcontainer/s390x/Dockerfile @@ -24,7 +24,7 @@ RUN dpkg --add-architecture s390x && \ && rm -rf /var/lib/apt/lists/* # Create non-root user with stable UID/GID -ARG USERNAME=devuser +ARG USERNAME=vscode ARG USER_UID=1000 ARG USER_GID=1000 From 43e97b7f3cdcb0aefbeff4934ab746b9594941c9 Mon Sep 17 00:00:00 2001 From: Joris Putcuyps Date: Tue, 28 Apr 2026 09:30:23 +0200 Subject: [PATCH 2/8] Expected actually doesn't require a monostate. (#1413) * Print test names at test time (#1343) * Fix operator| conflict with std::ranges (#1395) * Expected actually doesn't require a monostate. * Better naming, since uninitialised isn't an option for expected. --------- Co-authored-by: Roland Reichwein Co-authored-by: John Wellbelove Co-authored-by: John Wellbelove --- include/etl/expected.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/include/etl/expected.h b/include/etl/expected.h index 2bb2ca9a..503b08ba 100644 --- a/include/etl/expected.h +++ b/include/etl/expected.h @@ -827,13 +827,12 @@ namespace etl enum { - Uninitialised, Value_Type, Error_Type }; - typedef etl::variant storage_type; - storage_type storage; + typedef etl::variant storage_type; + storage_type storage; #if ETL_USING_CPP11 template < typename F, typename TExp, typename TRet, typename TValueRef, typename = typename etl::enable_if::value>::type> @@ -1189,7 +1188,7 @@ namespace etl enum { - Uninitialised, + Void_Type, Error_Type }; From ff772d4bd15ede7574088ac8e844ed509ef1f8aa Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Tue, 28 Apr 2026 09:57:21 +0200 Subject: [PATCH 3/8] Move operators for etl::unique_ptr to etl namespace (#1408) * Print test names at test time (#1343) * Fix operator| conflict with std::ranges (#1395) * Move operators for etl::unique_ptr to etl namespace This is in accordance with the operators of std::unique_ptr. Also, it doesn't pollute the global namespace, and also works together with ADL, finding the operators in the etl namespace now. --------- Co-authored-by: John Wellbelove Co-authored-by: John Wellbelove --- include/etl/memory.h | 68 +++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 36 deletions(-) diff --git a/include/etl/memory.h b/include/etl/memory.h index 0bf9e3d6..e4301260 100644 --- a/include/etl/memory.h +++ b/include/etl/memory.h @@ -2370,47 +2370,43 @@ namespace etl pointer p; TDeleter deleter; }; -} // namespace etl -//***************************************************************************** -// Global functions for unique_ptr -//***************************************************************************** -template -bool operator==(const etl::unique_ptr& lhs, const etl::unique_ptr& rhs) -{ - return lhs.get() == rhs.get(); -} + //***************************************************************************** + // Comparison operators for unique_ptr + //***************************************************************************** + template + bool operator==(const etl::unique_ptr& lhs, const etl::unique_ptr& rhs) + { + return lhs.get() == rhs.get(); + } -//********************************* -template -bool operator<(const etl::unique_ptr& lhs, const etl::unique_ptr& rhs) -{ - return reinterpret_cast(lhs.get()) < reinterpret_cast(rhs.get()); -} + //********************************* + template + bool operator<(const etl::unique_ptr& lhs, const etl::unique_ptr& rhs) + { + return reinterpret_cast(lhs.get()) < reinterpret_cast(rhs.get()); + } -//********************************* -template -bool operator<=(const etl::unique_ptr& lhs, const etl::unique_ptr& rhs) -{ - return !(rhs < lhs); -} + //********************************* + template + bool operator<=(const etl::unique_ptr& lhs, const etl::unique_ptr& rhs) + { + return !(rhs < lhs); + } -//********************************* -template -bool operator>(const etl::unique_ptr& lhs, const etl::unique_ptr& rhs) -{ - return (rhs < lhs); -} + //********************************* + template + bool operator>(const etl::unique_ptr& lhs, const etl::unique_ptr& rhs) + { + return (rhs < lhs); + } -//********************************* -template -bool operator>=(const etl::unique_ptr& lhs, const etl::unique_ptr& rhs) -{ - return !(lhs < rhs); -} - -namespace etl -{ + //********************************* + template + bool operator>=(const etl::unique_ptr& lhs, const etl::unique_ptr& rhs) + { + return !(lhs < rhs); + } //***************************************************************************** /// Default construct an item at address p. ///\ingroup memory From 5ccbc6fbff06f523c44fbc563681a0a9fe28a93f Mon Sep 17 00:00:00 2001 From: Joris Putcuyps Date: Tue, 28 Apr 2026 10:23:52 +0200 Subject: [PATCH 4/8] Swap can be part of the etl namespace and let ADL do its thing (#1414) * Print test names at test time (#1343) * Fix operator| conflict with std::ranges (#1395) * Swap can be part of the etl namespace and let ADL do its thing --------- Co-authored-by: Roland Reichwein Co-authored-by: John Wellbelove Co-authored-by: John Wellbelove --- include/etl/expected.h | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/include/etl/expected.h b/include/etl/expected.h index 503b08ba..a8335247 100644 --- a/include/etl/expected.h +++ b/include/etl/expected.h @@ -1380,24 +1380,25 @@ namespace etl { return !(lhs == rhs); } + + //******************************************* + /// Swap etl::expected. + //******************************************* + template + ETL_CONSTEXPR14 void swap(etl::expected& lhs, etl::expected& rhs) + { + lhs.swap(rhs); + } + + //******************************************* + /// Swap etl::unexpected. + //******************************************* + template + ETL_CONSTEXPR14 void swap(etl::unexpected& lhs, etl::unexpected& rhs) + { + lhs.swap(rhs); + } + } // namespace etl -//******************************************* -/// Swap etl::expected. -//******************************************* -template -ETL_CONSTEXPR14 void swap(etl::expected& lhs, etl::expected& rhs) -{ - lhs.swap(rhs); -} - -//******************************************* -/// Swap etl::unexpected. -//******************************************* -template -ETL_CONSTEXPR14 void swap(etl::unexpected& lhs, etl::unexpected& rhs) -{ - lhs.swap(rhs); -} - #endif From fe7b2da10cabfad4aa2f0808b36fc6c60224301b Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Tue, 28 Apr 2026 11:03:25 +0200 Subject: [PATCH 5/8] Fix missing tuple_size (#1407) * Print test names at test time (#1343) * Fix operator| conflict with std::ranges (#1395) * Fix missing tuple_size In case of certain clang versions, a wrong combination of activated and deactivated template forward declarations and specializations were provided. This led to redefinition errors and specialization errors. Now aligning those combinations, and providing definitions from from std in the STL using case. --------- Co-authored-by: John Wellbelove Co-authored-by: John Wellbelove --- include/etl/tuple.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/etl/tuple.h b/include/etl/tuple.h index f76c0a62..0a419374 100644 --- a/include/etl/tuple.h +++ b/include/etl/tuple.h @@ -35,6 +35,7 @@ SOFTWARE. #if ETL_USING_STL #include + #include #endif #include "functional.h" @@ -1179,7 +1180,9 @@ namespace etl namespace std { - #if ETL_NOT_USING_STL && !((defined(ETL_DEVELOPMENT_OS_APPLE) || (ETL_COMPILER_FULL_VERSION >= 190000)) && defined(ETL_COMPILER_CLANG)) + #if ETL_NOT_USING_STL \ + && !((defined(ETL_DEVELOPMENT_OS_APPLE) || (ETL_COMPILER_FULL_VERSION >= 190000) && (ETL_COMPILER_FULL_VERSION < 220000)) \ + && defined(ETL_COMPILER_CLANG)) template struct tuple_size; From ee0d4740b3a27aaefbcd6b8e6960080202836d4b Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Tue, 28 Apr 2026 11:43:54 +0200 Subject: [PATCH 6/8] Add begin() and end() to etl::expected (#1410) * Print test names at test time (#1343) * Fix operator| conflict with std::ranges (#1395) * Add begin() and end() to etl::expected * Adding error_or() to etl::expected --------- Co-authored-by: John Wellbelove Co-authored-by: John Wellbelove --- include/etl/expected.h | 129 ++++++++++++++++++++++++++++++++++++++ test/test_expected.cpp | 139 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 268 insertions(+) diff --git a/include/etl/expected.h b/include/etl/expected.h index a8335247..829c4247 100644 --- a/include/etl/expected.h +++ b/include/etl/expected.h @@ -604,6 +604,38 @@ namespace etl return etl::move(etl::get(storage)); } + //******************************************* + /// Get the error or a default value. + //******************************************* + template + ETL_NODISCARD ETL_CONSTEXPR14 etl::enable_if_t::value, error_type> error_or(G&& default_error) const& + { + if (has_value()) + { + return static_cast(etl::forward(default_error)); + } + else + { + return error(); + } + } + + //******************************************* + /// Get the error or a default value. + //******************************************* + template + ETL_NODISCARD ETL_CONSTEXPR14 etl::enable_if_t::value, error_type> error_or(G&& default_error) && + { + if (has_value()) + { + return static_cast(etl::forward(default_error)); + } + else + { + return etl::move(error()); + } + } + //******************************************* /// Swap with another etl::expected. //******************************************* @@ -661,6 +693,22 @@ namespace etl { return etl::get(storage); } + + //******************************************* + /// Get the error or a default value. + //******************************************* + template + error_type error_or(const G& default_error) const + { + if (has_value()) + { + return static_cast(default_error); + } + else + { + return error(); + } + } #endif //******************************************* @@ -725,6 +773,39 @@ namespace etl } #endif + //******************************************* + /// Returns a pointer to the value if has_value(), otherwise returns nullptr. + /// Allows expected to be used as a range of 0 or 1 elements. + //******************************************* + ETL_NODISCARD ETL_CONSTEXPR14 value_type* begin() ETL_NOEXCEPT + { + return has_value() ? &etl::get(storage) : ETL_NULLPTR; + } + + //******************************************* + /// Returns a pointer past the value if has_value(), otherwise returns nullptr. + //******************************************* + ETL_NODISCARD ETL_CONSTEXPR14 value_type* end() ETL_NOEXCEPT + { + return has_value() ? &etl::get(storage) + 1 : ETL_NULLPTR; + } + + //******************************************* + /// Returns a const pointer to the value if has_value(), otherwise returns nullptr. + //******************************************* + ETL_NODISCARD ETL_CONSTEXPR14 const value_type* begin() const ETL_NOEXCEPT + { + return has_value() ? &etl::get(storage) : ETL_NULLPTR; + } + + //******************************************* + /// Returns a const pointer past the value if has_value(), otherwise returns nullptr. + //******************************************* + ETL_NODISCARD ETL_CONSTEXPR14 const value_type* end() const ETL_NOEXCEPT + { + return has_value() ? &etl::get(storage) + 1 : ETL_NULLPTR; + } + #if ETL_USING_CPP11 template ::type>::type> auto transform(F&& f) & -> expected @@ -1065,6 +1146,38 @@ namespace etl { return etl::move(etl::get(storage)); } + + //******************************************* + /// Get the error or a default value. + //******************************************* + template + ETL_NODISCARD ETL_CONSTEXPR14 etl::enable_if_t::value, error_type> error_or(G&& default_error) const& + { + if (has_value()) + { + return static_cast(etl::forward(default_error)); + } + else + { + return error(); + } + } + + //******************************************* + /// Get the error or a default value. + //******************************************* + template + ETL_NODISCARD ETL_CONSTEXPR14 etl::enable_if_t::value, error_type> error_or(G&& default_error) && + { + if (has_value()) + { + return static_cast(etl::forward(default_error)); + } + else + { + return etl::move(error()); + } + } #else //******************************************* /// Returns the error @@ -1074,6 +1187,22 @@ namespace etl { return etl::get(storage); } + + //******************************************* + /// Get the error or a default value. + //******************************************* + template + error_type error_or(const G& default_error) const + { + if (has_value()) + { + return static_cast(default_error); + } + else + { + return error(); + } + } #endif //******************************************* diff --git a/test/test_expected.cpp b/test/test_expected.cpp index 024ecf47..a28e2f54 100644 --- a/test/test_expected.cpp +++ b/test/test_expected.cpp @@ -31,6 +31,7 @@ SOFTWARE. #include "etl/expected.h" #include "etl/type_traits.h" +#include #include #include @@ -1477,5 +1478,143 @@ namespace auto with_error_type_check = check_expected_type_helper(unexpected_out); CHECK_TRUE(with_error_type_check); } + + //************************************************************************* + TEST(test_begin_end_with_value) + { + etl::expected exp(std::string("hello")); + + CHECK_TRUE(exp.begin() != exp.end()); + CHECK_EQUAL(std::distance(exp.begin(), exp.end()), 1); + CHECK_EQUAL(*exp.begin(), std::string("hello")); + } + + //************************************************************************* + TEST(test_begin_end_with_error) + { + etl::expected exp(etl::unexpected(Error("err"))); + + CHECK_TRUE(exp.begin() == exp.end()); + CHECK_EQUAL(std::distance(exp.begin(), exp.end()), 0); + } + + //************************************************************************* + TEST(test_begin_end_const_with_value) + { + const etl::expected exp(std::string("world")); + + CHECK_TRUE(exp.begin() != exp.end()); + CHECK_EQUAL(std::distance(exp.begin(), exp.end()), 1); + CHECK_EQUAL(*exp.begin(), std::string("world")); + } + + //************************************************************************* + TEST(test_begin_end_const_with_error) + { + const etl::expected exp(etl::unexpected(Error("err"))); + + CHECK_TRUE(exp.begin() == exp.end()); + CHECK_EQUAL(std::distance(exp.begin(), exp.end()), 0); + } + + //************************************************************************* + TEST(test_range_for_with_value) + { + etl::expected exp(42); + + int count = 0; + int sum = 0; + for (auto& v : exp) + { + ++count; + sum += v; + } + + CHECK_EQUAL(1, count); + CHECK_EQUAL(42, sum); + } + + //************************************************************************* + TEST(test_range_for_with_error) + { + etl::expected exp(etl::unexpected(Error("err"))); + + int count = 0; + for (auto& v : exp) + { + (void)v; + ++count; + } + + CHECK_EQUAL(0, count); + } + + //************************************************************************* + TEST(test_error_or_with_value) + { + etl::expected exp(42); + + Error result = exp.error_or(Error("default")); + CHECK_EQUAL("default", result.e); + } + + //************************************************************************* + TEST(test_error_or_with_error) + { + etl::expected exp(etl::unexpected(Error("real_error"))); + + Error result = exp.error_or(Error("default")); + CHECK_EQUAL("real_error", result.e); + } + + //************************************************************************* + TEST(test_error_or_const_with_value) + { + const etl::expected exp(42); + + Error result = exp.error_or(Error("default")); + CHECK_EQUAL("default", result.e); + } + + //************************************************************************* + TEST(test_error_or_const_with_error) + { + const etl::expected exp(etl::unexpected(Error("real_error"))); + + Error result = exp.error_or(Error("default")); + CHECK_EQUAL("real_error", result.e); + } + + //************************************************************************* + TEST(test_error_or_rvalue_with_value) + { + Error result = etl::expected(42).error_or(Error("default")); + CHECK_EQUAL("default", result.e); + } + + //************************************************************************* + TEST(test_error_or_rvalue_with_error) + { + Error result = etl::expected(etl::unexpected(Error("real_error"))).error_or(Error("default")); + CHECK_EQUAL("real_error", result.e); + } + + //************************************************************************* + TEST(test_error_or_void_value_with_value) + { + etl::expected exp; + + Error result = exp.error_or(Error("default")); + CHECK_EQUAL("default", result.e); + } + + //************************************************************************* + TEST(test_error_or_void_value_with_error) + { + etl::expected exp(etl::unexpected(Error("real_error"))); + + Error result = exp.error_or(Error("default")); + CHECK_EQUAL("real_error", result.e); + } } } // namespace From 15ca12649e9273f6243cf69183038b4fff63fa38 Mon Sep 17 00:00:00 2001 From: Joris Putcuyps Date: Tue, 28 Apr 2026 14:13:55 +0200 Subject: [PATCH 7/8] Global namespace bitset free functions cleanup (#1411) * Print test names at test time (#1343) * Fix operator| conflict with std::ranges (#1395) * Keep comparison and swap free functions out of the global namespace and let ADL do its thing. * Apply the same global to etl namespace move on overlooked functions --------- Co-authored-by: Roland Reichwein Co-authored-by: John Wellbelove Co-authored-by: John Wellbelove --- include/etl/private/bitset_legacy.h | 18 +- include/etl/private/bitset_new.h | 498 ++++++++++++++-------------- 2 files changed, 256 insertions(+), 260 deletions(-) diff --git a/include/etl/private/bitset_legacy.h b/include/etl/private/bitset_legacy.h index 7fa70ce3..8846e034 100644 --- a/include/etl/private/bitset_legacy.h +++ b/include/etl/private/bitset_legacy.h @@ -1523,16 +1523,16 @@ namespace etl { return !(lhs == rhs); } -} // namespace etl -//************************************************************************* -/// swap -//************************************************************************* -template -void swap(etl::bitset& lhs, etl::bitset& rhs) -{ - lhs.swap(rhs); -} + //************************************************************************* + /// swap + //************************************************************************* + template + void swap(etl::bitset& lhs, etl::bitset& rhs) + { + lhs.swap(rhs); + } +} // namespace etl #include "minmax_pop.h" diff --git a/include/etl/private/bitset_new.h b/include/etl/private/bitset_new.h index 19d21794..e33f3b10 100644 --- a/include/etl/private/bitset_new.h +++ b/include/etl/private/bitset_new.h @@ -2519,32 +2519,30 @@ namespace etl temp ^= rhs; return temp; } -} // namespace etl -//*************************************************************************** -/// operator != -///\ingroup bitset -//*************************************************************************** -template -ETL_CONSTEXPR14 bool operator!=(const etl::bitset& lhs, const etl::bitset& rhs) ETL_NOEXCEPT -{ - return !(lhs == rhs); -} + //*************************************************************************** + /// operator != + ///\ingroup bitset + //*************************************************************************** + template + ETL_CONSTEXPR14 bool operator!=(const etl::bitset& lhs, const etl::bitset& rhs) ETL_NOEXCEPT + { + return !(lhs == rhs); + } -//************************************************************************* -/// swap -//************************************************************************* -template -ETL_CONSTEXPR14 void swap(etl::bitset& lhs, etl::bitset& rhs) ETL_NOEXCEPT -{ - lhs.swap(rhs); -} + //************************************************************************* + /// swap + //************************************************************************* + template + ETL_CONSTEXPR14 void swap(etl::bitset& lhs, etl::bitset& rhs) ETL_NOEXCEPT + { + lhs.swap(rhs); + } + + //*************************************************************************** + /// bitset_ext + //*************************************************************************** -//*************************************************************************** -/// bitset_ext -//*************************************************************************** -namespace etl -{ //*************************************************************************** template class bitset_ext; @@ -3396,29 +3394,26 @@ namespace etl // Pointer to the storage for the bitset. element_type* pbuffer; }; -} // namespace etl -//*************************************************************************** -/// operator != -///\ingroup bitset -//*************************************************************************** -template -ETL_CONSTEXPR14 bool operator!=(const etl::bitset_ext& lhs, const etl::bitset_ext& rhs) ETL_NOEXCEPT -{ - return !(lhs == rhs); -} + //*************************************************************************** + /// operator != + ///\ingroup bitset + //*************************************************************************** + template + ETL_CONSTEXPR14 bool operator!=(const etl::bitset_ext& lhs, const etl::bitset_ext& rhs) ETL_NOEXCEPT + { + return !(lhs == rhs); + } -//************************************************************************* -/// swap -//************************************************************************* -template -ETL_CONSTEXPR14 void swap(etl::bitset_ext& lhs, etl::bitset_ext& rhs) ETL_NOEXCEPT -{ - lhs.swap(rhs); -} + //************************************************************************* + /// swap + //************************************************************************* + template + ETL_CONSTEXPR14 void swap(etl::bitset_ext& lhs, etl::bitset_ext& rhs) ETL_NOEXCEPT + { + lhs.swap(rhs); + } -namespace etl -{ namespace private_bitset { //************************************************************************* @@ -3464,216 +3459,217 @@ namespace etl return true; } } // namespace private_bitset + + //*************************************************************************** + /// operator == + /// bitset + /// Different element types + ///\ingroup bitset + //*************************************************************************** + template + ETL_CONSTEXPR14 typename etl::enable_if::value, bool>::type + operator==(const etl::bitset& lhs, const etl::bitset& rhs) ETL_NOEXCEPT + { + // Get a span of each type. + typename etl::bitset::const_span_type lhs_span = lhs.span(); + typename etl::bitset::const_span_type rhs_span = rhs.span(); + + // Put the bitset with the largest element type as the first argument. + if ETL_IF_CONSTEXPR (sizeof(TLhsElement) > sizeof(TRhsElement)) + { + return etl::private_bitset::compare_bitset_spans(lhs_span, rhs_span); + } + else + { + return etl::private_bitset::compare_bitset_spans(rhs_span, lhs_span); + } + } + + //*************************************************************************** + /// operator != + /// bitset + /// Different element types + ///\ingroup bitset + //*************************************************************************** + template + ETL_CONSTEXPR14 typename etl::enable_if::value, bool>::type + operator!=(const etl::bitset& lhs, const etl::bitset& rhs) ETL_NOEXCEPT + { + return !(lhs == rhs); + } + + //*************************************************************************** + /// operator == + /// bitset_ext + /// Different element types + ///\ingroup bitset + //*************************************************************************** + template + ETL_CONSTEXPR14 typename etl::enable_if::value, bool>::type + operator==(const etl::bitset_ext& lhs, const etl::bitset_ext& rhs) ETL_NOEXCEPT + { + // Get a span of each type. + typename etl::bitset_ext::const_span_type lhs_span = lhs.span(); + typename etl::bitset_ext::const_span_type rhs_span = rhs.span(); + + // Put the bitset with the largest element type as the first argument. + if ETL_IF_CONSTEXPR (sizeof(TLhsElement) > sizeof(TRhsElement)) + { + return etl::private_bitset::compare_bitset_spans(lhs_span, rhs_span); + } + else + { + return etl::private_bitset::compare_bitset_spans(rhs_span, lhs_span); + } + } + + //*************************************************************************** + /// operator != + /// bitset_ext + /// Different element types + ///\ingroup bitset + //*************************************************************************** + template + ETL_CONSTEXPR14 typename etl::enable_if::value, bool>::type + operator!=(const etl::bitset_ext& lhs, const etl::bitset_ext& rhs) ETL_NOEXCEPT + { + return !(lhs == rhs); + } + + //*************************************************************************** + /// operator == + /// bitset compared with bitset_ext, same element types. + ///\ingroup bitset + //*************************************************************************** + template + ETL_CONSTEXPR14 bool operator==(const etl::bitset& lhs, const etl::bitset_ext& rhs) ETL_NOEXCEPT + { + const char Storage_Model = etl::bitset::Storage_Model; + const size_t Number_Of_Elements = etl::bitset::Number_Of_Elements; + + typename etl::bitset::const_span_type lhs_span = lhs.span(); + typename etl::bitset_ext::const_span_type rhs_span = rhs.span(); + + typedef etl::bitset_impl implementation; + + return implementation::operator_equality(lhs_span.begin(), rhs_span.begin(), Number_Of_Elements); + } + + //*************************************************************************** + /// operator != + /// bitset compared with bitset_ext, same element types. + ///\ingroup bitset + //*************************************************************************** + template + ETL_CONSTEXPR14 bool operator!=(const etl::bitset& lhs, const etl::bitset_ext& rhs) ETL_NOEXCEPT + { + return !(lhs == rhs); + } + + //*************************************************************************** + /// operator == + /// bitset_ext compared with bitset, same element types. + ///\ingroup bitset + //*************************************************************************** + template + ETL_CONSTEXPR14 bool operator==(const etl::bitset_ext& lhs, const etl::bitset& rhs) ETL_NOEXCEPT + { + const char Storage_Model = etl::bitset::Storage_Model; + const size_t Number_Of_Elements = etl::bitset::Number_Of_Elements; + + typename etl::bitset_ext::const_span_type lhs_span = lhs.span(); + typename etl::bitset::const_span_type rhs_span = rhs.span(); + + typedef etl::bitset_impl implementation; + + return implementation::operator_equality(lhs_span.begin(), rhs_span.begin(), Number_Of_Elements); + } + + //*************************************************************************** + /// operator != + /// bitset_ext compared with bitset, same element types. + ///\ingroup bitset + //*************************************************************************** + template + ETL_CONSTEXPR14 bool operator!=(const etl::bitset_ext& lhs, const etl::bitset& rhs) ETL_NOEXCEPT + { + return !(lhs == rhs); + } + + //*************************************************************************** + /// operator == + /// bitset compared with bitset_ext, different element types. + ///\ingroup bitset + //*************************************************************************** + template + ETL_CONSTEXPR14 typename etl::enable_if::value, bool>::type + operator==(const etl::bitset& lhs, const etl::bitset_ext& rhs) ETL_NOEXCEPT + { + // Get a span of each type. + typename etl::bitset::const_span_type lhs_span = lhs.span(); + typename etl::bitset_ext::const_span_type rhs_span = rhs.span(); + + // Put the bitset with the largest element type as the first argument. + if ETL_IF_CONSTEXPR (sizeof(TLhsElement) > sizeof(TRhsElement)) + { + return etl::private_bitset::compare_bitset_spans(lhs_span, rhs_span); + } + else + { + return etl::private_bitset::compare_bitset_spans(rhs_span, lhs_span); + } + } + + //*************************************************************************** + /// operator != + /// bitset compared with bitset_ext, different element types. + ///\ingroup bitset + //*************************************************************************** + template + ETL_CONSTEXPR14 typename etl::enable_if::value, bool>::type + operator!=(const etl::bitset& lhs, const etl::bitset_ext& rhs) ETL_NOEXCEPT + { + return !(lhs == rhs); + } + + //*************************************************************************** + /// operator == + /// bitset_ext compared with bitset, different element types. + ///\ingroup bitset + //*************************************************************************** + template + ETL_CONSTEXPR14 typename etl::enable_if::value, bool>::type + operator==(const etl::bitset_ext& lhs, const etl::bitset& rhs) ETL_NOEXCEPT + { + // Get a span of each type. + typename etl::bitset_ext::const_span_type lhs_span = lhs.span(); + typename etl::bitset::const_span_type rhs_span = rhs.span(); + + // Put the bitset with the largest element type as the first argument. + if ETL_IF_CONSTEXPR (sizeof(TLhsElement) > sizeof(TRhsElement)) + { + return etl::private_bitset::compare_bitset_spans(lhs_span, rhs_span); + } + else + { + return etl::private_bitset::compare_bitset_spans(rhs_span, lhs_span); + } + } + + //*************************************************************************** + /// operator != + /// bitset_ext compared with bitset, different element types. + ///\ingroup bitset + //*************************************************************************** + template + ETL_CONSTEXPR14 typename etl::enable_if::value, bool>::type + operator!=(const etl::bitset_ext& lhs, const etl::bitset& rhs) ETL_NOEXCEPT + { + return !(lhs == rhs); + } + } // namespace etl -//*************************************************************************** -/// operator == -/// bitset -/// Different element types -///\ingroup bitset -//*************************************************************************** -template -ETL_CONSTEXPR14 typename etl::enable_if::value, bool>::type - operator==(const etl::bitset& lhs, const etl::bitset& rhs) ETL_NOEXCEPT -{ - // Get a span of each type. - typename etl::bitset::const_span_type lhs_span = lhs.span(); - typename etl::bitset::const_span_type rhs_span = rhs.span(); - - // Put the bitset with the largest element type as the first argument. - if ETL_IF_CONSTEXPR (sizeof(TLhsElement) > sizeof(TRhsElement)) - { - return etl::private_bitset::compare_bitset_spans(lhs_span, rhs_span); - } - else - { - return etl::private_bitset::compare_bitset_spans(rhs_span, lhs_span); - } -} - -//*************************************************************************** -/// operator != -/// bitset -/// Different element types -///\ingroup bitset -//*************************************************************************** -template -ETL_CONSTEXPR14 typename etl::enable_if::value, bool>::type - operator!=(const etl::bitset& lhs, const etl::bitset& rhs) ETL_NOEXCEPT -{ - return !(lhs == rhs); -} - -//*************************************************************************** -/// operator == -/// bitset_ext -/// Different element types -///\ingroup bitset -//*************************************************************************** -template -ETL_CONSTEXPR14 typename etl::enable_if::value, bool>::type - operator==(const etl::bitset_ext& lhs, const etl::bitset_ext& rhs) ETL_NOEXCEPT -{ - // Get a span of each type. - typename etl::bitset_ext::const_span_type lhs_span = lhs.span(); - typename etl::bitset_ext::const_span_type rhs_span = rhs.span(); - - // Put the bitset with the largest element type as the first argument. - if ETL_IF_CONSTEXPR (sizeof(TLhsElement) > sizeof(TRhsElement)) - { - return etl::private_bitset::compare_bitset_spans(lhs_span, rhs_span); - } - else - { - return etl::private_bitset::compare_bitset_spans(rhs_span, lhs_span); - } -} - -//*************************************************************************** -/// operator != -/// bitset_ext -/// Different element types -///\ingroup bitset -//*************************************************************************** -template -ETL_CONSTEXPR14 typename etl::enable_if::value, bool>::type - operator!=(const etl::bitset_ext& lhs, const etl::bitset_ext& rhs) ETL_NOEXCEPT -{ - return !(lhs == rhs); -} - -//*************************************************************************** -/// operator == -/// bitset compared with bitset_ext, same element types. -///\ingroup bitset -//*************************************************************************** -template -ETL_CONSTEXPR14 bool operator==(const etl::bitset& lhs, const etl::bitset_ext& rhs) ETL_NOEXCEPT -{ - const char Storage_Model = etl::bitset::Storage_Model; - const size_t Number_Of_Elements = etl::bitset::Number_Of_Elements; - - typename etl::bitset::const_span_type lhs_span = lhs.span(); - typename etl::bitset_ext::const_span_type rhs_span = rhs.span(); - - typedef etl::bitset_impl implementation; - - return implementation::operator_equality(lhs_span.begin(), rhs_span.begin(), Number_Of_Elements); -} - -//*************************************************************************** -/// operator != -/// bitset compared with bitset_ext, same element types. -///\ingroup bitset -//*************************************************************************** -template -ETL_CONSTEXPR14 bool operator!=(const etl::bitset& lhs, const etl::bitset_ext& rhs) ETL_NOEXCEPT -{ - return !(lhs == rhs); -} - -//*************************************************************************** -/// operator == -/// bitset_ext compared with bitset, same element types. -///\ingroup bitset -//*************************************************************************** -template -ETL_CONSTEXPR14 bool operator==(const etl::bitset_ext& lhs, const etl::bitset& rhs) ETL_NOEXCEPT -{ - const char Storage_Model = etl::bitset::Storage_Model; - const size_t Number_Of_Elements = etl::bitset::Number_Of_Elements; - - typename etl::bitset_ext::const_span_type lhs_span = lhs.span(); - typename etl::bitset::const_span_type rhs_span = rhs.span(); - - typedef etl::bitset_impl implementation; - - return implementation::operator_equality(lhs_span.begin(), rhs_span.begin(), Number_Of_Elements); -} - -//*************************************************************************** -/// operator != -/// bitset_ext compared with bitset, same element types. -///\ingroup bitset -//*************************************************************************** -template -ETL_CONSTEXPR14 bool operator!=(const etl::bitset_ext& lhs, const etl::bitset& rhs) ETL_NOEXCEPT -{ - return !(lhs == rhs); -} - -//*************************************************************************** -/// operator == -/// bitset compared with bitset_ext, different element types. -///\ingroup bitset -//*************************************************************************** -template -ETL_CONSTEXPR14 typename etl::enable_if::value, bool>::type - operator==(const etl::bitset& lhs, const etl::bitset_ext& rhs) ETL_NOEXCEPT -{ - // Get a span of each type. - typename etl::bitset::const_span_type lhs_span = lhs.span(); - typename etl::bitset_ext::const_span_type rhs_span = rhs.span(); - - // Put the bitset with the largest element type as the first argument. - if ETL_IF_CONSTEXPR (sizeof(TLhsElement) > sizeof(TRhsElement)) - { - return etl::private_bitset::compare_bitset_spans(lhs_span, rhs_span); - } - else - { - return etl::private_bitset::compare_bitset_spans(rhs_span, lhs_span); - } -} - -//*************************************************************************** -/// operator != -/// bitset compared with bitset_ext, different element types. -///\ingroup bitset -//*************************************************************************** -template -ETL_CONSTEXPR14 typename etl::enable_if::value, bool>::type - operator!=(const etl::bitset& lhs, const etl::bitset_ext& rhs) ETL_NOEXCEPT -{ - return !(lhs == rhs); -} - -//*************************************************************************** -/// operator == -/// bitset_ext compared with bitset, different element types. -///\ingroup bitset -//*************************************************************************** -template -ETL_CONSTEXPR14 typename etl::enable_if::value, bool>::type - operator==(const etl::bitset_ext& lhs, const etl::bitset& rhs) ETL_NOEXCEPT -{ - // Get a span of each type. - typename etl::bitset_ext::const_span_type lhs_span = lhs.span(); - typename etl::bitset::const_span_type rhs_span = rhs.span(); - - // Put the bitset with the largest element type as the first argument. - if ETL_IF_CONSTEXPR (sizeof(TLhsElement) > sizeof(TRhsElement)) - { - return etl::private_bitset::compare_bitset_spans(lhs_span, rhs_span); - } - else - { - return etl::private_bitset::compare_bitset_spans(rhs_span, lhs_span); - } -} - -//*************************************************************************** -/// operator != -/// bitset_ext compared with bitset, different element types. -///\ingroup bitset -//*************************************************************************** -template -ETL_CONSTEXPR14 typename etl::enable_if::value, bool>::type - operator!=(const etl::bitset_ext& lhs, const etl::bitset& rhs) ETL_NOEXCEPT -{ - return !(lhs == rhs); -} - #include "minmax_pop.h" #endif From 943e8e60891aacf37e0dfd29badaf44b50ccaba2 Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Tue, 28 Apr 2026 15:35:21 +0200 Subject: [PATCH 8/8] Add invocable and further missing concepts to concepts.h (#1412) * Print test names at test time (#1343) * Fix operator| conflict with std::ranges (#1395) * Add concept invocable and further missing concepts to concepts.h --------- Co-authored-by: John Wellbelove Co-authored-by: John Wellbelove --- include/etl/concepts.h | 126 ++++++++++++++++++++ include/etl/type_traits.h | 25 ++++ test/test_concepts.cpp | 237 ++++++++++++++++++++++++++++++++++++++ test/test_type_traits.cpp | 38 ++++++ 4 files changed, 426 insertions(+) diff --git a/include/etl/concepts.h b/include/etl/concepts.h index ac539947..9376264b 100644 --- a/include/etl/concepts.h +++ b/include/etl/concepts.h @@ -33,6 +33,7 @@ SOFTWARE. #include "platform.h" +#include "invoke.h" #include "type_traits.h" #include "utility.h" @@ -50,12 +51,31 @@ namespace etl using std::assignable_from; using std::common_reference_with; using std::common_with; + using std::constructible_from; using std::convertible_to; + using std::copy_constructible; + using std::copyable; + using std::default_initializable; using std::derived_from; + using std::destructible; + using std::equality_comparable; + using std::equivalence_relation; using std::floating_point; using std::integral; + using std::invocable; + using std::movable; + using std::move_constructible; + using std::predicate; + using std::regular; + using std::regular_invocable; + using std::relation; using std::same_as; + using std::semiregular; using std::signed_integral; + using std::strict_weak_order; + using std::swappable; + using std::swappable_with; + using std::totally_ordered; using std::unsigned_integral; #else // not ETL_USING_STL @@ -114,6 +134,112 @@ namespace etl { lhs = etl::forward(rhs) } -> etl::same_as; }; + //*************************************************************************** + template + concept invocable = etl::is_invocable_v; + + //*************************************************************************** + template + concept regular_invocable = etl::invocable; + + //*************************************************************************** + template + concept destructible = requires(T& t) { + { t.~T() } noexcept; + }; + + //*************************************************************************** + template + concept constructible_from = etl::destructible && etl::is_constructible_v; + + //*************************************************************************** + template + concept default_initializable = etl::constructible_from && requires { + T{}; + ::new T; + }; + + //*************************************************************************** + template + concept move_constructible = etl::constructible_from && etl::convertible_to; + + //*************************************************************************** + template + concept copy_constructible = + etl::move_constructible && etl::constructible_from && etl::convertible_to && etl::constructible_from + && etl::convertible_to && etl::constructible_from && etl::convertible_to; + + //*************************************************************************** + namespace private_concepts + { + template + concept boolean_testable = etl::convertible_to && requires(T&& t) { + { !etl::forward(t) } -> etl::convertible_to; + }; + } // namespace private_concepts + + //*************************************************************************** + template + concept equality_comparable = requires(const etl::remove_reference_t& a, const etl::remove_reference_t& b) { + { a == b } -> private_concepts::boolean_testable; + { a != b } -> private_concepts::boolean_testable; + }; + + //*************************************************************************** + template + concept totally_ordered = etl::equality_comparable && requires(const etl::remove_reference_t& a, const etl::remove_reference_t& b) { + { a < b } -> private_concepts::boolean_testable; + { a > b } -> private_concepts::boolean_testable; + { a <= b } -> private_concepts::boolean_testable; + { a >= b } -> private_concepts::boolean_testable; + }; + + //*************************************************************************** + template + concept swappable = requires(T& a, T& b) { etl::swap(a, b); }; + + //*************************************************************************** + template + concept swappable_with = etl::common_reference_with&, etl::remove_reference_t&> && requires(T&& t, U&& u) { + etl::swap(etl::forward(t), etl::forward(t)); + etl::swap(etl::forward(u), etl::forward(u)); + etl::swap(etl::forward(t), etl::forward(u)); + etl::swap(etl::forward(u), etl::forward(t)); + }; + + //*************************************************************************** + template + concept movable = etl::is_object_v && etl::move_constructible && etl::assignable_from && etl::swappable; + + //*************************************************************************** + template + concept copyable = etl::copy_constructible && etl::movable && etl::assignable_from && etl::assignable_from + && etl::assignable_from; + + //*************************************************************************** + template + concept semiregular = etl::copyable && etl::default_initializable; + + //*************************************************************************** + template + concept regular = etl::semiregular && etl::equality_comparable; + + //*************************************************************************** + template + concept predicate = etl::regular_invocable && private_concepts::boolean_testable >; + + //*************************************************************************** + template + concept relation = etl::predicate && etl::predicate && etl::predicate && etl::predicate; + + //*************************************************************************** + template + concept equivalence_relation = etl::relation; + + //*************************************************************************** + template + concept strict_weak_order = etl::relation; + #endif } // namespace etl #endif diff --git a/include/etl/type_traits.h b/include/etl/type_traits.h index 2600da96..2b4372af 100644 --- a/include/etl/type_traits.h +++ b/include/etl/type_traits.h @@ -649,6 +649,18 @@ namespace etl struct is_void : true_type { }; + template <> + struct is_void : true_type + { + }; + template <> + struct is_void : true_type + { + }; + template <> + struct is_void : true_type + { + }; #if ETL_USING_CPP17 template @@ -3977,6 +3989,19 @@ namespace etl template inline constexpr bool is_function_v = etl::is_function::value; #endif + + //*************************************************************************** + /// is_object + //*************************************************************************** + template + struct is_object : etl::bool_constant::value && !etl::is_reference::value && !etl::is_void::value> + { + }; + + #if ETL_USING_CPP17 + template + inline constexpr bool is_object_v = etl::is_object::value; + #endif #endif #if ETL_USING_CPP11 diff --git a/test/test_concepts.cpp b/test/test_concepts.cpp index 347ec8fb..a6b03830 100644 --- a/test/test_concepts.cpp +++ b/test/test_concepts.cpp @@ -29,6 +29,7 @@ SOFTWARE. #include "unit_test_framework.h" #include +#include #include #if ETL_USING_CPP20 @@ -52,6 +53,65 @@ namespace { }; + struct NotDestructible + { + ~NotDestructible() = delete; + }; + + struct NotDefaultConstructible + { + NotDefaultConstructible(int) {} + }; + + struct NotCopyable + { + NotCopyable() = default; + NotCopyable(const NotCopyable&) = delete; + NotCopyable(NotCopyable&&) = default; + NotCopyable& operator=(const NotCopyable&) = delete; + NotCopyable& operator=(NotCopyable&&) = default; + }; + + struct NotMovable + { + NotMovable() = default; + NotMovable(const NotMovable&) = delete; + NotMovable(NotMovable&&) = delete; + NotMovable& operator=(const NotMovable&) = delete; + NotMovable& operator=(NotMovable&&) = delete; + }; + + struct NotEqualityComparable + { + }; + + struct EqualityComparableType + { + bool operator==(const EqualityComparableType&) const = default; + }; + + struct OrderedType + { + int value; + auto operator<=>(const OrderedType&) const = default; + }; + + struct BoolPredicate + { + bool operator()(int) const + { + return true; + } + }; + + struct IntRelation + { + bool operator()(int, int) const + { + return true; + } + }; + SUITE(test_concepts) { //************************************************************************* @@ -140,6 +200,183 @@ namespace static_assert(etl::assignable_from == false); static_assert(etl::assignable_from&, int> == false); } + + //************************************************************************* + TEST(test_invocable) + { + struct Functor + { + void operator()() {} + }; + struct FunctorWithArgs + { + int operator()(int, double) + { + return 0; + } + }; + + static_assert(etl::invocable == true); + static_assert(etl::invocable == true); + static_assert(etl::invocable == true); + static_assert(etl::invocable == true); + static_assert(etl::invocable == false); + static_assert(etl::invocable == false); + } + + //************************************************************************* + TEST(test_regular_invocable) + { + struct Functor + { + void operator()() {} + }; + + static_assert(etl::regular_invocable == true); + static_assert(etl::regular_invocable == true); + static_assert(etl::regular_invocable == false); + } + + //************************************************************************* + TEST(test_destructible) + { + static_assert(etl::destructible == true); + static_assert(etl::destructible == true); + static_assert(etl::destructible == false); + } + + //************************************************************************* + TEST(test_constructible_from) + { + static_assert(etl::constructible_from == true); + static_assert(etl::constructible_from == true); + static_assert(etl::constructible_from == true); + static_assert(etl::constructible_from == false); + } + + //************************************************************************* + TEST(test_default_initializable) + { + static_assert(etl::default_initializable == true); + static_assert(etl::default_initializable == true); + static_assert(etl::default_initializable == false); + } + + //************************************************************************* + TEST(test_move_constructible) + { + static_assert(etl::move_constructible == true); + static_assert(etl::move_constructible == true); + static_assert(etl::move_constructible == false); + } + + //************************************************************************* + TEST(test_copy_constructible) + { + static_assert(etl::copy_constructible == true); + static_assert(etl::copy_constructible == true); + static_assert(etl::copy_constructible == false); + } + + //************************************************************************* + TEST(test_equality_comparable) + { + static_assert(etl::equality_comparable == true); + static_assert(etl::equality_comparable == true); + static_assert(etl::equality_comparable == false); + } + + //************************************************************************* + TEST(test_totally_ordered) + { + static_assert(etl::totally_ordered == true); + static_assert(etl::totally_ordered == true); + static_assert(etl::totally_ordered == false); + } + + //************************************************************************* + TEST(test_swappable) + { + static_assert(etl::swappable == true); + static_assert(etl::swappable == true); + static_assert(etl::swappable == false); + } + + //************************************************************************* + TEST(test_swappable_with) + { + // Positive cases: same-type lvalue references that are swappable + static_assert(etl::swappable_with == true); + static_assert(etl::swappable_with == true); + + // Negative cases: unrelated types (no valid swap overload) + static_assert(etl::swappable_with == false); + + // Negative case: non-movable type cannot be swapped + static_assert(etl::swappable_with == false); + } + + //************************************************************************* + TEST(test_movable) + { + static_assert(etl::movable == true); + static_assert(etl::movable == true); + static_assert(etl::movable == false); + } + + //************************************************************************* + TEST(test_copyable) + { + static_assert(etl::copyable == true); + static_assert(etl::copyable == true); + static_assert(etl::copyable == false); + } + + //************************************************************************* + TEST(test_semiregular) + { + static_assert(etl::semiregular == true); + static_assert(etl::semiregular == true); + static_assert(etl::semiregular == false); + } + + //************************************************************************* + TEST(test_regular) + { + static_assert(etl::regular == true); + static_assert(etl::regular == true); + static_assert(etl::regular == false); + } + + //************************************************************************* + TEST(test_predicate) + { + static_assert(etl::predicate == true); + static_assert(etl::predicate == true); + static_assert(etl::predicate == false); + } + + //************************************************************************* + TEST(test_relation) + { + static_assert(etl::relation == true); + static_assert(etl::relation, int, int> == true); + static_assert(etl::relation == false); + } + + //************************************************************************* + TEST(test_equivalence_relation) + { + static_assert(etl::equivalence_relation, int, int> == true); + static_assert(etl::equivalence_relation == false); + } + + //************************************************************************* + TEST(test_strict_weak_order) + { + static_assert(etl::strict_weak_order, int, int> == true); + static_assert(etl::strict_weak_order == false); + } } } // namespace #endif diff --git a/test/test_type_traits.cpp b/test/test_type_traits.cpp index f6ef4cda..bb4d73f1 100644 --- a/test/test_type_traits.cpp +++ b/test/test_type_traits.cpp @@ -2211,5 +2211,43 @@ namespace CHECK_FALSE((etl::is_function::value)); CHECK_FALSE((etl::is_function::value)); // pointer, not function } + + //************************************************************************* + TEST(test_is_object) + { + CHECK_TRUE((etl::is_object::value)); + CHECK_TRUE((etl::is_object::value)); + CHECK_TRUE((etl::is_object::value)); + CHECK_TRUE((etl::is_object::value)); + CHECK_TRUE((etl::is_object::value)); + CHECK_TRUE((etl::is_object::value)); + CHECK_TRUE((etl::is_object::value)); + + CHECK_FALSE((etl::is_object::value)); + CHECK_FALSE((etl::is_object::value)); + CHECK_FALSE((etl::is_object::value)); + CHECK_FALSE((etl::is_object::value)); + CHECK_FALSE((etl::is_object::value)); + CHECK_FALSE((etl::is_object::value)); + CHECK_FALSE((etl::is_object::value)); + + CHECK_TRUE((etl::is_void::value)); + CHECK_TRUE((etl::is_void::value)); + CHECK_TRUE((etl::is_void::value)); + +#if ETL_USING_CPP17 + CHECK_TRUE((etl::is_object_v)); + CHECK_TRUE((etl::is_object_v)); + CHECK_TRUE((etl::is_object_v)); + + CHECK_FALSE((etl::is_object_v)); + CHECK_FALSE((etl::is_object_v)); + CHECK_FALSE((etl::is_object_v)); + CHECK_FALSE((etl::is_object_v)); + CHECK_FALSE((etl::is_object_v)); + CHECK_FALSE((etl::is_object_v)); + CHECK_FALSE((etl::is_object_v)); +#endif + } } } // namespace