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 <jwellbelove@users.noreply.github.com>
This commit is contained in:
Roland Reichwein 2026-08-31 20:09:16 +02:00 committed by GitHub
parent fa238db580
commit 06e54f6b23
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 682 additions and 5 deletions

View File

@ -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`
&emsp;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 <typename T>
inline constexpr bool is_scalar_v = etl::is_scalar<T>::value;
```
C++17
## is_scoped_enum
From: `20.50.0`
```cpp
template <typename T>
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 <typename T>
inline constexpr bool is_scoped_enum_v = etl::is_scoped_enum<T>::value;
```
C++17
## is_trivially_default_constructible
From: `20.50.0`
```cpp
template <typename T>
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 <typename T>
inline constexpr bool is_trivially_default_constructible_v = etl::is_trivially_default_constructible<T>::value;
```
C++17
## is_trivially_move_constructible
From: `20.50.0`
```cpp
template <typename T>
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 <typename T>
inline constexpr bool is_trivially_move_constructible_v = etl::is_trivially_move_constructible<T>::value;
```
C++17
## is_trivially_move_assignable
From: `20.50.0`
```cpp
template <typename T>
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 <typename T>
inline constexpr bool is_trivially_move_assignable_v = etl::is_trivially_move_assignable<T>::value;
```
C++17
## is_trivially_assignable
```cpp
template <typename T1, typename T2>
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`.
&emsp;See Scenarios 1 to 4 above for how this trait is defined when the STL or the compiler built-ins are unavailable.
```cpp
template <typename T1, typename T2>
inline constexpr bool is_trivially_assignable_v = etl::is_trivially_assignable<T1, T2>::value;
```
C++17
## is_layout_compatible
From: `20.50.0`
```cpp
template <typename T, typename U>
struct is_layout_compatible
```
Checks if `T` and `U` are layout-compatible types.
The result is found in the member `value`.
&emsp;When using the STL with C++20 or above, this is defined as `std::is_layout_compatible<T, U>`.
&emsp;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 <typename T, typename U>
inline constexpr bool is_layout_compatible_v = etl::is_layout_compatible<T, U>::value;
```
C++17
## is_pointer_interconvertible_base_of
From: `20.50.0`
```cpp
template <typename TBase, typename TDerived>
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`.
&emsp;When using the STL with C++20 or above, this is defined as `std::is_pointer_interconvertible_base_of<TBase, TDerived>`.
&emsp;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.
&emsp;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 <typename TBase, typename TDerived>
inline constexpr bool is_pointer_interconvertible_base_of_v = etl::is_pointer_interconvertible_base_of<TBase, TDerived>::value;
```
C++17

View File

@ -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);

View File

