Add etl::is_standard_layout and other type traits according to std (#1545)

* Update _index.md

* Update _index.md

* Cherry pick the Docker fixes for PowerPC (#1563)

Co-authored-by: John Wellbelove <john.wellbelove@etlcpp.com>

* Add etl::is_standard_layout and further type traits

Added type traits:

* etl::is_standard_layout
* etl::is_null_pointer
* etl::is_union
* etl::is_scalar
* etl::is_empty
* etl::is_polymorphic
* etl::is_abstract
* etl::is_final
* etl::is_aggregate
* etl::is_destructible
* etl::is_nothrow_destructible
* etl::has_virtual_destructor
* etl::is_swappable
* etl::is_swappable_with
* etl::is_nothrow_swappable
* etl::is_nothrow_swappable_with
* etl::has_unique_object_representation
* etl::is_bounded_array
* etl::is_unbounded_array
* etl::is_trivial

Document etl::is_pod

Note that etl::swap needed adjustment to enable nothrow detection via
SFINAE constraints. This change closes in to the standard.

* Fix preprocessor directive formatting in header

---------

Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>
Co-authored-by: John Wellbelove <john.wellbelove@etlcpp.com>
This commit is contained in:
Roland Reichwein 2026-08-24 14:11:11 +02:00 committed by GitHub
parent 25e2d6e8a3
commit fa3ac28f55
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 2457 additions and 1 deletions

View File

@ -32,6 +32,26 @@ Not all traits have been defined as some rely on compiler intrinsics that are no
`is_compound`
`is_array`
`is_pointer`
`is_null_pointer`
`is_scalar`
`is_union`
`is_empty`
`is_polymorphic`
`is_abstract`
`is_final`
`is_aggregate`
`is_trivial`
`is_standard_layout`
`is_destructible`
`is_nothrow_destructible`
`has_virtual_destructor`
`has_unique_object_representations`
`is_bounded_array`
`is_unbounded_array`
`is_swappable`
`is_swappable_with`
`is_nothrow_swappable`
`is_nothrow_swappable_with`
`is_reference`
`is_base_of`
`make_signed`
@ -476,3 +496,382 @@ template <typename T>
inline constexpr bool is_object_pointer_v = etl::is_object_pointer<T>::value;
```
C++17
## is_pod
From: `20.49.0`
```cpp
template <typename T>
struct is_pod
```
Checks if `T` is a POD (Plain Old Data) type.
The result is found in the member `value`.
&emsp;When using the STL, this is defined as `is_standard_layout<T> && is_trivially_default_constructible<T> && is_trivially_copyable<T>`.
&emsp;When not using the STL, this is conservatively defined as `is_fundamental<T> || is_pointer<T>`.
```cpp
template <typename T>
inline constexpr bool is_pod_v = etl::is_pod<T>::value;
```
C++17
## is_standard_layout
From: `20.49.0`
```cpp
template <typename T>
struct is_standard_layout
```
Checks if `T` is a standard-layout type.
The result is found in the member `value`.
```cpp
template <typename T>
inline constexpr bool is_standard_layout_v = etl::is_standard_layout<T>::value;
```
C++17
## is_trivial
From: `20.49.0`
```cpp
template <typename T>
struct is_trivial
```
Checks if `T` is a trivial type; i.e. it is trivially copyable and has one or more
default constructors, all of which are trivial.
The result is found in the member `value`.
```cpp
template <typename T>
inline constexpr bool is_trivial_v = etl::is_trivial<T>::value;
```
C++17
**Note:** When not using the STL, this trait requires compiler support (the `__is_trivial` intrinsic).
If that is not available then the trait is not defined, as there is no portable way of
determining whether a type is trivial.
## is_bounded_array
From: `20.49.0`
```cpp
template <typename T>
struct is_bounded_array
```
Checks if `T` is an array type of known bound.
`T[N]` returns `true`, `T[]` and all other types return `false`.
The result is found in the member `value`.
```cpp
template <typename T>
inline constexpr bool is_bounded_array_v = etl::is_bounded_array<T>::value;
```
C++17
## is_unbounded_array
From: `20.49.0`
```cpp
template <typename T>
struct is_unbounded_array
```
Checks if `T` is an array type of unknown bound.
`T[]` returns `true`, `T[N]` and all other types return `false`.
The result is found in the member `value`.
```cpp
template <typename T>
inline constexpr bool is_unbounded_array_v = etl::is_unbounded_array<T>::value;
```
C++17
## is_destructible
From: `20.49.0`
```cpp
template <typename T>
struct is_destructible
```
Checks if `T` is a destructible type; that is, an object type whose destructor is not deleted and is accessible, a reference type, or an array of a destructible type.
Incomplete types, `void`, function types and arrays of unknown bound are not destructible.
The result is found in the member `value`.
&emsp;When not using the STL, the trait is detected by checking whether `declval<T&>().~T()` is a valid expression.
&emsp;Requires either compiler support or C++11. When neither is available, this trait is not defined.
```cpp
template <typename T>
inline constexpr bool is_destructible_v = etl::is_destructible<T>::value;
```
C++17
## is_nothrow_destructible
From: `20.49.0`
```cpp
template <typename T>
struct is_nothrow_destructible
```
Checks if `T` is a destructible type whose destructor is known not to throw.
Types that are not destructible are not nothrow destructible.
The result is found in the member `value`.
&emsp;When not using the STL, the trait is detected by checking `noexcept(declval<T&>().~T())` for destructible types.
&emsp;Requires either compiler support or C++11. When neither is available, this trait is not defined.
```cpp
template <typename T>
inline constexpr bool is_nothrow_destructible_v = etl::is_nothrow_destructible<T>::value;
```
C++17
## is_swappable
From: `20.49.0`
```cpp
template <typename T>
struct is_swappable
```
Checks if `T` is a referenceable type and lvalues of type `T` can be swapped by an unqualified call to `swap`.
The result is found in the member `value`.
&emsp;When using the STL and C++17, this is defined as `std::is_swappable<T>`.
&emsp;Otherwise the trait checks whether `swap(declval<T&>(), declval<T&>())` is a valid expression, where the `swap` considered is `etl::swap`, `std::swap` if it is available, and any `swap` found by argument dependent lookup.
&emsp;Requires C++11. Without it there is no way of detecting the validity of an expression, so this trait is not defined.
&emsp;Note that when using the STL with C++11 or C++14, the accuracy of this trait depends on `std::swap` being constrained by the standard library implementation. Standard libraries that only constrain `std::swap` from C++17 will cause this trait to report `true` for types that cannot actually be swapped.
```cpp
template <typename T>
inline constexpr bool is_swappable_v = etl::is_swappable<T>::value;
```
C++17
## is_swappable_with
From: `20.49.0`
```cpp
template <typename T, typename U>
struct is_swappable_with
```
Checks if expressions of type `T` and `U` can be swapped by unqualified calls to `swap`, in both directions.
The result is found in the member `value`.
&emsp;When using the STL and C++17, this is defined as `std::is_swappable_with<T, U>`.
&emsp;Otherwise the trait checks whether both `swap(declval<T>(), declval<U>())` and `swap(declval<U>(), declval<T>())` are valid expressions, where the `swap` considered is `etl::swap`, `std::swap` if it is available, and any `swap` found by argument dependent lookup.
&emsp;Note that, unlike `is_swappable`, no references are added to `T` and `U`, so the value categories of the arguments are those of `T` and `U`. `is_swappable_with<int, int>::value` is `false`, whereas `is_swappable_with<int&, int&>::value` is `true`.
&emsp;Requires C++11. Without it there is no way of detecting the validity of an expression, so this trait is not defined.
&emsp;Note that when using the STL with C++11 or C++14, the accuracy of this trait depends on `std::swap` being constrained by the standard library implementation. Standard libraries that only constrain `std::swap` from C++17 will cause this trait to report `true` for types that cannot actually be swapped.
```cpp
template <typename T, typename U>
inline constexpr bool is_swappable_with_v = etl::is_swappable_with<T, U>::value;
```
C++17
## is_nothrow_swappable
From: `20.49.0`
```cpp
template <typename T>
struct is_nothrow_swappable
```
Checks if `T` is a referenceable type and lvalues of type `T` can be swapped by an unqualified call to `swap`, and that the swap cannot throw.
The result is found in the member `value`.
&emsp;When using the STL and C++17, this is defined as `std::is_nothrow_swappable<T>`.
&emsp;Otherwise the trait checks that `etl::is_swappable<T>::value` is `true` and that `swap(declval<T&>(), declval<T&>())` is `noexcept`.
&emsp;Requires C++11. Without it there is no way of detecting the validity of an expression, so this trait is not defined.
&emsp;Note that when neither the STL nor the type traits builtins are available, `etl::is_nothrow_move_constructible` and `etl::is_nothrow_move_assignable` are conservatively `false` for class types, so `etl::swap` is not `noexcept` for them and this trait is conservatively `false` too.
```cpp
template <typename T>
inline constexpr bool is_nothrow_swappable_v = etl::is_nothrow_swappable<T>::value;
```
C++17
## is_nothrow_swappable_with
From: `20.49.0`
```cpp
template <typename T, typename U>
struct is_nothrow_swappable_with
```
Checks if expressions of type `T` and `U` can be swapped by unqualified calls to `swap`, in both directions, and that neither swap can throw.
The result is found in the member `value`.
&emsp;When using the STL and C++17, this is defined as `std::is_nothrow_swappable_with<T, U>`.
&emsp;Otherwise the trait checks that `etl::is_swappable_with<T, U>::value` is `true` and that both `swap(declval<T>(), declval<U>())` and `swap(declval<U>(), declval<T>())` are `noexcept`.
&emsp;Note that, as for `is_swappable_with`, no references are added to `T` and `U`, so the value categories of the arguments are those of `T` and `U`. `is_nothrow_swappable_with<int, int>::value` is `false`, whereas `is_nothrow_swappable_with<int&, int&>::value` is `true`.
&emsp;Requires C++11. Without it there is no way of detecting the validity of an expression, so this trait is not defined.
&emsp;Note that when neither the STL nor the type traits builtins are available, `etl::is_nothrow_move_constructible` and `etl::is_nothrow_move_assignable` are conservatively `false` for class types, so `etl::swap` is not `noexcept` for them and this trait is conservatively `false` too.
```cpp
template <typename T, typename U>
inline constexpr bool is_nothrow_swappable_with_v = etl::is_nothrow_swappable_with<T, U>::value;
```
C++17
## is_union
From: `20.49.0`
```cpp
template <typename T>
struct is_union
```
Checks if `T` is a union type.
The result is found in the member `value`.
&emsp;When the compiler does not provide the required intrinsic, this trait conservatively reports `false` for every type.
```cpp
template <typename T>
inline constexpr bool is_union_v = etl::is_union<T>::value;
```
C++17
## is_empty
From: `20.49.0`
```cpp
template <typename T>
struct is_empty
```
Checks if `T` is an empty class type; that is, a non-union class type with no non-static data members other than zero-sized bit-fields, no virtual functions, no virtual base classes and no non-empty base classes.
The result is found in the member `value`.
&emsp;Requires compiler support. When the compiler does not provide the required intrinsic, this trait is not defined.
```cpp
template <typename T>
inline constexpr bool is_empty_v = etl::is_empty<T>::value;
```
C++17
## is_polymorphic
From: `20.49.0`
```cpp
template <typename T>
struct is_polymorphic
```
Checks if `T` is a polymorphic class type; that is, a class that declares or inherits at least one virtual function.
The result is found in the member `value`.
&emsp;Requires compiler support. When the compiler does not provide the required intrinsic, this trait is not defined.
```cpp
template <typename T>
inline constexpr bool is_polymorphic_v = etl::is_polymorphic<T>::value;
```
C++17
## is_abstract
From: `20.49.0`
```cpp
template <typename T>
struct is_abstract
```
Checks if `T` is an abstract class type; that is, a class that declares or inherits at least one pure virtual function.
The result is found in the member `value`.
&emsp;Requires compiler support. When the compiler does not provide the required intrinsic, this trait is not defined.
```cpp
template <typename T>
inline constexpr bool is_abstract_v = etl::is_abstract<T>::value;
```
C++17
## is_final
From: `20.49.0`
```cpp
template <typename T>
struct is_final
```
Checks if `T` is a class or union type marked `final`, optionally cv-qualified.
The result is found in the member `value`.
&emsp;When using the STL, this requires C++14 or above. Otherwise it requires compiler support. When neither is available, this trait is not defined.
```cpp
template <typename T>
inline constexpr bool is_final_v = etl::is_final<T>::value;
```
C++17
## is_aggregate
From: `20.49.0`
```cpp
template <typename T>
struct is_aggregate
```
Checks if `T` is an aggregate type, optionally cv-qualified.
An aggregate is an array type or a class type that has no user-declared or inherited constructors, no private or protected non-static data members, no virtual functions and no virtual, private or protected base classes.
The result is found in the member `value`.
&emsp;When using the STL, this requires C++17 or above. Otherwise it requires compiler support. When neither is available, this trait is not defined.
```cpp
template <typename T>
inline constexpr bool is_aggregate_v = etl::is_aggregate<T>::value;
```
C++17
## has_virtual_destructor
From: `20.49.0`
```cpp
template <typename T>
struct has_virtual_destructor
```
Checks if `T` is a class type with a virtual destructor, optionally cv-qualified.
The result is found in the member `value`.
&emsp;When not using the STL, this requires compiler support. When it is not available, this trait is not defined.
```cpp
template <typename T>
inline constexpr bool has_virtual_destructor_v = etl::has_virtual_destructor<T>::value;
```
C++17
## has_unique_object_representations
From: `20.49.0`
```cpp
template <typename T>
struct has_unique_object_representations
```
Checks if `T` is trivially copyable and any two objects of type `T` with the same value have the same object representation; that is, the type has no padding bits and no two distinct object representations compare equal.
Arrays and cv-qualifiers are ignored; the trait is applied to `etl::remove_all_extents<typename etl::remove_cv<T>::type>::type`.
The result is found in the member `value`.
&emsp;When using the STL, this requires C++17 or above. Otherwise it requires compiler support. When neither is available, this trait is not defined.
```cpp
template <typename T>
inline constexpr bool has_unique_object_representations_v = etl::has_unique_object_representations<T>::value;
```
C++17
## is_null_pointer
From: `20.49.0`
```cpp
template <typename T>
struct is_null_pointer
```
Checks if `T` is `etl::nullptr_t`, optionally cv-qualified.
The result is found in the member `value`.
```cpp
template <typename T>
inline constexpr bool is_null_pointer_v = etl::is_null_pointer<T>::value;
```
C++17
## is_scalar
From: `20.49.0`
```cpp
template <typename T>
struct is_scalar
```
Checks if `T` is a scalar type; that is, an arithmetic, enumeration, pointer, pointer to member or `etl::nullptr_t` type, optionally cv-qualified.
The result is found in the member `value`.
```cpp
template <typename T>
inline constexpr bool is_scalar_v = etl::is_scalar<T>::value;
```
C++17

View File

@ -57,10 +57,58 @@ SOFTWARE.
#define ETL_USING_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE 1
#endif
#if !defined(ETL_USING_BUILTIN_IS_DESTRUCTIBLE)
#define ETL_USING_BUILTIN_IS_DESTRUCTIBLE 1
#endif
#if !defined(ETL_USING_BUILTIN_IS_NOTHROW_DESTRUCTIBLE)
#define ETL_USING_BUILTIN_IS_NOTHROW_DESTRUCTIBLE 1
#endif
#if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_COPYABLE)
#define ETL_USING_BUILTIN_IS_TRIVIALLY_COPYABLE 1
#endif
#if !defined(ETL_USING_BUILTIN_IS_STANDARD_LAYOUT)
#define ETL_USING_BUILTIN_IS_STANDARD_LAYOUT 1
#endif
#if !defined(ETL_USING_BUILTIN_IS_TRIVIAL)
#define ETL_USING_BUILTIN_IS_TRIVIAL 1
#endif
#if !defined(ETL_USING_BUILTIN_IS_UNION)
#define ETL_USING_BUILTIN_IS_UNION 1
#endif
#if !defined(ETL_USING_BUILTIN_IS_EMPTY)
#define ETL_USING_BUILTIN_IS_EMPTY 1
#endif
#if !defined(ETL_USING_BUILTIN_IS_POLYMORPHIC)
#define ETL_USING_BUILTIN_IS_POLYMORPHIC 1
#endif
#if !defined(ETL_USING_BUILTIN_IS_ABSTRACT)
#define ETL_USING_BUILTIN_IS_ABSTRACT 1
#endif
#if !defined(ETL_USING_BUILTIN_IS_FINAL)
#define ETL_USING_BUILTIN_IS_FINAL 1
#endif
#if !defined(ETL_USING_BUILTIN_IS_AGGREGATE)
#define ETL_USING_BUILTIN_IS_AGGREGATE 1
#endif
#if !defined(ETL_USING_BUILTIN_HAS_VIRTUAL_DESTRUCTOR)
#define ETL_USING_BUILTIN_HAS_VIRTUAL_DESTRUCTOR 1
#endif
#if !defined(ETL_USING_BUILTIN_HAS_UNIQUE_OBJECT_REPRESENTATIONS)
#define ETL_USING_BUILTIN_HAS_UNIQUE_OBJECT_REPRESENTATIONS 1
#endif
#if !defined(ETL_USING_BUILTIN_UNDERLYING_TYPE)
#define ETL_USING_BUILTIN_UNDERLYING_TYPE 1
#endif
@ -124,10 +172,58 @@ SOFTWARE.
#define ETL_USING_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE (__has_builtin(__has_trivial_destructor) || __has_builtin(__is_trivially_destructible))
#endif
#if !defined(ETL_USING_BUILTIN_IS_DESTRUCTIBLE)
#define ETL_USING_BUILTIN_IS_DESTRUCTIBLE __has_builtin(__is_destructible)
#endif
#if !defined(ETL_USING_BUILTIN_IS_NOTHROW_DESTRUCTIBLE)
#define ETL_USING_BUILTIN_IS_NOTHROW_DESTRUCTIBLE __has_builtin(__is_nothrow_destructible)
#endif
#if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_COPYABLE)
#define ETL_USING_BUILTIN_IS_TRIVIALLY_COPYABLE (__has_builtin(__has_trivial_copy) || __has_builtin(__is_trivially_copyable))
#endif
#if !defined(ETL_USING_BUILTIN_IS_STANDARD_LAYOUT)
#define ETL_USING_BUILTIN_IS_STANDARD_LAYOUT __has_builtin(__is_standard_layout)
#endif
#if !defined(ETL_USING_BUILTIN_IS_TRIVIAL)
#define ETL_USING_BUILTIN_IS_TRIVIAL __has_builtin(__is_trivial)
#endif
#if !defined(ETL_USING_BUILTIN_IS_UNION)
#define ETL_USING_BUILTIN_IS_UNION __has_builtin(__is_union)
#endif
#if !defined(ETL_USING_BUILTIN_IS_EMPTY)
#define ETL_USING_BUILTIN_IS_EMPTY __has_builtin(__is_empty)
#endif
#if !defined(ETL_USING_BUILTIN_IS_POLYMORPHIC)
#define ETL_USING_BUILTIN_IS_POLYMORPHIC __has_builtin(__is_polymorphic)
#endif
#if !defined(ETL_USING_BUILTIN_IS_ABSTRACT)
#define ETL_USING_BUILTIN_IS_ABSTRACT __has_builtin(__is_abstract)
#endif
#if !defined(ETL_USING_BUILTIN_IS_FINAL)
#define ETL_USING_BUILTIN_IS_FINAL __has_builtin(__is_final)
#endif
#if !defined(ETL_USING_BUILTIN_IS_AGGREGATE)
#define ETL_USING_BUILTIN_IS_AGGREGATE __has_builtin(__is_aggregate)
#endif
#if !defined(ETL_USING_BUILTIN_HAS_VIRTUAL_DESTRUCTOR)
#define ETL_USING_BUILTIN_HAS_VIRTUAL_DESTRUCTOR __has_builtin(__has_virtual_destructor)
#endif
#if !defined(ETL_USING_BUILTIN_HAS_UNIQUE_OBJECT_REPRESENTATIONS)
#define ETL_USING_BUILTIN_HAS_UNIQUE_OBJECT_REPRESENTATIONS __has_builtin(__has_unique_object_representations)
#endif
#if !defined(ETL_USING_BUILTIN_UNDERLYING_TYPE)
#define ETL_USING_BUILTIN_UNDERLYING_TYPE __has_builtin(__underlying_type)
#endif
@ -183,6 +279,46 @@ SOFTWARE.
#define ETL_USING_BUILTIN_IS_TRIVIALLY_COPYABLE 1
#endif
#if !defined(ETL_USING_BUILTIN_IS_STANDARD_LAYOUT)
#define ETL_USING_BUILTIN_IS_STANDARD_LAYOUT 1
#endif
#if !defined(ETL_USING_BUILTIN_IS_TRIVIAL)
#define ETL_USING_BUILTIN_IS_TRIVIAL 1
#endif
#if !defined(ETL_USING_BUILTIN_IS_UNION)
#define ETL_USING_BUILTIN_IS_UNION 1
#endif
#if !defined(ETL_USING_BUILTIN_IS_EMPTY)
#define ETL_USING_BUILTIN_IS_EMPTY 1
#endif
#if !defined(ETL_USING_BUILTIN_IS_POLYMORPHIC)
#define ETL_USING_BUILTIN_IS_POLYMORPHIC 1
#endif
#if !defined(ETL_USING_BUILTIN_IS_ABSTRACT)
#define ETL_USING_BUILTIN_IS_ABSTRACT 1
#endif
#if !defined(ETL_USING_BUILTIN_IS_FINAL)
#define ETL_USING_BUILTIN_IS_FINAL 1
#endif
#if !defined(ETL_USING_BUILTIN_IS_AGGREGATE)
#define ETL_USING_BUILTIN_IS_AGGREGATE 1
#endif
#if !defined(ETL_USING_BUILTIN_HAS_VIRTUAL_DESTRUCTOR)
#define ETL_USING_BUILTIN_HAS_VIRTUAL_DESTRUCTOR 1
#endif
#if !defined(ETL_USING_BUILTIN_HAS_UNIQUE_OBJECT_REPRESENTATIONS)
#define ETL_USING_BUILTIN_HAS_UNIQUE_OBJECT_REPRESENTATIONS 1
#endif
// MSVC has supported __builtin_bit_cast since VS2019 16.6. __has_builtin is not
// used for Microsoft (see above) to avoid a VS2022 intellisense issue, so the
// intrinsic is enabled here directly for the no-STL configuration.
@ -216,10 +352,58 @@ SOFTWARE.
#define ETL_USING_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE 0
#endif
#if !defined(ETL_USING_BUILTIN_IS_DESTRUCTIBLE)
#define ETL_USING_BUILTIN_IS_DESTRUCTIBLE 0
#endif
#if !defined(ETL_USING_BUILTIN_IS_NOTHROW_DESTRUCTIBLE)
#define ETL_USING_BUILTIN_IS_NOTHROW_DESTRUCTIBLE 0
#endif
#if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_COPYABLE)
#define ETL_USING_BUILTIN_IS_TRIVIALLY_COPYABLE 0
#endif
#if !defined(ETL_USING_BUILTIN_IS_STANDARD_LAYOUT)
#define ETL_USING_BUILTIN_IS_STANDARD_LAYOUT 0
#endif
#if !defined(ETL_USING_BUILTIN_IS_TRIVIAL)
#define ETL_USING_BUILTIN_IS_TRIVIAL 0
#endif
#if !defined(ETL_USING_BUILTIN_IS_UNION)
#define ETL_USING_BUILTIN_IS_UNION 0
#endif
#if !defined(ETL_USING_BUILTIN_IS_EMPTY)
#define ETL_USING_BUILTIN_IS_EMPTY 0
#endif
#if !defined(ETL_USING_BUILTIN_IS_POLYMORPHIC)
#define ETL_USING_BUILTIN_IS_POLYMORPHIC 0
#endif
#if !defined(ETL_USING_BUILTIN_IS_ABSTRACT)
#define ETL_USING_BUILTIN_IS_ABSTRACT 0
#endif
#if !defined(ETL_USING_BUILTIN_IS_FINAL)
#define ETL_USING_BUILTIN_IS_FINAL 0
#endif
#if !defined(ETL_USING_BUILTIN_IS_AGGREGATE)
#define ETL_USING_BUILTIN_IS_AGGREGATE 0
#endif
#if !defined(ETL_USING_BUILTIN_HAS_VIRTUAL_DESTRUCTOR)
#define ETL_USING_BUILTIN_HAS_VIRTUAL_DESTRUCTOR 0
#endif
#if !defined(ETL_USING_BUILTIN_HAS_UNIQUE_OBJECT_REPRESENTATIONS)
#define ETL_USING_BUILTIN_HAS_UNIQUE_OBJECT_REPRESENTATIONS 0
#endif
#if !defined(ETL_USING_BUILTIN_UNDERLYING_TYPE)
#define ETL_USING_BUILTIN_UNDERLYING_TYPE 0
#endif

View File

@ -47,6 +47,12 @@ SOFTWARE.
#include <type_traits>
#endif
// Required for std::swap, which etl::is_swappable must consider in any
// configuration that does not define etl::swap.
#if ETL_USING_CPP11 && (ETL_USING_STL || defined(ETL_IN_UNIT_TEST))
#include <utility>
#endif
namespace etl
{
#if ETL_USING_CPP11
@ -741,6 +747,38 @@ namespace etl
inline constexpr bool is_array_v = is_array<T>::value;
#endif
//***************************************************************************
/// is_bounded_array
template <typename T>
struct is_bounded_array : false_type
{
};
template <typename T, size_t Size>
struct is_bounded_array<T[Size]> : true_type
{
};
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_bounded_array_v = is_bounded_array<T>::value;
#endif
//***************************************************************************
/// is_unbounded_array
template <typename T>
struct is_unbounded_array : false_type
{
};
template <typename T>
struct is_unbounded_array<T[]> : true_type
{
};
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_unbounded_array_v = is_unbounded_array<T>::value;
#endif
//***************************************************************************
/// is_pointer
template <typename T>
@ -846,6 +884,38 @@ namespace etl
inline constexpr bool is_pod_v = etl::is_pod<T>::value;
#endif
//***************************************************************************
/// is_standard_layout
/// Requires compiler support. Without it there is no portable way to
/// determine whether a type is standard layout, so the trait is not defined.
#if ETL_USING_BUILTIN_IS_STANDARD_LAYOUT
template <typename T>
struct is_standard_layout : etl::bool_constant<__is_standard_layout(T)>
{
};
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_standard_layout_v = etl::is_standard_layout<T>::value;
#endif
#endif
//***************************************************************************
/// is_trivial
/// Requires compiler support. Without it there is no portable way to
/// determine whether a type is trivial, so the trait is not defined.
#if ETL_USING_BUILTIN_IS_TRIVIAL
template <typename T>
struct is_trivial : etl::bool_constant<__is_trivial(T)>
{
};
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_trivial_v = etl::is_trivial<T>::value;
#endif
#endif
//***************************************************************************
/// conditional
template <bool BValue, typename T, typename F>
@ -1144,6 +1214,137 @@ namespace etl
inline constexpr bool is_class_v = is_class<T>::value;
#endif
//***************************************************************************
/// is_union
/// Requires compiler support. Without it there is no portable way to
/// distinguish a union from a class, so the trait is not defined.
#if ETL_USING_BUILTIN_IS_UNION
template <typename T>
struct is_union : etl::bool_constant<__is_union(T)>
{
};
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_union_v = is_union<T>::value;
#endif
#endif
//***************************************************************************
/// is_empty
/// Requires compiler support. Without it there is no portable way to
/// determine whether a class type is empty, so the trait is not defined.
#if ETL_USING_BUILTIN_IS_EMPTY
template <typename T>
struct is_empty : etl::bool_constant<__is_empty(T)>
{
};
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_empty_v = is_empty<T>::value;
#endif
#endif
//***************************************************************************
/// is_polymorphic
/// Requires compiler support. Without it there is no portable way to
/// determine whether a class type is polymorphic, so the trait is not defined.
#if ETL_USING_BUILTIN_IS_POLYMORPHIC
template <typename T>
struct is_polymorphic : etl::bool_constant<__is_polymorphic(T)>
{
};
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_polymorphic_v = is_polymorphic<T>::value;
#endif
#endif
//***************************************************************************
/// is_abstract
/// Requires compiler support. Without it there is no portable way to
/// determine whether a class type is abstract, so the trait is not defined.
#if ETL_USING_BUILTIN_IS_ABSTRACT
template <typename T>
struct is_abstract : etl::bool_constant<__is_abstract(T)>
{
};
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_abstract_v = is_abstract<T>::value;
#endif
#endif
//***************************************************************************
/// is_final
/// Requires compiler support. Without it there is no portable way to
/// determine whether a class type is final, so the trait is not defined.
#if ETL_USING_BUILTIN_IS_FINAL
template <typename T>
struct is_final : etl::bool_constant<__is_final(T)>
{
};
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_final_v = is_final<T>::value;
#endif
#endif
//***************************************************************************
/// is_aggregate
/// Requires compiler support. Without it there is no portable way to
/// determine whether a type is an aggregate, so the trait is not defined.
#if ETL_USING_BUILTIN_IS_AGGREGATE
template <typename T>
struct is_aggregate : etl::bool_constant<__is_aggregate(typename etl::remove_cv<T>::type)>
{
};
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_aggregate_v = is_aggregate<T>::value;
#endif
#endif
//***************************************************************************
/// has_virtual_destructor
/// Requires compiler support. Without it there is no portable way to
/// determine whether a class type has a virtual destructor, so the trait is
/// not defined.
#if ETL_USING_BUILTIN_HAS_VIRTUAL_DESTRUCTOR
template <typename T>
struct has_virtual_destructor : etl::bool_constant<__has_virtual_destructor(T)>
{
};
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool has_virtual_destructor_v = has_virtual_destructor<T>::value;
#endif
#endif
//***************************************************************************
/// has_unique_object_representations
/// Requires compiler support. Without it there is no portable way to
/// determine whether a type has a unique object representation, so the trait
/// is not defined.
#if ETL_USING_BUILTIN_HAS_UNIQUE_OBJECT_REPRESENTATIONS
template <typename T>
struct has_unique_object_representations
: etl::bool_constant<__has_unique_object_representations(typename etl::remove_cv<typename etl::remove_all_extents<T>::type>::type)>
{
};
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool has_unique_object_representations_v = has_unique_object_representations<T>::value;
#endif
#endif
//***************************************************************************
/// is_base_of
#if ETL_USING_CPP11
@ -1464,6 +1665,132 @@ namespace etl
template <typename TFrom, typename TTo >
inline constexpr bool is_nothrow_convertible_v = etl::is_nothrow_convertible<TFrom, TTo>::value;
#endif
//***************************************************************************
/// is_destructible
/// Requires either compiler support or C++11. Without them there is no
/// portable way to determine whether a type is destructible, so the trait
/// is not defined.
#if ETL_USING_BUILTIN_IS_DESTRUCTIBLE
template <typename T>
struct is_destructible : etl::bool_constant<__is_destructible(T)>
{
};
#elif ETL_USING_CPP11
namespace private_type_traits
{
// Selected only if 'declval<T&>().~T()' is a valid expression.
// Void types, function types and types with an inaccessible or deleted
// destructor all fail substitution and select the fallback.
template <typename T>
struct is_destructible_impl
{
private:
template <typename U, typename = decltype(etl::declval<U&>().~U())>
static etl::true_type test(int);
template <typename>
static etl::false_type test(...);
public:
static ETL_CONSTANT bool value = decltype(test<T>(0))::value;
};
template <typename T>
struct is_destructible_helper : etl::bool_constant<is_destructible_impl<typename etl::remove_all_extents<T>::type>::value>
{
};
// Reference types are always destructible.
template <typename T>
struct is_destructible_helper<T&> : etl::true_type
{
};
template <typename T>
struct is_destructible_helper<T&&> : etl::true_type
{
};
// Arrays of unknown bound are incomplete types.
template <typename T>
struct is_destructible_helper<T[]> : etl::false_type
{
};
} // namespace private_type_traits
template <typename T>
struct is_destructible : etl::bool_constant<private_type_traits::is_destructible_helper<T>::value>
{
};
#endif
// C++17 implies C++11, so the trait is always defined when the alias is.
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_destructible_v = etl::is_destructible<T>::value;
#endif
//***************************************************************************
/// is_nothrow_destructible
/// Requires either compiler support or C++11. Without them there is no
/// portable way to determine whether a type is nothrow destructible, so the
/// trait is not defined.
#if ETL_USING_BUILTIN_IS_NOTHROW_DESTRUCTIBLE
template <typename T>
struct is_nothrow_destructible : etl::bool_constant<__is_nothrow_destructible(T)>
{
};
#elif ETL_USING_CPP11
namespace private_type_traits
{
// Only instantiated for destructible types, so 'declval<T&>().~T()' is a valid expression.
template <typename T, bool IsDestructible = etl::is_destructible<T>::value>
struct is_nothrow_destructible_impl : etl::false_type
{
};
template <typename T>
struct is_nothrow_destructible_impl<T, true> : etl::bool_constant<noexcept(etl::declval<T&>().~T())>
{
};
template <typename T>
struct is_nothrow_destructible_helper : etl::bool_constant<is_nothrow_destructible_impl<typename etl::remove_all_extents<T>::type>::value>
{
};
// Reference types are always nothrow destructible.
template <typename T>
struct is_nothrow_destructible_helper<T&> : etl::true_type
{
};
template <typename T>
struct is_nothrow_destructible_helper<T&&> : etl::true_type
{
};
// Arrays of unknown bound are incomplete types.
template <typename T>
struct is_nothrow_destructible_helper<T[]> : etl::false_type
{
};
} // namespace private_type_traits
template <typename T>
struct is_nothrow_destructible : etl::bool_constant<private_type_traits::is_nothrow_destructible_helper<T>::value>
{
};
#endif
// C++17 implies C++11, so the trait is always defined when the alias is.
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_nothrow_destructible_v = etl::is_nothrow_destructible<T>::value;
#endif
//***************************************************************************
@ -1849,6 +2176,56 @@ namespace etl
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_array_v = std::is_array_v<T>;
#endif
//***************************************************************************
/// is_bounded_array
///\ingroup type_traits
#if ETL_USING_CPP20 && defined(__cpp_lib_bounded_array_traits)
template <typename T>
struct is_bounded_array : std::is_bounded_array<T>
{
};
#else
template <typename T>
struct is_bounded_array : std::false_type
{
};
template <typename T, size_t Size>
struct is_bounded_array<T[Size]> : std::true_type
{
};
#endif
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_bounded_array_v = etl::is_bounded_array<T>::value;
#endif
//***************************************************************************
/// is_unbounded_array
///\ingroup type_traits
#if ETL_USING_CPP20 && defined(__cpp_lib_bounded_array_traits)
template <typename T>
struct is_unbounded_array : std::is_unbounded_array<T>
{
};
#else
template <typename T>
struct is_unbounded_array : std::false_type
{
};
template <typename T>
struct is_unbounded_array<T[]> : std::true_type
{
};
#endif
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_unbounded_array_v = etl::is_unbounded_array<T>::value;
#endif
//***************************************************************************
@ -1920,6 +2297,72 @@ namespace etl
inline constexpr bool is_pod_v = std::is_standard_layout_v<T> && std::is_trivially_default_constructible_v<T> && std::is_trivially_copyable_v<T>;
#endif
//***************************************************************************
/// is_standard_layout
///\ingroup type_traits
template <typename T>
struct is_standard_layout : std::is_standard_layout<T>
{
};
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_standard_layout_v = std::is_standard_layout_v<T>;
#endif
//***************************************************************************
/// is_trivial
///\ingroup type_traits
#if ETL_USING_CPP26
// std::is_trivial is deprecated in C++26 and later; avoid using it and
// compose the trait from is_trivially_copyable && is_trivially_default_constructible instead.
template <typename T>
struct is_trivial : etl::bool_constant<std::is_trivially_copyable<T>::value && std::is_trivially_default_constructible<T>::value>
{
};
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_trivial_v = std::is_trivially_copyable_v<T> && std::is_trivially_default_constructible_v<T>;
#endif
#else
template <typename T>
struct is_trivial : std::is_trivial<T>
{
};
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_trivial_v = std::is_trivial_v<T>;
#endif
#endif
//***************************************************************************
/// is_destructible
///\ingroup type_traits
template <typename T>
struct is_destructible : std::is_destructible<T>
{
};
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_destructible_v = std::is_destructible_v<T>;
#endif
//***************************************************************************
/// is_nothrow_destructible
///\ingroup type_traits
template <typename T>
struct is_nothrow_destructible : std::is_nothrow_destructible<T>
{
};
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_nothrow_destructible_v = std::is_nothrow_destructible_v<T>;
#endif
#if defined(ETL_COMPILER_GCC)
#if ETL_COMPILER_VERSION >= 5
#define ETL_GCC_V5_TYPE_TRAITS_SUPPORTED
@ -2100,6 +2543,127 @@ namespace etl
inline constexpr bool is_class_v = is_class<T>::value;
#endif
//***************************************************************************
/// is_union
template <typename T>
struct is_union : std::is_union<T>
{
};
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_union_v = std::is_union_v<T>;
#endif
//***************************************************************************
/// is_empty
template <typename T>
struct is_empty : std::is_empty<T>
{
};
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_empty_v = std::is_empty_v<T>;
#endif
//***************************************************************************
/// is_polymorphic
template <typename T>
struct is_polymorphic : std::is_polymorphic<T>
{
};
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_polymorphic_v = std::is_polymorphic_v<T>;
#endif
//***************************************************************************
/// is_abstract
template <typename T>
struct is_abstract : std::is_abstract<T>
{
};
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_abstract_v = std::is_abstract_v<T>;
#endif
//***************************************************************************
/// is_final
/// std::is_final is only available from C++14, so for C++11 the compiler
/// builtin is used, if available. Otherwise the trait is not defined.
#if ETL_USING_CPP14
template <typename T>
struct is_final : std::is_final<T>
{
};
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_final_v = std::is_final_v<T>;
#endif
#elif ETL_USING_BUILTIN_IS_FINAL
template <typename T>
struct is_final : etl::bool_constant<__is_final(T)>
{
};
#endif
//***************************************************************************
/// is_aggregate
/// std::is_aggregate is only available from C++17, so for C++11 and C++14 the
/// compiler builtin is used, if available. Otherwise the trait is not defined.
#if ETL_USING_CPP17
template <typename T>
struct is_aggregate : std::is_aggregate<T>
{
};
template <typename T>
inline constexpr bool is_aggregate_v = std::is_aggregate_v<T>;
#elif ETL_USING_BUILTIN_IS_AGGREGATE
template <typename T>
struct is_aggregate : etl::bool_constant<__is_aggregate(typename etl::remove_cv<T>::type)>
{
};
#endif
//***************************************************************************
/// has_virtual_destructor
template <typename T>
struct has_virtual_destructor : std::has_virtual_destructor<T>
{
};
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool has_virtual_destructor_v = std::has_virtual_destructor_v<T>;
#endif
//***************************************************************************
/// has_unique_object_representations
/// std::has_unique_object_representations is only available from C++17, so for
/// C++11 and C++14 the compiler builtin is used, if available. Otherwise the
/// trait is not defined.
#if ETL_USING_CPP17
template <typename T>
struct has_unique_object_representations : std::has_unique_object_representations<T>
{
};
template <typename T>
inline constexpr bool has_unique_object_representations_v = std::has_unique_object_representations_v<T>;
#elif ETL_USING_BUILTIN_HAS_UNIQUE_OBJECT_REPRESENTATIONS
template <typename T>
struct has_unique_object_representations
: etl::bool_constant<__has_unique_object_representations(typename etl::remove_cv<typename etl::remove_all_extents<T>::type>::type)>
{
};
#endif
//***************************************************************************
/// add_lvalue_reference
template <typename T>
@ -2253,6 +2817,19 @@ namespace etl
#endif // Condition = ETL_USING_STL && ETL_USING_CPP11
//***************************************************************************
/// is_null_pointer
///\ingroup type_traits
template <typename T>
struct is_null_pointer : etl::is_same<typename etl::remove_cv<T>::type, etl::nullptr_t>
{
};
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_null_pointer_v = is_null_pointer<T>::value;
#endif
//***************************************************************************
// ETL extended type traits.
//***************************************************************************
@ -3996,6 +4573,23 @@ namespace etl
inline constexpr bool is_member_pointer_v = etl::is_member_pointer<T>::value;
#endif
//***************************************************************************
/// is_scalar
/// An arithmetic, enumeration, pointer, pointer to member or
/// etl::nullptr_t type, optionally cv-qualified.
//***************************************************************************
template <typename T>
struct is_scalar
: etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_enum<T>::value || etl::is_pointer<T>::value || etl::is_member_pointer<T>::value
|| etl::is_null_pointer<T>::value>
{
};
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_scalar_v = etl::is_scalar<T>::value;
#endif
#if ETL_USING_CPP11
//*********************************
/// Check if T is a function type
@ -4130,6 +4724,235 @@ namespace etl
inline constexpr bool is_object_pointer_v = etl::is_object_pointer<T>::value;
#endif
//***************************************************************************
/// swap
/// Declared here, and defined in utility.h, so that etl::is_swappable below
/// finds it by ordinary unqualified lookup.
/// We can't have std::swap and etl::swap templates coexisting in the unit
/// tests as the compiler will be unable to decide which one to use, due to
/// ADL.
//***************************************************************************
#if ETL_NOT_USING_STL && !defined(ETL_IN_UNIT_TEST)
#if ETL_USING_CPP11
namespace private_type_traits
{
template <typename T>
struct is_swappable_helper;
template <typename T>
struct is_nothrow_swappable_helper;
} // namespace private_type_traits
// Constrained, as the standard requires, so that an attempt to swap a type
// that cannot be moved is a substitution failure rather than a hard error.
// This is what allows etl::is_swappable to be implemented.
// The exception specification is conditional, as the standard requires, so
// that etl::is_nothrow_swappable can be implemented.
template <typename T>
ETL_CONSTEXPR14 typename etl::enable_if<etl::is_move_constructible<T>::value && etl::is_move_assignable<T>::value>::type swap(T& a, T& b)
ETL_NOEXCEPT_IF(etl::is_nothrow_move_constructible<T>::value&& etl::is_nothrow_move_assignable<T>::value);
template <typename T, size_t Size>
ETL_CONSTEXPR14 typename etl::enable_if<private_type_traits::is_swappable_helper<T>::value>::type swap(T (&a)[Size], T (&b)[Size])
ETL_NOEXCEPT_IF(private_type_traits::is_nothrow_swappable_helper<T>::value);
#else
template <typename T>
ETL_CONSTEXPR14 void swap(T& a, T& b) ETL_NOEXCEPT;
template <typename T, size_t Size>
ETL_CONSTEXPR14 void swap(T (&a)[Size], T (&b)[Size]) ETL_NOEXCEPT;
#endif
#endif
//***************************************************************************
/// is_swappable
/// Determines whether lvalues of type T can be swapped by an unqualified
/// call to swap.
/// Requires C++11. Without it there is no way of detecting the validity of
/// an expression, so the trait is not defined.
//***************************************************************************
#if ETL_USING_STL && ETL_USING_CPP17
template <typename T>
struct is_swappable : std::is_swappable<T>
{
};
//***************************************************************************
/// is_swappable_with
//***************************************************************************
template <typename T, typename U>
struct is_swappable_with : std::is_swappable_with<T, U>
{
};
#elif ETL_USING_CPP11
namespace private_type_traits
{
namespace swap_detect
{
// Bring std::swap into scope, if it is available, so that the unqualified
// call below finds it in those configurations that do not define etl::swap.
// Otherwise etl::swap is found by ordinary lookup in the enclosing
// namespace. Either way, a swap found by argument dependent lookup takes
// part in overload resolution.
#if ETL_USING_STL || defined(ETL_IN_UNIT_TEST)
using std::swap;
#endif
// Selected only if 'swap(declval<T&>(), declval<T&>())' is a valid expression.
template <typename T>
struct is_swappable_test
{
private:
template <typename U, typename = decltype(swap(etl::declval<U&>(), etl::declval<U&>()))>
static etl::true_type test(int);
template <typename>
static etl::false_type test(...);
public:
static ETL_CONSTANT bool value = decltype(test<T>(0))::value;
};
// Selected only if both 'swap(declval<T>(), declval<U>())' and
// 'swap(declval<U>(), declval<T>())' are valid expressions.
template <typename T, typename U>
struct is_swappable_with_test
{
private:
template <typename T1, typename U1, typename = decltype(swap(etl::declval<T1>(), etl::declval<U1>())),
typename = decltype(swap(etl::declval<U1>(), etl::declval<T1>()))>
static etl::true_type test(int);
template <typename, typename>
static etl::false_type test(...);
public:
static ETL_CONSTANT bool value = decltype(test<T, U>(0))::value;
};
} // namespace swap_detect
template <typename T>
struct is_swappable_helper : etl::bool_constant<swap_detect::is_swappable_test<T>::value>
{
};
template <typename T, typename U>
struct is_swappable_with_helper : etl::bool_constant<swap_detect::is_swappable_with_test<T, U>::value>
{
};
} // namespace private_type_traits
template <typename T>
struct is_swappable : etl::bool_constant<private_type_traits::is_swappable_helper<T>::value>
{
};
//***************************************************************************
/// is_swappable_with
//***************************************************************************
template <typename T, typename U>
struct is_swappable_with : etl::bool_constant<private_type_traits::is_swappable_with_helper<T, U>::value>
{
};
#endif
//***************************************************************************
/// is_nothrow_swappable
/// Determines whether lvalues of type T can be swapped by an unqualified
/// call to swap, and that the swap cannot throw.
/// Requires C++11. Without it there is no way of detecting the validity of
/// an expression, so the trait is not defined.
//***************************************************************************
#if ETL_USING_STL && ETL_USING_CPP17
template <typename T>
struct is_nothrow_swappable : std::is_nothrow_swappable<T>
{
};
//***************************************************************************
/// is_nothrow_swappable_with
//***************************************************************************
template <typename T, typename U>
struct is_nothrow_swappable_with : std::is_nothrow_swappable_with<T, U>
{
};
#elif ETL_USING_CPP11
namespace private_type_traits
{
namespace swap_detect
{
// Only 'true' if the type is swappable and the swap expression is noexcept.
template <typename T, bool Is_Swappable = is_swappable_test<T>::value>
struct is_nothrow_swappable_test
{
static ETL_CONSTANT bool value = false;
};
template <typename T>
struct is_nothrow_swappable_test<T, true>
{
static ETL_CONSTANT bool value = noexcept(swap(etl::declval<T&>(), etl::declval<T&>()));
};
// Only 'true' if the types are swappable with each other and both of the
// swap expressions are noexcept.
template <typename T, typename U, bool Is_Swappable_With = is_swappable_with_test<T, U>::value>
struct is_nothrow_swappable_with_test
{
static ETL_CONSTANT bool value = false;
};
template <typename T, typename U>
struct is_nothrow_swappable_with_test<T, U, true>
{
static ETL_CONSTANT bool value = noexcept(swap(etl::declval<T>(), etl::declval<U>())) && noexcept(swap(etl::declval<U>(), etl::declval<T>()));
};
} // namespace swap_detect
template <typename T>
struct is_nothrow_swappable_helper : etl::bool_constant<swap_detect::is_nothrow_swappable_test<T>::value>
{
};
template <typename T, typename U>
struct is_nothrow_swappable_with_helper : etl::bool_constant<swap_detect::is_nothrow_swappable_with_test<T, U>::value>
{
};
} // namespace private_type_traits
template <typename T>
struct is_nothrow_swappable : etl::bool_constant<private_type_traits::is_nothrow_swappable_helper<T>::value>
{
};
//***************************************************************************
/// is_nothrow_swappable_with
//***************************************************************************
template <typename T, typename U>
struct is_nothrow_swappable_with : etl::bool_constant<private_type_traits::is_nothrow_swappable_with_helper<T, U>::value>
{
};
#endif
// C++17 implies C++11, so the trait is always defined when the alias is.
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_swappable_v = etl::is_swappable<T>::value;
template <typename T, typename U>
inline constexpr bool is_swappable_with_v = etl::is_swappable_with<T, U>::value;
template <typename T>
inline constexpr bool is_nothrow_swappable_v = etl::is_nothrow_swappable<T>::value;
template <typename T, typename U>
inline constexpr bool is_nothrow_swappable_with_v = etl::is_nothrow_swappable_with<T, U>::value;
#endif
#if ETL_USING_CPP11
//*********************************
/// Check for the presence of operator()

View File

@ -340,7 +340,31 @@ namespace etl
// We can't have std::swap and etl::swap templates coexisting in the unit
// tests as the compiler will be unable to decide which one to use, due to
// ADL.
// These are declared in type_traits.h, so that etl::is_swappable can find
// them, and defined here.
#if ETL_NOT_USING_STL && !defined(ETL_IN_UNIT_TEST)
#if ETL_USING_CPP11
//***************************************************************************
// swap
template <typename T>
ETL_CONSTEXPR14 typename etl::enable_if<etl::is_move_constructible<T>::value && etl::is_move_assignable<T>::value>::type swap(T& a, T& b)
ETL_NOEXCEPT_IF(etl::is_nothrow_move_constructible<T>::value&& etl::is_nothrow_move_assignable<T>::value)
{
T temp(ETL_MOVE(a));
a = ETL_MOVE(b);
b = ETL_MOVE(temp);
}
template <typename T, size_t Size>
ETL_CONSTEXPR14 typename etl::enable_if<private_type_traits::is_swappable_helper<T>::value>::type swap(T (&a)[Size], T (&b)[Size])
ETL_NOEXCEPT_IF(private_type_traits::is_nothrow_swappable_helper<T>::value)
{
for (size_t i = 0UL; i < Size; ++i)
{
swap(a[i], b[i]);
}
}
#else
//***************************************************************************
// swap
template <typename T>
@ -351,7 +375,7 @@ namespace etl
b = ETL_MOVE(temp);
}
template < class T, size_t Size >
template <typename T, size_t Size>
ETL_CONSTEXPR14 void swap(T (&a)[Size], T (&b)[Size]) ETL_NOEXCEPT
{
for (size_t i = 0UL; i < Size; ++i)
@ -359,6 +383,7 @@ namespace etl
swap(a[i], b[i]);
}
}
#endif
#endif
//***************************************************************************

File diff suppressed because it is too large Load Diff