- fennec::variant & fennec::generic, TODO: Test

This commit is contained in:
2025-12-13 19:00:43 -05:00
parent 9553f9b662
commit a1bdc077b1
23 changed files with 974 additions and 56 deletions

View File

@@ -19,13 +19,19 @@
#ifndef FENNEC_LANG_DETAIL_TYPE_SEQUENCES_H
#define FENNEC_LANG_DETAIL_TYPE_SEQUENCES_H
#include <fennec/math/common.h>
#include <fennec/lang/type_transforms.h>
namespace fennec::detail
{
template<typename...TypesT> struct _type_sequence {};
template<typename FirstT, typename... RestT> struct _first_element : type_identity<FirstT> {};
// fennec::nth_element =================================================================================================
template<size_t n, size_t i, typename...TypesT> struct _nth_element;
template<size_t n, size_t i> struct _nth_element<n, i> : type_identity<void> {};
@@ -35,6 +41,56 @@ namespace fennec::detail
n == i, HeadT,
typename _nth_element<n, i + 1, RestT...>::type
> {};
// fennec::max_element_size ============================================================================================
template<size_t, typename...> struct _max_element_size;
template<size_t M, typename HeadT>
struct _max_element_size<M, HeadT>
: integral_constant<size_t, fennec::max(M, sizeof(HeadT))> {
};
template<size_t M, typename HeadT, typename...RestT>
struct _max_element_size<M, HeadT, RestT...>
: _max_element_size<fennec::max(M, sizeof(HeadT)), RestT...> {
};
// fennec::find_element ================================================================================================
template<size_t N, typename, typename...> struct _find_element;
template<size_t N, typename FindT, typename HeadT>
struct _find_element<N, FindT, HeadT> : integral_constant<size_t, is_same_v<FindT, HeadT> ? N : N + 1> {};
template<size_t N, typename FindT, typename HeadT, typename...RestT> requires(is_same_v<FindT, HeadT>)
struct _find_element<N, FindT, HeadT, RestT...>
: conditional_t<is_same_v<FindT, HeadT>, integral_constant<size_t, N>, _find_element<N + 1, FindT, RestT...>> {};
// fennec::search_element ==============================================================================================
template<template<typename> typename, typename...> struct _search_element;
template<template<typename> typename SearchT> struct _search_element<SearchT> : type_identity<void> {};
template<template<typename> typename SearchT, typename HeadT, typename...RestT> requires(SearchT<HeadT>{})
struct _search_element<SearchT, HeadT, RestT...>
: conditional_t<SearchT<HeadT>{}, type_identity<HeadT>, _search_element<SearchT, RestT...>> {
};
template<template<typename, typename...> typename, typename, typename...> struct _search_element_args;
template<template<typename, typename...> typename SearchT, typename...ArgsT>
struct _search_element_args<SearchT, _type_sequence<ArgsT...>> : type_identity<void> {};
template<template<typename, typename...> typename SearchT, typename HeadT, typename...RestT, typename...ArgsT>
struct _search_element_args<SearchT, _type_sequence<ArgsT...>, HeadT, RestT...>
: conditional_t<SearchT<HeadT, ArgsT...>{}, type_identity<HeadT>, _search_element_args<SearchT, _type_sequence<ArgsT...>, RestT...>> {};
}
#endif // FENNEC_LANG_DETAIL_TYPE_SEQUENCES_H

View File