@ -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 <typename T, typename U>
struct is_layout_compatible : etl::bool_constant<__is_layout_compatible(T, U)>
{
};
#if ETL_USING_CPP17
template <typename T, typename U>
inline constexpr bool is_layout_compatible_v = etl::is_layout_compatible<T, U>::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 <typename TBase, typename TDerived>
struct is_pointer_interconvertible_base_of : etl::bool_constant<__is_pointer_interconvertible_base_of(TBase, TDerived)>
{
};
#if ETL_USING_CPP17
template <typename TBase, typename TDerived>
inline constexpr bool is_pointer_interconvertible_base_of_v = etl::is_pointer_interconvertible_base_of<TBase, TDerived>::value;
#endif
#endif
//***************************************************************************
/// conditional
template <bool BValue, typename T, typename F>
@ -1667,6 +1699,20 @@ namespace etl
inline constexpr bool is_nothrow_convertible_v = etl::is_nothrow_convertible<TFrom, TTo>::value;
#endif
//***************************************************************************
/// is_scoped_enum
///\ingroup type_traits
/// An enumeration is scoped if it is not implicitly convertible to an integer.
template <typename T>
struct is_scoped_enum : etl::bool_constant<etl::is_enum<T>::value && !etl::is_convertible<T, int>::value>
{
};
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_scoped_enum_v = etl::is_scoped_enum<T>::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 <typename T, typename U>
struct is_layout_compatible : std::is_layout_compatible<T, U>
{
};
template <typename T, typename U>
inline constexpr bool is_layout_compatible_v = std::is_layout_compatible_v<T, U>;
#elif ETL_USING_BUILTIN_IS_LAYOUT_COMPATIBLE
template <typename T, typename U>
struct is_layout_compatible : etl::bool_constant<__is_layout_compatible(T, U)>
{
};
#if ETL_USING_CPP17
template <typename T, typename U>
inline constexpr bool is_layout_compatible_v = etl::is_layout_compatible<T, U>::value;
#endif
#endif
//***************************************************************************
/// is_pointer_interconvertible_base_of
///\ingroup type_traits
#if ETL_USING_CPP20 && defined(__cpp_lib_is_pointer_interconvertible)
template <typename TBase, typename TDerived>
struct is_pointer_interconvertible_base_of : std::is_pointer_interconvertible_base_of<TBase, TDerived>
{
};
template <typename TBase, typename TDerived>
inline constexpr bool is_pointer_interconvertible_base_of_v = std::is_pointer_interconvertible_base_of_v<TBase, TDerived>;
#elif ETL_USING_BUILTIN_IS_POINTER_INTERCONVERTIBLE_BASE_OF
template <typename TBase, typename TDerived>
struct is_pointer_interconvertible_base_of : etl::bool_constant<__is_pointer_interconvertible_base_of(TBase, TDerived)>
{
};
#if ETL_USING_CPP17
template <typename TBase, typename TDerived>
inline constexpr bool is_pointer_interconvertible_base_of_v = etl::is_pointer_interconvertible_base_of<TBase, TDerived>::value;
#endif
#endif
//***************************************************************************
/// is_destructible
///\ingroup type_traits
@ -2711,6 +2803,27 @@ namespace etl
inline constexpr bool is_enum_v = etl::is_enum<T>::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 <typename T>
struct is_scoped_enum : std::is_scoped_enum<T>
{
};
#else
template <typename T>
struct is_scoped_enum : etl::bool_constant<std::is_enum<T>::value && !std::is_convertible<T, int>::value>
{
};
#endif
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_scoped_enum_v = etl::is_scoped_enum<T>::value;
#endif
#endif
//***************************************************************************
@ -3295,6 +3408,26 @@ namespace etl
#else
template <typename T>
using is_trivially_copy_constructible = etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>;
#endif
//*********************************************
// is_trivially_default_constructible
#if ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED
template <typename T>
using is_trivially_default_constructible = std::is_trivially_default_constructible<T>;
#else
template <typename T>
using is_trivially_default_constructible = etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>;
#endif
//*********************************************
// is_trivially_move_constructible
#if ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED
template <typename T>
using is_trivially_move_constructible = std::is_trivially_move_constructible<T>;
#else
template <typename T>
using is_trivially_move_constructible = etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>;
#endif
//*********************************************
@ -3307,14 +3440,46 @@ namespace etl
using is_trivially_destructible = etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>;
#endif
//*********************************************
// is_trivially_assignable
#if ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED
template <typename T1, typename T2>
using is_trivially_assignable = std::is_trivially_assignable<T1, T2>;
#elif ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE
template <typename T1, typename T2>
using is_trivially_assignable = etl::bool_constant<__is_trivially_assignable(T1, T2)>;
#else
template <typename T1, typename T2>
using is_trivially_assignable = etl::bool_constant<(etl::is_arithmetic<T1>::value || etl::is_pointer<T1>::value)
&& (etl::is_arithmetic<T2>::value || etl::is_pointer<T2>::value)>;
#endif
//*********************************************
// is_trivially_copy_assignable
#if ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED
template <typename T>
using is_trivially_copy_assignable = std::is_trivially_copy_assignable<T>;
#elif ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE
template <typename T>
using is_trivially_copy_assignable =
etl::is_trivially_assignable< typename etl::add_lvalue_reference<T>::type, typename etl::add_lvalue_reference<const T>::type>;
#else
template <typename T>
using is_trivially_copy_assignable = etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>;
#endif
//*********************************************
// is_trivially_move_assignable
#if ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED
template <typename T>
using is_trivially_move_assignable = std::is_trivially_move_assignable<T>;
#elif ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE
template <typename T>
using is_trivially_move_assignable =
etl::is_trivially_assignable< typename etl::add_lvalue_reference<T>::type, typename etl::add_rvalue_reference<T>::type>;
#else
template <typename T>
using is_trivially_move_assignable = etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>;
#endif
//*********************************************
@ -3550,6 +3715,27 @@ namespace etl
{
};
//*********************************************
// is_trivially_default_constructible
template <typename T>
struct is_trivially_default_constructible : public is_trivially_constructible<T>
{
};
//*********************************************
// is_trivially_move_constructible
#if ETL_USING_CPP11
template <typename T>
struct is_trivially_move_constructible : public is_trivially_constructible< T, typename add_rvalue_reference<T>::type>
{
};
#else
template <typename T>
struct is_trivially_move_constructible : public etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
{
};
#endif
//*********************************************
// is_trivially_destructible
template <typename T>
@ -3562,18 +3748,37 @@ namespace etl
#endif
};
//*********************************************
// is_trivially_assignable
template <typename T1, typename T2>
struct is_trivially_assignable
{
static ETL_CONSTANT bool value = __is_trivially_assignable(T1, T2);
};
//*********************************************
// is_trivially_copy_assignable
template <typename T>
struct is_trivially_copy_assignable
: public etl::is_trivially_assignable< typename etl::add_lvalue_reference<T>::type, typename etl::add_lvalue_reference<const T>::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 <typename T>
struct is_trivially_move_assignable
: public etl::is_trivially_assignable< typename etl::add_lvalue_reference<T>::type, typename etl::add_rvalue_reference<T>::type>
{
};
#else
template <typename T>
struct is_trivially_move_assignable : public etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
{
};
#endif
//*********************************************
// is_trivially_copyable
template <typename T>
@ -3826,6 +4031,32 @@ namespace etl
template <typename T>
struct is_trivially_copy_constructible<T, false>;
//*********************************************
// is_trivially_default_constructible
template <typename T, bool BValue = etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
struct is_trivially_default_constructible;
template <typename T>
struct is_trivially_default_constructible<T, true> : public etl::true_type
{
};
template <typename T>
struct is_trivially_default_constructible<T, false>;
//*********************************************
// is_trivially_move_constructible
template <typename T, bool BValue = etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
struct is_trivially_move_constructible;
template <typename T>
struct is_trivially_move_constructible<T, true> : public etl::true_type
{
};
template <typename T>
struct is_trivially_move_constructible<T, false>;
//*********************************************
// is_trivially_destructible
template <typename T, bool BValue = etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
@ -3839,6 +4070,21 @@ namespace etl
template <typename T>
struct is_trivially_destructible<T, false>;
//*********************************************
// is_trivially_assignable
template <typename T1, typename T2,
bool BValue =
(etl::is_arithmetic<T1>::value || etl::is_pointer<T1>::value) && (etl::is_arithmetic<T2>::value || etl::is_pointer<T2>::value)>
struct is_trivially_assignable;
template <typename T1, typename T2>
struct is_trivially_assignable<T1, T2, true> : public etl::true_type
{
};
template <typename T1, typename T2>
struct is_trivially_assignable<T1, T2, false>;
//*********************************************
// is_trivially_copy_assignable
template <typename T, bool BValue = etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
@ -3852,6 +4098,19 @@ namespace etl
template <typename T>
struct is_trivially_copy_assignable<T, false>;
//*********************************************
// is_trivially_move_assignable
template <typename T, bool BValue = etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
struct is_trivially_move_assignable;
template <typename T>
struct is_trivially_move_assignable<T, true> : public etl::true_type
{
};
template <typename T>
struct is_trivially_move_assignable<T, false>;
//*********************************************
// is_trivially_copyable
template <typename T, bool BValue = etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
@ -4106,6 +4365,20 @@ namespace etl
{
};
//*********************************************
// is_trivially_default_constructible
template <typename T>
struct is_trivially_default_constructible : public etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
{
};
//*********************************************
// is_trivially_move_constructible
template <typename T>
struct is_trivially_move_constructible : public etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
{
};
//*********************************************
// is_trivially_destructible
template <typename T>
@ -4113,10 +4386,40 @@ namespace etl
{
};
//*********************************************
// is_trivially_assignable
template <typename T1, typename T2>
#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<T1>::value || etl::is_pointer<T1>::value)
&& (etl::is_arithmetic<T2>::value || etl::is_pointer<T2>::value)>
#endif
{
};
//*********************************************
// is_trivially_copy_assignable
template <typename T>
#if ETL_USING_BUILTIN_IS_TRIVIALLY_ASSIGNABLE
struct is_trivially_copy_assignable
: public etl::is_trivially_assignable< typename etl::add_lvalue_reference<T>::type, typename etl::add_lvalue_reference<const T>::type>
#else
struct is_trivially_copy_assignable : public etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
#endif
{
};
//*********************************************
// is_trivially_move_assignable
template <typename T>
#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<T>::type, typename etl::add_rvalue_reference<T>::type>
#else
struct is_trivially_move_assignable : public etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
#endif
{
};
@ -4233,12 +4536,24 @@ namespace etl
template <typename T>
inline constexpr bool is_trivially_copy_constructible_v = etl::is_trivially_copy_constructible<T>::value;
template <typename T>
inline constexpr bool is_trivially_default_constructible_v = etl::is_trivially_default_constructible<T>::value;
template <typename T>
inline constexpr bool is_trivially_move_constructible_v = etl::is_trivially_move_constructible<T>::value;
template <typename T>
inline constexpr bool is_trivially_destructible_v = etl::is_trivially_destructible<T>::value;
template <typename T1, typename T2>
inline constexpr bool is_trivially_assignable_v = etl::is_trivially_assignable<T1, T2>::value;
template <typename T>
inline constexpr bool is_trivially_copy_assignable_v = etl::is_trivially_copy_assignable<T>::value;
template <typename T>
inline constexpr bool is_trivially_move_assignable_v = etl::is_trivially_move_assignable<T>::value;
template <typename T>
inline constexpr bool is_trivially_copyable_v = etl::is_trivially_copyable<T>::value;

