mirror of
https://github.com/ETLCPP/etl.git
synced 2026-10-28 18:07:10 +08:00
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:
parent
25e2d6e8a3
commit
fa3ac28f55
@ -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`.
|
||||
 When using the STL, this is defined as `is_standard_layout<T> && is_trivially_default_constructible<T> && is_trivially_copyable<T>`.
|
||||
 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`.
|
||||
 When not using the STL, the trait is detected by checking whether `declval<T&>().~T()` is a valid expression.
|
||||
 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`.
|
||||
 When not using the STL, the trait is detected by checking `noexcept(declval<T&>().~T())` for destructible types.
|
||||
 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`.
|
||||
 When using the STL and C++17, this is defined as `std::is_swappable<T>`.
|
||||
 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.
|
||||
 Requires C++11. Without it there is no way of detecting the validity of an expression, so this trait is not defined.
|
||||
 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`.
|
||||
 When using the STL and C++17, this is defined as `std::is_swappable_with<T, U>`.
|
||||
 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.
|
||||
 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`.
|
||||
 Requires C++11. Without it there is no way of detecting the validity of an expression, so this trait is not defined.
|
||||
 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`.
|
||||
 When using the STL and C++17, this is defined as `std::is_nothrow_swappable<T>`.
|
||||
 Otherwise the trait checks that `etl::is_swappable<T>::value` is `true` and that `swap(declval<T&>(), declval<T&>())` is `noexcept`.
|
||||
 Requires C++11. Without it there is no way of detecting the validity of an expression, so this trait is not defined.
|
||||
 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`.
|
||||
 When using the STL and C++17, this is defined as `std::is_nothrow_swappable_with<T, U>`.
|
||||
 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`.
|
||||
 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`.
|
||||
 Requires C++11. Without it there is no way of detecting the validity of an expression, so this trait is not defined.
|
||||
 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`.
|
||||
 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`.
|
||||
 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`.
|
||||
 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`.
|
||||
 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`.
|
||||
 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`.
|
||||
 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`.
|
||||
 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`.
|
||||
 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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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)
|
||||
@ -360,6 +384,7 @@ namespace etl
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//***************************************************************************
|
||||
///\brief pair holds two objects of arbitrary type
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user