From 06e54f6b23a2fc69e4e722f29756d7a506a5d08e Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Mon, 31 Aug 2026 20:09:16 +0200 Subject: [PATCH] Add missing type traits (#1573) etl::is_scoped_enum etl::is_trivially_default_constructible etl::is_trivially_move_constructible etl::is_trivially_move_assignable etl::is_trivially_assignable etl::is_layout_compatible etl::is_pointer_interconvertible_base_of Co-authored-by: John Wellbelove --- docs/types/type-traits.md | 124 +++++++ .../etl/profiles/determine_builtin_support.h | 41 +++ include/etl/type_traits.h | 325 +++++++++++++++++- test/test_type_traits.cpp | 197 +++++++++++ 4 files changed, 682 insertions(+), 5 deletions(-) diff --git a/docs/types/type-traits.md b/docs/types/type-traits.md index 98326be6..dc95aca1 100644 --- a/docs/types/type-traits.md +++ b/docs/types/type-traits.md @@ -42,6 +42,8 @@ Not all traits have been defined as some rely on compiler intrinsics that are no `is_aggregate` `is_trivial` `is_standard_layout` +`is_layout_compatible` +`is_pointer_interconvertible_base_of` `is_destructible` `is_nothrow_destructible` `has_virtual_destructor` @@ -72,6 +74,7 @@ Not all traits have been defined as some rely on compiler intrinsics that are no `declvar` `20.28.0` `common_type` `is_enum` `20.30.0` +`is_scoped_enum` `20.50.0` `underlying_type` `20.42.0`  Unless the ETL is set to use builtins, the user must specialise the template for their enumerations. @@ -87,8 +90,12 @@ The following will be defined according to the C++ standard and user defined mac `is_move_constructible` `is_trivially_constructible` `is_trivially_copy_constructible` +`is_trivially_default_constructible` +`is_trivially_move_constructible` `is_trivially_destructible` +`is_trivially_assignable` `is_trivially_copy_assignable` +`is_trivially_move_assignable` `is_trivially_copyable` ## Scenario 1 @@ -875,3 +882,120 @@ template inline constexpr bool is_scalar_v = etl::is_scalar::value; ``` C++17 + +## is_scoped_enum +From: `20.50.0` + +```cpp +template +struct is_scoped_enum +``` +Checks if `T` is a scoped enumeration type; that is, an enumeration type that is not implicitly convertible to an integer. +The result is found in the member `value`. + +```cpp +template +inline constexpr bool is_scoped_enum_v = etl::is_scoped_enum::value; +``` +C++17 + +## is_trivially_default_constructible +From: `20.50.0` + +```cpp +template +struct is_trivially_default_constructible +``` +Checks if `T` is default constructible and the default construction is trivial. +The result is found in the member `value`. + +```cpp +template +inline constexpr bool is_trivially_default_constructible_v = etl::is_trivially_default_constructible::value; +``` +C++17 + +## is_trivially_move_constructible +From: `20.50.0` + +```cpp +template +struct is_trivially_move_constructible +``` +Checks if `T` is move constructible and the move construction is trivial. +The result is found in the member `value`. + +```cpp +template +inline constexpr bool is_trivially_move_constructible_v = etl::is_trivially_move_constructible::value; +``` +C++17 + +## is_trivially_move_assignable +From: `20.50.0` + +```cpp +template +struct is_trivially_move_assignable +``` +Checks if `T` is move assignable and the move assignment is trivial. +The result is found in the member `value`. + +```cpp +template +inline constexpr bool is_trivially_move_assignable_v = etl::is_trivially_move_assignable::value; +``` +C++17 + +## is_trivially_assignable + +```cpp +template +struct is_trivially_assignable +``` +Checks if an expression of type `T2` can be assigned to an lvalue expression of type `T1`, and that the assignment is trivial. +The result is found in the member `value`. + See Scenarios 1 to 4 above for how this trait is defined when the STL or the compiler built-ins are unavailable. + +```cpp +template +inline constexpr bool is_trivially_assignable_v = etl::is_trivially_assignable::value; +``` +C++17 + +## is_layout_compatible +From: `20.50.0` + +```cpp +template +struct is_layout_compatible +``` +Checks if `T` and `U` are layout-compatible types. +The result is found in the member `value`. + When using the STL with C++20 or above, this is defined as `std::is_layout_compatible`. + Otherwise it requires compiler support (the `__is_layout_compatible` intrinsic). When neither is available, this trait is not defined, as there is no portable way of determining layout compatibility. + +```cpp +template +inline constexpr bool is_layout_compatible_v = etl::is_layout_compatible::value; +``` +C++17 + +## is_pointer_interconvertible_base_of +From: `20.50.0` + +```cpp +template +struct is_pointer_interconvertible_base_of +``` +Checks if `TBase` is a pointer-interconvertible base class of `TDerived`; that is, every object of type `TDerived` has its `TBase` base class subobject at the same address as the complete object. +The result is found in the member `value`. + When using the STL with C++20 or above, this is defined as `std::is_pointer_interconvertible_base_of`. + Otherwise it requires compiler support (the `__is_pointer_interconvertible_base_of` intrinsic). When neither is available, this trait is not defined, as there is no portable way of determining pointer interconvertibility. + Note that, as required by the standard, the program is ill-formed if `TDerived` is a complete non-union class type and `TBase` is an incomplete class type. The trait cannot be used to probe possibly-incomplete types. + +```cpp +template +inline constexpr bool is_pointer_interconvertible_base_of_v = etl::is_pointer_interconvertible_base_of::value; +``` +C++17 diff --git a/include/etl/profiles/determine_builtin_support.h b/include/etl/profiles/determine_builtin_support.h index 6340e6e3..ad681fb5 100644 --- a/include/etl/profiles/determine_builtin_support.h +++ b/include/etl/profiles/determine_builtin_support.h @@ -53,6 +53,10 @@ SOFTWARE. #define ETL_USING_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE 1 #endif + #if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE) + #define ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE 1 + #endif + #if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE) #define ETL_USING_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE 1 #endif @@ -77,6 +81,14 @@ SOFTWARE. #define ETL_USING_BUILTIN_IS_TRIVIAL 1 #endif + #if !defined(ETL_USING_BUILTIN_IS_LAYOUT_COMPATIBLE) + #define ETL_USING_BUILTIN_IS_LAYOUT_COMPATIBLE 1 + #endif + + #if !defined(ETL_USING_BUILTIN_IS_POINTER_INTERCONVERTIBLE_BASE_OF) + #define ETL_USING_BUILTIN_IS_POINTER_INTERCONVERTIBLE_BASE_OF 1 + #endif + #if !defined(ETL_USING_BUILTIN_IS_UNION) #define ETL_USING_BUILTIN_IS_UNION 1 #endif @@ -168,6 +180,10 @@ SOFTWARE. #define ETL_USING_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE (__has_builtin(__has_trivial_constructor) || __has_builtin(__is_trivially_constructible)) #endif + #if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE) + #define ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE __has_builtin(__is_trivially_assignable) + #endif + #if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE) #define ETL_USING_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE (__has_builtin(__has_trivial_destructor) || __has_builtin(__is_trivially_destructible)) #endif @@ -192,6 +208,14 @@ SOFTWARE. #define ETL_USING_BUILTIN_IS_TRIVIAL __has_builtin(__is_trivial) #endif + #if !defined(ETL_USING_BUILTIN_IS_LAYOUT_COMPATIBLE) + #define ETL_USING_BUILTIN_IS_LAYOUT_COMPATIBLE __has_builtin(__is_layout_compatible) + #endif + + #if !defined(ETL_USING_BUILTIN_IS_POINTER_INTERCONVERTIBLE_BASE_OF) + #define ETL_USING_BUILTIN_IS_POINTER_INTERCONVERTIBLE_BASE_OF __has_builtin(__is_pointer_interconvertible_base_of) + #endif + #if !defined(ETL_USING_BUILTIN_IS_UNION) #define ETL_USING_BUILTIN_IS_UNION __has_builtin(__is_union) #endif @@ -283,6 +307,10 @@ SOFTWARE. #define ETL_USING_BUILTIN_IS_TRIVIALLY_COPYABLE 1 #endif + #if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE) + #define ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE 1 + #endif + #if !defined(ETL_USING_BUILTIN_IS_STANDARD_LAYOUT) #define ETL_USING_BUILTIN_IS_STANDARD_LAYOUT 1 #endif @@ -352,6 +380,10 @@ SOFTWARE. #define ETL_USING_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE 0 #endif +#if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE) + #define ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE 0 +#endif + #if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE) #define ETL_USING_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE 0 #endif @@ -376,6 +408,14 @@ SOFTWARE. #define ETL_USING_BUILTIN_IS_TRIVIAL 0 #endif +#if !defined(ETL_USING_BUILTIN_IS_LAYOUT_COMPATIBLE) + #define ETL_USING_BUILTIN_IS_LAYOUT_COMPATIBLE 0 +#endif + +#if !defined(ETL_USING_BUILTIN_IS_POINTER_INTERCONVERTIBLE_BASE_OF) + #define ETL_USING_BUILTIN_IS_POINTER_INTERCONVERTIBLE_BASE_OF 0 +#endif + #if !defined(ETL_USING_BUILTIN_IS_UNION) #define ETL_USING_BUILTIN_IS_UNION 0 #endif @@ -480,6 +520,7 @@ namespace etl static ETL_CONSTANT bool using_builtin_is_nothrow_constructible = (ETL_USING_BUILTIN_IS_NOTHROW_CONSTRUCTIBLE == 1); static ETL_CONSTANT bool using_builtin_is_nothrow_assignable = (ETL_USING_BUILTIN_IS_NOTHROW_ASSIGNABLE == 1); static ETL_CONSTANT bool using_builtin_is_trivially_constructible = (ETL_USING_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE == 1); + static ETL_CONSTANT bool using_builtin_is_trivially_assignable = (ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE == 1); static ETL_CONSTANT bool using_builtin_is_trivially_destructible = (ETL_USING_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE == 1); static ETL_CONSTANT bool using_builtin_is_trivially_copyable = (ETL_USING_BUILTIN_IS_TRIVIALLY_COPYABLE == 1); static ETL_CONSTANT bool using_builtin_underlying_type = (ETL_USING_BUILTIN_UNDERLYING_TYPE == 1); diff --git a/include/etl/type_traits.h b/include/etl/type_traits.h index 87b7607b..ea9823a7 100644 --- a/include/etl/type_traits.h +++ b/include/etl/type_traits.h @@ -916,6 +916,38 @@ namespace etl #endif #endif + //*************************************************************************** + /// is_layout_compatible + /// Requires compiler support. Without it there is no portable way to + /// determine whether two types are layout compatible, so the trait is not defined. + #if ETL_USING_BUILTIN_IS_LAYOUT_COMPATIBLE + template + struct is_layout_compatible : etl::bool_constant<__is_layout_compatible(T, U)> + { + }; + + #if ETL_USING_CPP17 + template + inline constexpr bool is_layout_compatible_v = etl::is_layout_compatible::value; + #endif + #endif + + //*************************************************************************** + /// is_pointer_interconvertible_base_of + /// Requires compiler support. Without it there is no portable way to + /// determine pointer interconvertibility, so the trait is not defined. + #if ETL_USING_BUILTIN_IS_POINTER_INTERCONVERTIBLE_BASE_OF + template + struct is_pointer_interconvertible_base_of : etl::bool_constant<__is_pointer_interconvertible_base_of(TBase, TDerived)> + { + }; + + #if ETL_USING_CPP17 + template + inline constexpr bool is_pointer_interconvertible_base_of_v = etl::is_pointer_interconvertible_base_of::value; + #endif + #endif + //*************************************************************************** /// conditional template @@ -1667,6 +1699,20 @@ namespace etl inline constexpr bool is_nothrow_convertible_v = etl::is_nothrow_convertible::value; #endif + //*************************************************************************** + /// is_scoped_enum + ///\ingroup type_traits + /// An enumeration is scoped if it is not implicitly convertible to an integer. + template + struct is_scoped_enum : etl::bool_constant::value && !etl::is_convertible::value> + { + }; + + #if ETL_USING_CPP17 + template + inline constexpr bool is_scoped_enum_v = etl::is_scoped_enum::value; + #endif + //*************************************************************************** /// is_destructible /// Requires either compiler support or C++11. Without them there is no @@ -2337,6 +2383,52 @@ namespace etl #endif #endif + //*************************************************************************** + /// is_layout_compatible + ///\ingroup type_traits + #if ETL_USING_CPP20 && defined(__cpp_lib_is_layout_compatible) + template + struct is_layout_compatible : std::is_layout_compatible + { + }; + + template + inline constexpr bool is_layout_compatible_v = std::is_layout_compatible_v; + #elif ETL_USING_BUILTIN_IS_LAYOUT_COMPATIBLE + template + struct is_layout_compatible : etl::bool_constant<__is_layout_compatible(T, U)> + { + }; + + #if ETL_USING_CPP17 + template + inline constexpr bool is_layout_compatible_v = etl::is_layout_compatible::value; + #endif + #endif + + //*************************************************************************** + /// is_pointer_interconvertible_base_of + ///\ingroup type_traits + #if ETL_USING_CPP20 && defined(__cpp_lib_is_pointer_interconvertible) + template + struct is_pointer_interconvertible_base_of : std::is_pointer_interconvertible_base_of + { + }; + + template + inline constexpr bool is_pointer_interconvertible_base_of_v = std::is_pointer_interconvertible_base_of_v; + #elif ETL_USING_BUILTIN_IS_POINTER_INTERCONVERTIBLE_BASE_OF + template + struct is_pointer_interconvertible_base_of : etl::bool_constant<__is_pointer_interconvertible_base_of(TBase, TDerived)> + { + }; + + #if ETL_USING_CPP17 + template + inline constexpr bool is_pointer_interconvertible_base_of_v = etl::is_pointer_interconvertible_base_of::value; + #endif + #endif + //*************************************************************************** /// is_destructible ///\ingroup type_traits @@ -2711,6 +2803,27 @@ namespace etl inline constexpr bool is_enum_v = etl::is_enum::value; #endif + //*************************************************************************** + /// is_scoped_enum + ///\ingroup type_traits + /// An enumeration is scoped if it is not implicitly convertible to an integer. + #if ETL_USING_CPP23 && defined(__cpp_lib_is_scoped_enum) + template + struct is_scoped_enum : std::is_scoped_enum + { + }; + #else + template + struct is_scoped_enum : etl::bool_constant::value && !std::is_convertible::value> + { + }; + #endif + + #if ETL_USING_CPP17 + template + inline constexpr bool is_scoped_enum_v = etl::is_scoped_enum::value; + #endif + #endif //*************************************************************************** @@ -3295,6 +3408,26 @@ namespace etl #else template using is_trivially_copy_constructible = etl::bool_constant::value || etl::is_pointer::value>; + #endif + + //********************************************* + // is_trivially_default_constructible + #if ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED + template + using is_trivially_default_constructible = std::is_trivially_default_constructible; + #else + template + using is_trivially_default_constructible = etl::bool_constant::value || etl::is_pointer::value>; + #endif + + //********************************************* + // is_trivially_move_constructible + #if ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED + template + using is_trivially_move_constructible = std::is_trivially_move_constructible; + #else + template + using is_trivially_move_constructible = etl::bool_constant::value || etl::is_pointer::value>; #endif //********************************************* @@ -3307,14 +3440,46 @@ namespace etl using is_trivially_destructible = etl::bool_constant::value || etl::is_pointer::value>; #endif + //********************************************* + // is_trivially_assignable + #if ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED + template + using is_trivially_assignable = std::is_trivially_assignable; + #elif ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE + template + using is_trivially_assignable = etl::bool_constant<__is_trivially_assignable(T1, T2)>; + #else + template + using is_trivially_assignable = etl::bool_constant<(etl::is_arithmetic::value || etl::is_pointer::value) + && (etl::is_arithmetic::value || etl::is_pointer::value)>; + #endif + //********************************************* // is_trivially_copy_assignable #if ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED template using is_trivially_copy_assignable = std::is_trivially_copy_assignable; + #elif ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE + template + using is_trivially_copy_assignable = + etl::is_trivially_assignable< typename etl::add_lvalue_reference::type, typename etl::add_lvalue_reference::type>; #else template using is_trivially_copy_assignable = etl::bool_constant::value || etl::is_pointer::value>; + #endif + + //********************************************* + // is_trivially_move_assignable + #if ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED + template + using is_trivially_move_assignable = std::is_trivially_move_assignable; + #elif ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE + template + using is_trivially_move_assignable = + etl::is_trivially_assignable< typename etl::add_lvalue_reference::type, typename etl::add_rvalue_reference::type>; + #else + template + using is_trivially_move_assignable = etl::bool_constant::value || etl::is_pointer::value>; #endif //********************************************* @@ -3550,6 +3715,27 @@ namespace etl { }; + //********************************************* + // is_trivially_default_constructible + template + struct is_trivially_default_constructible : public is_trivially_constructible + { + }; + + //********************************************* + // is_trivially_move_constructible + #if ETL_USING_CPP11 + template + struct is_trivially_move_constructible : public is_trivially_constructible< T, typename add_rvalue_reference::type> + { + }; + #else + template + struct is_trivially_move_constructible : public etl::bool_constant::value || etl::is_pointer::value> + { + }; + #endif + //********************************************* // is_trivially_destructible template @@ -3562,18 +3748,37 @@ namespace etl #endif }; + //********************************************* + // is_trivially_assignable + template + struct is_trivially_assignable + { + static ETL_CONSTANT bool value = __is_trivially_assignable(T1, T2); + }; + //********************************************* // is_trivially_copy_assignable template struct is_trivially_copy_assignable + : public etl::is_trivially_assignable< typename etl::add_lvalue_reference::type, typename etl::add_lvalue_reference::type> { - #if defined(ETL_COMPILER_GCC) - static ETL_CONSTANT bool value = __has_trivial_copy(T); - #else - static ETL_CONSTANT bool value = __is_trivially_copyable(T); - #endif }; + //********************************************* + // is_trivially_move_assignable + #if ETL_USING_CPP11 + template + struct is_trivially_move_assignable + : public etl::is_trivially_assignable< typename etl::add_lvalue_reference::type, typename etl::add_rvalue_reference::type> + { + }; + #else + template + struct is_trivially_move_assignable : public etl::bool_constant::value || etl::is_pointer::value> + { + }; + #endif + //********************************************* // is_trivially_copyable template @@ -3826,6 +4031,32 @@ namespace etl template struct is_trivially_copy_constructible; + //********************************************* + // is_trivially_default_constructible + template ::value || etl::is_pointer::value> + struct is_trivially_default_constructible; + + template + struct is_trivially_default_constructible : public etl::true_type + { + }; + + template + struct is_trivially_default_constructible; + + //********************************************* + // is_trivially_move_constructible + template ::value || etl::is_pointer::value> + struct is_trivially_move_constructible; + + template + struct is_trivially_move_constructible : public etl::true_type + { + }; + + template + struct is_trivially_move_constructible; + //********************************************* // is_trivially_destructible template ::value || etl::is_pointer::value> @@ -3839,6 +4070,21 @@ namespace etl template struct is_trivially_destructible; + //********************************************* + // is_trivially_assignable + template ::value || etl::is_pointer::value) && (etl::is_arithmetic::value || etl::is_pointer::value)> + struct is_trivially_assignable; + + template + struct is_trivially_assignable : public etl::true_type + { + }; + + template + struct is_trivially_assignable; + //********************************************* // is_trivially_copy_assignable template ::value || etl::is_pointer::value> @@ -3852,6 +4098,19 @@ namespace etl template struct is_trivially_copy_assignable; + //********************************************* + // is_trivially_move_assignable + template ::value || etl::is_pointer::value> + struct is_trivially_move_assignable; + + template + struct is_trivially_move_assignable : public etl::true_type + { + }; + + template + struct is_trivially_move_assignable; + //********************************************* // is_trivially_copyable template ::value || etl::is_pointer::value> @@ -4106,6 +4365,20 @@ namespace etl { }; + //********************************************* + // is_trivially_default_constructible + template + struct is_trivially_default_constructible : public etl::bool_constant::value || etl::is_pointer::value> + { + }; + + //********************************************* + // is_trivially_move_constructible + template + struct is_trivially_move_constructible : public etl::bool_constant::value || etl::is_pointer::value> + { + }; + //********************************************* // is_trivially_destructible template @@ -4113,10 +4386,40 @@ namespace etl { }; + //********************************************* + // is_trivially_assignable + template + #if ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE + struct is_trivially_assignable : public etl::bool_constant<__is_trivially_assignable(T1, T2)> + #else + struct is_trivially_assignable + : public etl::bool_constant< (etl::is_arithmetic::value || etl::is_pointer::value) + && (etl::is_arithmetic::value || etl::is_pointer::value)> + #endif + { + }; + //********************************************* // is_trivially_copy_assignable template + #if ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE + struct is_trivially_copy_assignable + : public etl::is_trivially_assignable< typename etl::add_lvalue_reference::type, typename etl::add_lvalue_reference::type> + #else struct is_trivially_copy_assignable : public etl::bool_constant::value || etl::is_pointer::value> + #endif + { + }; + + //********************************************* + // is_trivially_move_assignable + template + #if ETL_USING_CPP11 && ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE + struct is_trivially_move_assignable + : public etl::is_trivially_assignable< typename etl::add_lvalue_reference::type, typename etl::add_rvalue_reference::type> + #else + struct is_trivially_move_assignable : public etl::bool_constant::value || etl::is_pointer::value> + #endif { }; @@ -4233,12 +4536,24 @@ namespace etl template inline constexpr bool is_trivially_copy_constructible_v = etl::is_trivially_copy_constructible::value; + template + inline constexpr bool is_trivially_default_constructible_v = etl::is_trivially_default_constructible::value; + + template + inline constexpr bool is_trivially_move_constructible_v = etl::is_trivially_move_constructible::value; + template inline constexpr bool is_trivially_destructible_v = etl::is_trivially_destructible::value; + template + inline constexpr bool is_trivially_assignable_v = etl::is_trivially_assignable::value; + template inline constexpr bool is_trivially_copy_assignable_v = etl::is_trivially_copy_assignable::value; + template + inline constexpr bool is_trivially_move_assignable_v = etl::is_trivially_move_assignable::value; + template inline constexpr bool is_trivially_copyable_v = etl::is_trivially_copyable::value; diff --git a/test/test_type_traits.cpp b/test/test_type_traits.cpp index ab2e7c4c..0c031435 100644 --- a/test/test_type_traits.cpp +++ b/test/test_type_traits.cpp @@ -847,6 +847,104 @@ namespace #endif } + //************************************************************************* +#if ETL_USING_BUILTIN_IS_LAYOUT_COMPATIBLE || (ETL_USING_STL && ETL_USING_CPP20 && defined(__cpp_lib_is_layout_compatible)) + TEST(test_is_layout_compatible) + { + struct A + { + int a; + }; + + struct B + { + const int b; + }; + + struct C + { + int c1; + int c2; + }; + + struct D + { + char d; + }; + + CHECK((etl::is_layout_compatible::value)); + CHECK((etl::is_layout_compatible::value)); + CHECK((etl::is_layout_compatible::value)); + CHECK((etl::is_layout_compatible::value)); + CHECK((!etl::is_layout_compatible::value)); + CHECK((!etl::is_layout_compatible::value)); + CHECK((!etl::is_layout_compatible::value)); + + #if ETL_USING_STL && ETL_USING_CPP20 && defined(__cpp_lib_is_layout_compatible) + CHECK((etl::is_layout_compatible::value == std::is_layout_compatible::value)); + CHECK((etl::is_layout_compatible::value == std::is_layout_compatible::value)); + #endif + + #if ETL_USING_CPP17 + CHECK((etl::is_layout_compatible_v)); + CHECK((!etl::is_layout_compatible_v)); + #endif + } +#endif + + //************************************************************************* +#if ETL_USING_BUILTIN_IS_POINTER_INTERCONVERTIBLE_BASE_OF || (ETL_USING_STL && ETL_USING_CPP20 && defined(__cpp_lib_is_pointer_interconvertible)) + TEST(test_is_pointer_interconvertible_base_of) + { + struct Base + { + int b; + }; + + struct Derived : public Base + { + }; + + struct VirtualDerived : virtual public Base + { + }; + + struct Polymorphic + { + virtual ~Polymorphic() {} + + int p; + }; + + struct PolymorphicDerived : public Polymorphic + { + }; + + struct Unrelated + { + int u; + }; + + CHECK((etl::is_pointer_interconvertible_base_of::value)); + CHECK((etl::is_pointer_interconvertible_base_of::value)); + CHECK((!etl::is_pointer_interconvertible_base_of::value)); + CHECK((!etl::is_pointer_interconvertible_base_of::value)); + CHECK((!etl::is_pointer_interconvertible_base_of::value)); + CHECK((!etl::is_pointer_interconvertible_base_of::value)); + + #if ETL_USING_STL && ETL_USING_CPP20 && defined(__cpp_lib_is_pointer_interconvertible) + CHECK((etl::is_pointer_interconvertible_base_of::value == std::is_pointer_interconvertible_base_of::value)); + CHECK((etl::is_pointer_interconvertible_base_of::value + == std::is_pointer_interconvertible_base_of::value)); + #endif + + #if ETL_USING_CPP17 + CHECK((etl::is_pointer_interconvertible_base_of_v)); + CHECK((!etl::is_pointer_interconvertible_base_of_v)); + #endif + } +#endif + //************************************************************************* TEST(test_is_destructible) { @@ -2378,6 +2476,33 @@ namespace } #undef CHECK_EQUAL_FOR_TYPE + //************************************************************************* + TEST(test_is_scoped_enum) + { + CHECK_FALSE((etl::is_scoped_enum::value)); + CHECK_FALSE((etl::is_scoped_enum::value)); + CHECK_FALSE((etl::is_scoped_enum::value)); + CHECK_FALSE((etl::is_scoped_enum::value)); + CHECK_FALSE((etl::is_scoped_enum::value)); + CHECK_FALSE((etl::is_scoped_enum::value)); + CHECK_FALSE((etl::is_scoped_enum::value)); + + CHECK_TRUE((etl::is_scoped_enum::value)); + CHECK_TRUE((etl::is_scoped_enum::value)); + CHECK_FALSE((etl::is_scoped_enum::value)); + +#if ETL_USING_CPP17 + CHECK_FALSE((etl::is_scoped_enum_v)); + CHECK_TRUE((etl::is_scoped_enum_v)); +#endif + +#if ETL_USING_CPP23 && defined(__cpp_lib_is_scoped_enum) + CHECK_EQUAL((std::is_scoped_enum::value), (etl::is_scoped_enum::value)); + CHECK_EQUAL((std::is_scoped_enum::value), (etl::is_scoped_enum::value)); + CHECK_EQUAL((std::is_scoped_enum::value), (etl::is_scoped_enum::value)); +#endif + } + //************************************************************************* TEST(test_integral_constants) { @@ -2755,6 +2880,42 @@ namespace #endif } + //************************************************************************* + TEST(test_is_trivially_default_constructible) + { +#if (!(defined(ETL_COMPILER_GCC) && defined(ETL_USE_TYPE_TRAITS_BUILTINS))) + #if ETL_USING_STL || defined(ETL_USE_TYPE_TRAITS_BUILTINS) || defined(ETL_USER_DEFINED_TYPE_TRAITS) + CHECK((etl::is_trivially_default_constructible::value) == (std::is_trivially_default_constructible::value)); + CHECK((etl::is_trivially_default_constructible::value) == (std::is_trivially_default_constructible::value)); + CHECK((etl::is_trivially_default_constructible::value) == (std::is_trivially_default_constructible::value)); + CHECK((etl::is_trivially_default_constructible::value) == (std::is_trivially_default_constructible::value)); + + #if ETL_USING_CPP17 + CHECK((etl::is_trivially_default_constructible_v) == (std::is_trivially_default_constructible_v)); + CHECK((etl::is_trivially_default_constructible_v) == (std::is_trivially_default_constructible_v)); + #endif + #endif +#endif + } + + //************************************************************************* + TEST(test_is_trivially_move_constructible) + { +#if (!(defined(ETL_COMPILER_GCC) && defined(ETL_USE_TYPE_TRAITS_BUILTINS))) + #if ETL_USING_CPP11 && (ETL_USING_STL || defined(ETL_USE_TYPE_TRAITS_BUILTINS) || defined(ETL_USER_DEFINED_TYPE_TRAITS)) + CHECK((etl::is_trivially_move_constructible::value) == (std::is_trivially_move_constructible::value)); + CHECK((etl::is_trivially_move_constructible::value) == (std::is_trivially_move_constructible::value)); + CHECK((etl::is_trivially_move_constructible::value) == (std::is_trivially_move_constructible::value)); + CHECK((etl::is_trivially_move_constructible::value) == (std::is_trivially_move_constructible::value)); + + #if ETL_USING_CPP17 + CHECK((etl::is_trivially_move_constructible_v) == (std::is_trivially_move_constructible_v)); + CHECK((etl::is_trivially_move_constructible_v) == (std::is_trivially_move_constructible_v)); + #endif + #endif +#endif + } + //************************************************************************* TEST(test_is_trivially_destructible) { @@ -2771,6 +2932,25 @@ namespace #endif } + //************************************************************************* + TEST(test_is_trivially_assignable) + { +#if ETL_USING_CPP11 && !defined(ETL_USER_DEFINED_TYPE_TRAITS) \ + && (ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED || ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE) + CHECK((etl::is_trivially_assignable::value) == (std::is_trivially_assignable::value)); + CHECK((etl::is_trivially_assignable::value) == (std::is_trivially_assignable::value)); + CHECK((etl::is_trivially_assignable::value) == (std::is_trivially_assignable::value)); + CHECK((etl::is_trivially_assignable::value) == (std::is_trivially_assignable::value)); + CHECK((etl::is_trivially_assignable::value) + == (std::is_trivially_assignable::value)); + + #if ETL_USING_CPP17 + CHECK((etl::is_trivially_assignable_v) == (std::is_trivially_assignable_v)); + CHECK((etl::is_trivially_assignable_v) == (std::is_trivially_assignable_v)); + #endif +#endif + } + //************************************************************************* TEST(test_is_trivially_copy_assignable) { @@ -2789,6 +2969,23 @@ namespace #endif } + //************************************************************************* + TEST(test_is_trivially_move_assignable) + { +#if ETL_USING_CPP11 && !defined(ETL_USER_DEFINED_TYPE_TRAITS) \ + && (ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED || ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE) + CHECK((etl::is_trivially_move_assignable::value) == (std::is_trivially_move_assignable::value)); + CHECK((etl::is_trivially_move_assignable::value) == (std::is_trivially_move_assignable::value)); + CHECK((etl::is_trivially_move_assignable::value) == (std::is_trivially_move_assignable::value)); + CHECK((etl::is_trivially_move_assignable::value) == (std::is_trivially_move_assignable::value)); + + #if ETL_USING_CPP17 + CHECK((etl::is_trivially_move_assignable_v) == (std::is_trivially_move_assignable_v)); + CHECK((etl::is_trivially_move_assignable_v) == (std::is_trivially_move_assignable_v)); + #endif +#endif + } + //************************************************************************* TEST(test_is_trivially_copyable) {