View File

@ -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<int, int>::value));
CHECK((etl::is_layout_compatible<int, const int>::value));
CHECK((etl::is_layout_compatible<A, A>::value));
CHECK((etl::is_layout_compatible<A, B>::value));
CHECK((!etl::is_layout_compatible<A, C>::value));
CHECK((!etl::is_layout_compatible<A, D>::value));
CHECK((!etl::is_layout_compatible<int, char>::value));
#if ETL_USING_STL && ETL_USING_CPP20 && defined(__cpp_lib_is_layout_compatible)
CHECK((etl::is_layout_compatible<A, B>::value == std::is_layout_compatible<A, B>::value));
CHECK((etl::is_layout_compatible<A, C>::value == std::is_layout_compatible<A, C>::value));
#endif
#if ETL_USING_CPP17
CHECK((etl::is_layout_compatible_v<A, B>));
CHECK((!etl::is_layout_compatible_v<A, C>));
#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<Base, Base>::value));
CHECK((etl::is_pointer_interconvertible_base_of<Base, Derived>::value));
CHECK((!etl::is_pointer_interconvertible_base_of<Base, VirtualDerived>::value));
CHECK((!etl::is_pointer_interconvertible_base_of<Polymorphic, PolymorphicDerived>::value));
CHECK((!etl::is_pointer_interconvertible_base_of<Base, Unrelated>::value));
CHECK((!etl::is_pointer_interconvertible_base_of<Derived, Base>::value));
#if ETL_USING_STL && ETL_USING_CPP20 && defined(__cpp_lib_is_pointer_interconvertible)
CHECK((etl::is_pointer_interconvertible_base_of<Base, Derived>::value == std::is_pointer_interconvertible_base_of<Base, Derived>::value));
CHECK((etl::is_pointer_interconvertible_base_of<Base, VirtualDerived>::value
== std::is_pointer_interconvertible_base_of<Base, VirtualDerived>::value));
#endif
#if ETL_USING_CPP17
CHECK((etl::is_pointer_interconvertible_base_of_v<Base, Derived>));
CHECK((!etl::is_pointer_interconvertible_base_of_v<Base, VirtualDerived>));
#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<void>::value));
CHECK_FALSE((etl::is_scoped_enum<int>::value));
CHECK_FALSE((etl::is_scoped_enum<int*>::value));
CHECK_FALSE((etl::is_scoped_enum<ToAny>::value));
CHECK_FALSE((etl::is_scoped_enum<Enum>::value));
CHECK_FALSE((etl::is_scoped_enum<const Enum>::value));
CHECK_FALSE((etl::is_scoped_enum<Enum*>::value));
CHECK_TRUE((etl::is_scoped_enum<EnumClass>::value));
CHECK_TRUE((etl::is_scoped_enum<const EnumClass>::value));
CHECK_FALSE((etl::is_scoped_enum<EnumClass*>::value));
#if ETL_USING_CPP17
CHECK_FALSE((etl::is_scoped_enum_v<Enum>));
CHECK_TRUE((etl::is_scoped_enum_v<EnumClass>));
#endif
#if ETL_USING_CPP23 && defined(__cpp_lib_is_scoped_enum)
CHECK_EQUAL((std::is_scoped_enum<Enum>::value), (etl::is_scoped_enum<Enum>::value));
CHECK_EQUAL((std::is_scoped_enum<EnumClass>::value), (etl::is_scoped_enum<EnumClass>::value));
CHECK_EQUAL((std::is_scoped_enum<int>::value), (etl::is_scoped_enum<int>::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<int>::value) == (std::is_trivially_default_constructible<int>::value));
CHECK((etl::is_trivially_default_constructible<Copyable>::value) == (std::is_trivially_default_constructible<Copyable>::value));
CHECK((etl::is_trivially_default_constructible<Moveable>::value) == (std::is_trivially_default_constructible<Moveable>::value));
CHECK((etl::is_trivially_default_constructible<MoveableCopyable>::value) == (std::is_trivially_default_constructible<MoveableCopyable>::value));
#if ETL_USING_CPP17
CHECK((etl::is_trivially_default_constructible_v<int>) == (std::is_trivially_default_constructible_v<int>));
CHECK((etl::is_trivially_default_constructible_v<Copyable>) == (std::is_trivially_default_constructible_v<Copyable>));
#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<int>::value) == (std::is_trivially_move_constructible<int>::value));
CHECK((etl::is_trivially_move_constructible<Copyable>::value) == (std::is_trivially_move_constructible<Copyable>::value));
CHECK((etl::is_trivially_move_constructible<Moveable>::value) == (std::is_trivially_move_constructible<Moveable>::value));
CHECK((etl::is_trivially_move_constructible<MoveableCopyable>::value) == (std::is_trivially_move_constructible<MoveableCopyable>::value));
#if ETL_USING_CPP17
CHECK((etl::is_trivially_move_constructible_v<int>) == (std::is_trivially_move_constructible_v<int>));
CHECK((etl::is_trivially_move_constructible_v<Moveable>) == (std::is_trivially_move_constructible_v<Moveable>));
#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<int&, int>::value) == (std::is_trivially_assignable<int&, int>::value));
CHECK((etl::is_trivially_assignable<int, int>::value) == (std::is_trivially_assignable<int, int>::value));
CHECK((etl::is_trivially_assignable<Copyable&, const Copyable&>::value) == (std::is_trivially_assignable<Copyable&, const Copyable&>::value));
CHECK((etl::is_trivially_assignable<Moveable&, Moveable&&>::value) == (std::is_trivially_assignable<Moveable&, Moveable&&>::value));
CHECK((etl::is_trivially_assignable<MoveableCopyable&, const MoveableCopyable&>::value)
== (std::is_trivially_assignable<MoveableCopyable&, const MoveableCopyable&>::value));
#if ETL_USING_CPP17
CHECK((etl::is_trivially_assignable_v<int&, int>) == (std::is_trivially_assignable_v<int&, int>));
CHECK((etl::is_trivially_assignable_v<Copyable&, const Copyable&>) == (std::is_trivially_assignable_v<Copyable&, const Copyable&>));
#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<int>::value) == (std::is_trivially_move_assignable<int>::value));
CHECK((etl::is_trivially_move_assignable<Copyable>::value) == (std::is_trivially_move_assignable<Copyable>::value));
CHECK((etl::is_trivially_move_assignable<Moveable>::value) == (std::is_trivially_move_assignable<Moveable>::value));
CHECK((etl::is_trivially_move_assignable<MoveableCopyable>::value) == (std::is_trivially_move_assignable<MoveableCopyable>::value));
#if ETL_USING_CPP17
CHECK((etl::is_trivially_move_assignable_v<int>) == (std::is_trivially_move_assignable_v<int>));
CHECK((etl::is_trivially_move_assignable_v<Moveable>) == (std::is_trivially_move_assignable_v<Moveable>));
#endif
#endif
}
//*************************************************************************
TEST(test_is_trivially_copyable)
{