@@ -63,9 +63,19 @@ namespace fennec::detail
template<> struct _is_floating_point<float_t> : true_type {};
template<> struct _is_floating_point<double_t> : true_type {};
template<typename> struct _is_pointer : false_type {};
template<typename> struct _is_pointer : false_type {};
template<typename T> struct _is_pointer<T*> : true_type {};
template<typename> struct _is_reference : false_type {};
template<typename T> struct _is_reference<T&> : true_type {};
template<typename T> struct _is_reference<T&&> : true_type {};
template<typename> struct _is_lvalue_reference : false_type {};
template<typename T> struct _is_lvalue_reference<T&> : true_type {};
template<typename> struct _is_rvalue_reference : false_type {};
template<typename T> struct _is_rvalue_reference<T&&> : true_type {};
template<typename T> struct _is_complete {
template<typename U>
static auto test(U*) -> bool_constant<sizeof(U) == sizeof(U)>;

View File

@@ -213,6 +213,14 @@
# define FENNEC_HAS_BUILTIN_IS_ENUM 0
#endif
// Inconsistent without intrinsics.
#if __has_builtin(__is_union)
# define FENNEC_HAS_BUILTIN_IS_UNION 1
# define FENNEC_BUILTIN_IS_UNION(arg) __is_union(arg)
#else
# define FENNEC_HAS_BUILTIN_IS_UNION 0
#endif
// Inconsistent without intrinsics
#if __has_builtin(__is_final)
# define FENNEC_HAS_BUILTIN_IS_FINAL 1
@@ -221,12 +229,20 @@
# define FENNEC_HAS_BUILTIN_IS_FINAL 0
#endif
// Inconsistent with dynamic intrinsics, requires a massive table for static intrinsics
#if __has_builtin(__is_fundamental)
# define FENNEC_HAS_BUILTIN_IS_FUNDAMENTAL 1
# define FENNEC_BUILTIN_IS_FUNDAMENTAL(arg) __is_fundamental(arg)
// Inconsistent without intrinsics
#if __has_builtin(__is_function)
# define FENNEC_HAS_BUILTIN_IS_FUNCTION 1
# define FENNEC_BUILTIN_IS_FUNCTION(arg) __is_function(arg)
#else
# define FENNEC_HAS_BUILTIN_IS_FUNDAMENTAL 0
# define FENNEC_HAS_BUILTIN_IS_FUNCTION 0
#endif
// Inconsistent without intrinsics
#if __has_builtin(__is_object)
# define FENNEC_HAS_BUILTIN_IS_OBJECT 1
# define FENNEC_BUILTIN_IS_OBJECT(arg) __is_object(arg)
#else
# define FENNEC_HAS_BUILTIN_IS_FUNCTION 0
#endif
// Inconsistent without intrinsics

View File

@@ -43,6 +43,7 @@
/// - \subpage fennec_lang_conditional_types
/// - \subpage fennec_lang_numeric_transforms
/// - \subpage fennec_lang_metasequences
/// - \subpage fennec_lang_type_identity
/// - \subpage fennec_lang_type_sequences
/// - \subpage fennec_lang_type_traits
/// - \subpage fennec_lang_type_transforms

View File

@@ -51,6 +51,12 @@
/// \ref fennec::replace_first_element "typename replace_first_element<ClassT, SubT, OriginT, RestT...>::type"<br>
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::replace_first_element
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::is_unique "is_unique<TypesT...>::value"<br>
/// \ref fennec::is_unique_v "is_unique_v<TypesT...>"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::is_unique
/// </table>
///
@@ -59,6 +65,12 @@
namespace fennec
{
template<typename...TypesT> struct type_sequence {};
// fennec::first_element ===============================================================================================
///
/// \brief Get the first element of a template parameter pack
/// \tparam TypesT the Parameter Pack
@@ -69,8 +81,20 @@ template<typename...TypesT> struct first_element : detail::_first_element<TypesT
template<typename...TypesT> using first_element_t = typename first_element<TypesT...>::type;
// fennec::nth_element =================================================================================================
///
/// \brief Gets the type of the nth element of the type sequence `TypesT...`
/// \tparam n The index in the type sequence
/// \tparam TypesT The type sequence
template<size_t n, typename...TypesT> struct nth_element : detail::_nth_element<n, 0, TypesT...> {};
template<size_t n, typename...TypesT> using nth_element_t = nth_element<n, TypesT...>::type;
// fennec::replace_first_element =======================================================================================
///
/// \brief Take a Template with a Pack `ClassT<ArgsT...>` and replace the first `ArgT` of `ArgsT...` with `SubT`
@@ -84,6 +108,99 @@ template<
struct replace_first_element<ClassT<OriginT, RestT...>, SubT> // Specialization
{ using type = ClassT<SubT, RestT...>; }; // Definition
// fennec::max_element_size ============================================================================================
///
/// \brief Gets the max value of the size of each type in the sequence, i.e. `max(sizeof(Ts)...)`
/// \tparam Ts The type sequence to check
template<typename...Ts> struct max_element_size : detail::_max_element_size<0, Ts...> {};
///
/// \brief Shorthand for `max_element_size<Ts...>::value`
/// \tparam Ts The type sequence to check
template<typename...Ts> constexpr size_t max_element_size_v = max_element_size<Ts...>::value;
// fennec::find_element ================================================================================================
///
/// \brief Finds the index of `T` in `Ts`, if `T` is not found, results in `sizeof...(Ts)`
/// \tparam T The type to find
/// \tparam Ts The type sequence to check
template<typename T, typename...Ts> struct find_element : detail::_find_element<0, T, Ts...> {};
///
/// \brief Shorthand for `find_element<T, Ts...>::value`
/// \tparam T The type to find
/// \tparam Ts The type sequence to check
template<typename T, typename...Ts> constexpr size_t find_element_v = find_element<T, Ts...>::value;
// fennec::search_element ==============================================================================================
///
/// \brief Find the first element in `TypesT...` that satisfies `SearchT<T>`
/// \tparam SearchT A type that satisfies `template<typename>` and contains `static constexpr bool value;` to use for searching
/// \tparam TypesT The type sequence to search
template<template<typename> typename SearchT, typename...TypesT> struct search_element : detail::_search_element<SearchT, TypesT...> {};
///
/// \brief Shorthand for `search_element_t<T, Ts...>::type`
/// \tparam SearchT A type that satisfies `template<typename>` and contains `static constexpr bool value;` to use for searching
/// \tparam TypesT The type sequence to search
template<template<typename> typename SearchT, typename...TypesT> using search_element_t = search_element<SearchT, TypesT...>::type;
template<template<typename, typename...> typename, typename, typename...> struct search_element_args;
template<template<typename, typename...> typename SearchT, typename...TypesT, typename...ArgsT>
struct search_element_args<SearchT, type_sequence<ArgsT...>, TypesT...>
: detail::_search_element_args<SearchT, detail::_type_sequence<ArgsT...>, TypesT...> {
};
// fennec::contains_element ============================================================================================
///
/// \brief Checks if the type sequence `Ts...` contains `T`
/// \tparam T The type to find
/// \tparam Ts The type sequence to check
template<typename T, typename...Ts> struct contains_element : bool_constant<(is_same_v<T, Ts> or ...)> {};
///
/// \brief Shorthand for `contains_element_v<T, Ts...>::value`
/// \tparam T The type to find
/// \tparam Ts The type sequence to check
template<typename T, typename...Ts> constexpr bool contains_element_v = contains_element<T, Ts...>::value;
// fennec::is_unique ===================================================================================================
///
/// \brief Checks if all types in a type sequence are unique
/// \tparam Ts The type sequence to check
template<typename...Ts> struct is_unique : false_type {};
// Single type case
template<typename T> struct is_unique<T> : true_type {};
// Recursion case
template<typename T, typename...Ts> requires(not is_same_v<T, Ts> && ...)
struct is_unique<T, Ts...> : is_unique<Ts...> {};
///
/// \brief Shorthand for `is_unique<Ts...>::value`
/// \tparam Ts The type sequence to check
template<typename...Ts> constexpr bool is_unique_v = is_unique<Ts...>::value;
}

View File

@@ -360,7 +360,7 @@
/// \ref fennec::is_nothrow_move_constructible "is_nothrow_move_constructible<ClassT, ArgsT...>::value"<br>
/// \ref fennec::is_nothrow_move_constructible_v "is_nothrow_move_constructible_v<ClassT, ArgsT...>"
/// <td width="50%" style="vertical-align: top">
/// \movedetails fennec::is_move_constructible
/// \copydetails fennec::is_move_constructible
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::is_assignable "is_assignable<ClassT, ArgsT...>::value"<br>
@@ -390,7 +390,7 @@
/// \ref fennec::is_nothrow_move_assignable "is_nothrow_move_assignable<ClassT, ArgsT...>::value"<br>
/// \ref fennec::is_nothrow_move_assignable_v "is_nothrow_move_assignable_v<ClassT, ArgsT...>"
/// <td width="50%" style="vertical-align: top">
/// \movedetails fennec::is_move_assignable
/// \copydetails fennec::is_move_assignable
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::is_destructible "is_destructible<ClassT, ArgsT...>::value"<br>
@@ -446,7 +446,7 @@ constexpr inline bool is_constant_evaluated() noexcept {
// fennec::is_void =====================================================================================================
///
/// \brief check if \p T is of type void
/// \brief Check if \p T is of type void
///
/// \details Stores a boolean value in `is_void::value`, representing whether the provided type is of base type void.
/// \tparam T type to check
@@ -454,7 +454,7 @@ template<typename T> struct is_void
: detail::_is_void<remove_cvr_t<T>>{};
///
/// \brief shorthand for ```is_void<T>::value```
/// \brief Shorthand for ```is_void<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_void_v = is_void<T>::value;
@@ -463,7 +463,7 @@ template<typename T> constexpr bool_t is_void_v = is_void<T>::value;
// fennec::is_null_pointer =============================================================================================
///
/// \brief check if \p T is of type nullptr_t
/// \brief Check if \p T is of type nullptr_t
///
/// \details Stores a boolean value in `is_null_pointer::value`, representing whether the provided type is of base type nullptr_t.
/// \tparam T type to check
@@ -471,7 +471,7 @@ template<typename T> struct is_null_pointer
: detail::_is_null_pointer<remove_cvr_t<T>>{};
///
/// \brief shorthand for ```is_null_pointer<T>::value```
/// \brief Shorthand for ```is_null_pointer<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_null_pointer_v = is_null_pointer<T>::value;
@@ -482,7 +482,7 @@ template<typename T> constexpr bool_t is_null_pointer_v = is_null_pointer<T>::va
#ifdef FENNEC_BUILTIN_IS_ARRAY
///
/// \brief check if \p T is of an array type
/// \brief Check if \p T is of an array type
/// \tparam T type to check
template<typename T> struct is_array
: bool_constant<FENNEC_BUILTIN_IS_ARRAY(T)> {};
@@ -490,7 +490,7 @@ template<typename T> struct is_array
#else
///
/// \brief check if \p T is of an array type
/// \brief Check if \p T is of an array type
/// \tparam T type to check
template<typename T> struct is_array
: false_type {};
@@ -506,25 +506,72 @@ template<typename T> struct is_array<T[]>
#endif
///
/// \brief shorthand for ```is_array<T>::value```
/// \brief Shorthand for ```is_array<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_array_v = is_array<T>::value;
// fennec::is_enum ====================================================================================================
///
/// \brief Check if \p T is an enum
/// \tparam T type to check
template<typename T> struct is_enum
: bool_constant<FENNEC_BUILTIN_IS_ENUM(T)> {};
///
/// \brief Check if \p T is a class
/// \tparam T type to check
template<typename T> constexpr size_t is_enum_v = is_enum<T>::value;
// fennec::is_union ====================================================================================================
///
/// \brief Check if \p T is a union
/// \tparam T type to check
template<typename T> struct is_union
: bool_constant<FENNEC_BUILTIN_IS_UNION(T)> {};
///
/// \brief Check if \p T is a class
/// \tparam T type to check
template<typename T> constexpr size_t is_union_v = is_union<T>::value;
// fennec::is_class ====================================================================================================
///
/// \brief check if \p T is a class
/// \brief Check if \p T is a class
/// \tparam T type to check
template<typename T> struct is_class
: bool_constant<FENNEC_BUILTIN_IS_CLASS(T)> {};
///
/// \brief check if \p T is a class
/// \brief Check if \p T is a class
/// \tparam T type to check
template<typename T> constexpr size_t is_class_v = is_class<T>::value;
// fennec::is_function ====================================================================================================
///
/// \brief Check if \p T is a class
/// \tparam T type to check
template<typename T> struct is_function
: bool_constant<FENNEC_BUILTIN_IS_FUNCTION(T)> {};
///
/// \brief Check if \p T is a class
/// \tparam T type to check
template<typename T> constexpr size_t is_function_v = is_function<T>::value;
// Integral Types ======================================================================================================
@@ -532,7 +579,7 @@ template<typename T> constexpr size_t is_class_v = is_class<T>::value;
// fennec::is_bool =====================================================================================================
///
/// \brief check if \p T is of type bool
/// \brief Check if \p T is of type bool
///
/// \details Stores a boolean value in `is_bool::value`, representing whether the provided type is of base type bool.
/// \tparam T type to check
@@ -540,12 +587,16 @@ template<typename T> struct is_bool
: detail::_is_bool<remove_cvr_t<T>>{};
///
/// \brief shorthand for ```is_bool<T>::value```
/// \brief Shorthand for ```is_bool<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_bool_v = is_bool<T>::value;
// fennec::is_integral =================================================================================================
///
/// \brief check if \p T is of an integral
/// \brief Check if \p T is of an integral
///
/// \details Stores a boolean value in `is_integral::value`, representing whether the provided type is of a base integer type.
/// \tparam T type to check
@@ -553,13 +604,17 @@ template<typename T> struct is_integral
: detail::_is_integral<remove_cvr_t<T>> {};
///
/// \brief shorthand for ```is_integral<T>::value```
/// \brief Shorthand for ```is_integral<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_integral_v = is_integral<T>::value;
// fennec::is_signed =================================================================================================
///
/// \brief check if \p T is of a signed integral
/// \brief Check if \p T is of a signed integral
///
/// \details Checks if type `T` is a signed type i.e. `T(-1) < T(0)` and stores it in `is_same::value`.
/// \tparam T type to check
@@ -567,13 +622,17 @@ template<typename T> struct is_signed
: detail::_is_signed<remove_cvr_t<T>> {};
///
/// \brief shorthand for ```is_signed<T>::value```
/// \brief Shorthand for ```is_signed<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_signed_v = is_signed<T>::value;
// fennec::is_unsigned =================================================================================================
///
/// \brief check if \p T is of an unsigned integral
/// \brief Check if \p T is of an unsigned integral
///
/// \details Checks if type `T` is an unsigned type i.e. `T(-1) > T(0)` and stores it in `is_same::value`.
/// \tparam T type to check
@@ -581,7 +640,7 @@ template<typename T> struct is_unsigned
: detail::_is_unsigned<remove_cvr_t<T>> {};
///
/// \brief shorthand for ```is_unsigned<T>::value```
/// \brief Shorthand for ```is_unsigned<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_unsigned_v = is_unsigned<T>::value;
@@ -590,15 +649,15 @@ template<typename T> constexpr bool_t is_unsigned_v = is_unsigned<T>::value;
// Floating Point Types ================================================================================================
///
/// \brief check if \p T is of a floating point type
/// \brief Check if \p T is of a floating point type
///
/// \details Checks if type `T` is a floating point type and store it in `is_same::value`.
/// \details Stores a boolean value in `is_floating_point::value`, representing whether the provided type is of a base floating point type.
/// \tparam T type to check
template<typename T> struct is_floating_point
: detail::_is_floating_point<remove_cvr_t<T>>{};
///
/// \brief shorthand for ```is_floating_point<T>::value```
/// \brief Shorthand for ```is_floating_point<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_floating_point_v = is_floating_point<T> {};
@@ -606,24 +665,69 @@ template<typename T> constexpr bool_t is_floating_point_v = is_floating_point<T>
// Pointer Types =======================================================================================================
///
/// \brief check if \p T is of a floating point type
/// \brief Check if \p T is of a pointer type
///
/// \details Checks if type `T` is a floating point type and store it in `is_same::value`.
/// \details Stores a boolean value in `is_pointer::value`, representing whether the provided type is of a base pointer type.
/// \tparam T type to check
template<typename T> struct is_pointer
: detail::_is_pointer<remove_cvr_t<T>>{};
///
/// \brief shorthand for ```is_floating_point<T>::value```
/// \brief Shorthand for ```is_pointer<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_pointer_v = is_pointer<T> {};
// Reference Types =======================================================================================================
///
/// \brief Check if \p T is of a floating point type
///
/// \details Checks if type `T` is a floating point type and store it in `is_same::value`.
/// \tparam T type to check
template<typename T> struct is_reference
: detail::_is_reference<T>{};
///
/// \brief Shorthand for ```is_floating_point<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_reference_v = is_reference<T> {};
///
/// \brief Check if \p T is of a floating point type
///
/// \details Checks if type `T` is a floating point type and store it in `is_same::value`.
/// \tparam T type to check
template<typename T> struct is_lvalue_reference
: detail::_is_lvalue_reference<T>{};
///
/// \brief Shorthand for ```is_floating_point<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_lvalue_reference_v = is_lvalue_reference<T> {};
///
/// \brief Check if \p T is of a floating point type
///
/// \details Checks if type `T` is a floating point type and store it in `is_same::value`.
/// \tparam T type to check
template<typename T> struct is_rvalue_reference
: detail::_is_rvalue_reference<T>{};
///
/// \brief Shorthand for ```is_floating_point<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_rvalue_reference_v = is_rvalue_reference<T> {};
// Arithmetic Types ====================================================================================================
///
/// \brief check if \p T is an arithmetic type
/// \brief Check if \p T is an arithmetic type
///
/// \details Checks if type `T` is a built-in type with arithmetic operators and store it in `is_same::value`.
/// \tparam T type to check
@@ -631,21 +735,38 @@ template<typename T> struct is_arithmetic
: bool_constant<is_integral_v<T> or is_floating_point_v<T>>{};
///
/// \brief shorthand for ```is_arithmetic<T>::value```
/// \brief Shorthand for ```is_arithmetic<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_arithmetic_v = is_arithmetic<T>::value;
// Arithmetic Types ====================================================================================================
///
/// \brief Check if \p T is an arithmetic type
///
/// \details Checks if type `T` is a built-in type with arithmetic operators and store it in `is_same::value`.
/// \tparam T type to check
template<typename T> struct is_scalar
: bool_constant<is_arithmetic_v<T> or is_enum_v<T> or is_pointer_v<T>>{};
///
/// \brief Shorthand for ```is_scalar<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_scalar_v = is_scalar<T>::value;
// fennec::is_fundamental ==============================================================================================
///
/// \brief check if \p T is a fundamental type, i.e. arithmetic, void, or nullptr_t
/// \brief Check if \p T is a fundamental type, i.e. arithmetic, void, or nullptr_t
/// \tparam T type to check
template<typename T> struct is_fundamental
: bool_constant<is_arithmetic_v<T> || is_void_v<T> || is_null_pointer_v<T>>{};
///
/// \brief shorthand for ```is_fundamental<T>::value```
/// \brief Shorthand for ```is_fundamental<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_fundamental_v = is_fundamental<T>::value;
@@ -653,7 +774,7 @@ template<typename T> constexpr bool_t is_fundamental_v = is_fundamental<T>::valu
// fennec::is_same =====================================================================================================
///
/// \brief check if the two types are identical
/// \brief Check if the two types are identical
///
/// \details Checks if `T0` and `T1` are identical and store it in `is_same::value`
/// \tparam T0 first type to check
@@ -664,7 +785,7 @@ template<typename T0, typename T1> struct is_same : false_type {};
template<typename T> struct is_same<T, T> : true_type {};
///
/// \brief shorthand for ```is_same<T0, T1>::value```
/// \brief Shorthand for ```is_same<T0, T1>::value```
/// \tparam T0 first type to check
/// \tparam T1 second type to check
template<typename T0, typename T1> constexpr bool_t is_same_v = is_same<T0, T1> {};
@@ -672,63 +793,63 @@ template<typename T0, typename T1> constexpr bool_t is_same_v = is_same<T0, T1>
// fennec::is_complete ==============================================================================================
///
/// \brief check if type `T` is complete
/// \brief Check if type `T` is complete
///
/// \details Checks if `T`
/// \tparam T type to check
template<typename T> struct is_complete : detail::_is_complete<T>::type {};
///
/// \brief shorthand for `is_complete<TypeT0, TypeT1>::value`
/// \brief Shorthand for `is_complete<TypeT0, TypeT1>::value`
/// \tparam T type to check
template<typename T> constexpr bool_t is_complete_v = is_complete<T>{};
// fennec::is_iterable ==============================================================================================
///
/// \brief check if type `T` is iterable
/// \brief Check if type `T` is iterable
///
/// \details Checks if `T`
/// \tparam T type to check
template<typename T> struct is_iterable : decltype(detail::_is_iterable<T>(0)) {};
///
/// \brief shorthand for `is_iterable<TypeT0, TypeT1>::value`
/// \brief Shorthand for `is_iterable<TypeT0, TypeT1>::value`
/// \tparam T type to check
template<typename T> constexpr bool_t is_iterable_v = is_iterable<T>{};
// fennec::is_indexable ==============================================================================================
///
/// \brief check if type `T` is indexable
/// \brief Check if type `T` is indexable
///
/// \details Checks if `T`
/// \tparam T type to check
template<typename T> struct is_indexable : decltype(detail::_is_indexable<T>(0)) {};
///
/// \brief shorthand for `is_indexable<TypeT0, TypeT1>::value`
/// \brief Shorthand for `is_indexable<TypeT0, TypeT1>::value`
/// \tparam T type to check
template<typename T> constexpr bool_t is_indexable_v = is_indexable<T>{};
// fennec::is_mappable ==============================================================================================
///
/// \brief check if type `T` is mappable
/// \brief Check if type `T` is mappable
///
/// \details Checks if `T`
/// \tparam T type to check
template<typename T> struct is_mappable : decltype(detail::_is_mappable<T>(0)) {};
///
/// \brief shorthand for `is_mappable<TypeT0, TypeT1>::value`
/// \brief Shorthand for `is_mappable<TypeT0, TypeT1>::value`
/// \tparam T type to check
template<typename T> constexpr bool_t is_mappable_v = is_mappable<T>{};
// fennec::is_convertible ==============================================================================================
///
/// \brief check if type `T0` can be converted `T1`
/// \brief Check if type `T0` can be converted `T1`
///
/// \details Checks if `TypeT0`
/// \tparam FromT First type
@@ -737,7 +858,7 @@ template<typename FromT, typename ToT> struct is_convertible
: bool_constant<FENNEC_BUILTIN_IS_CONVERTIBLE(FromT, ToT)> {};
///
/// \brief shorthand for `can_convert<TypeT0, TypeT1>::value`
/// \brief Shorthand for `can_convert<TypeT0, TypeT1>::value`
/// \param FromT First type
/// \param ToT Second type
template<typename FromT, typename ToT> constexpr bool_t is_convertible_v = is_convertible<FromT, ToT>{};
@@ -779,7 +900,7 @@ template<typename ClassT> struct is_default_constructible
///
/// \brief Shorthand for `is_default_constructible<ClassT>::value`
template<typename ClassT, typename...ArgsT> constexpr bool_t is_default_constructible_v = is_default_constructible<ClassT>{};
template<typename ClassT> constexpr bool_t is_default_constructible_v = is_default_constructible<ClassT>{};

View File

@@ -213,6 +213,8 @@ namespace fennec
using bool_t = bool; ///< \brief A conditional type
using byte_t = unsigned char; ///< \brief A type capable of holding a single byte
using char_t = char; ///< \brief A type capable of holding an ascii value
using schar_t = signed char; ///< \brief A type with the size of a char, capable of holding a signed 8-bit integer
using uchar_t = unsigned char; ///< \brief A type with the size of a char, capable of holding an unsigned 8-bit integer