- Separated Platform and Compiler Dependent Behaviour into CMake scripts

- Implemented Basic Platform Interfaces
 - Implemented partial Linux platform and Wayland Display.
 - Implemented Dependencies for the above
   - map
     - set
       - optional
     - pair

TODO: threading
This commit is contained in:
2025-07-22 00:59:41 -04:00
parent ab1c7d94be
commit 73333b4c67
86 changed files with 3257 additions and 203 deletions

View File

@@ -46,7 +46,12 @@
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// assert(expr, desc)
/// <td width="50%" style="vertical-align: top">
/// Make an assertion with expression `expr` and provide a description `desc`.
/// Make an assertion with expression `expr` and provide a description `desc`. Only halts in debug mode.
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// assertf(expr, desc)
/// <td width="50%" style="vertical-align: top">
/// Make an assertion with expression `expr` and provide a description `desc`. Always halts.
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// assertd(expr, desc)
@@ -65,15 +70,20 @@
using assert_handler = void (*)(const char *, const char *, int , const char *);
void __assert_impl(const char* expression, const char* file, int line, const char* function, const char* desc);
void __assert_impl(const char* expression, const char* file, int line, const char* function, const char* desc, bool halt);
// flagged unlikely to optimize branch prediction
#define assert(expression, description) \
if(not(expression)) [[unlikely]] { \
__assert_impl(#expression, __FILE__, __LINE__, __PRETTY_FUNCTION__, description); \
__assert_impl(#expression, __FILE__, __LINE__, __PRETTY_FUNCTION__, description, not FENNEC_RELEASE); \
}
#ifdef NDEBUG
#define assertf(expression, description) \
if(not(expression)) [[unlikely]] { \
__assert_impl(#expression, __FILE__, __LINE__, __PRETTY_FUNCTION__, description, true); \
}
#if FENNEC_RELEASE
#define assertd(expression, description) (0)
#else
#define assertd(expression, description) assert(expression, description)

View File

@@ -32,6 +32,8 @@
#ifndef FENNEC_LANG_CONDITIONAL_TYPES_H
#define FENNEC_LANG_CONDITIONAL_TYPES_H
#include <fennec/lang/type_identity.h>
///
/// \page fennec_lang_conditional_types Conditional Types
///
@@ -64,8 +66,6 @@
///
///
#include <fennec/lang/type_transforms.h>
namespace fennec
{
@@ -92,12 +92,12 @@ using conditional_t
// specialization of fennec::conditional for `true` case
template<typename T, typename F>
struct conditional<true, T, F> : type_transform<T>{};
struct conditional<true, T, F> : type_identity<T>{};
// specialization of fennec::conditional for `false` case
template<typename T, typename F>
struct conditional<false, T, F> : type_transform<F>{};
struct conditional<false, T, F> : type_identity<F>{};
// fennec::detect ======================================================================================================

View File

@@ -28,34 +28,34 @@ namespace fennec
namespace detail
{
template<typename> struct __make_unsigned : type_transform<undefined_t> {};
template<typename> struct __make_unsigned : type_identity<undefined_t> {};
template<> struct __make_unsigned<char_t> : type_transform<uchar_t> {};
template<> struct __make_unsigned<uchar_t> : type_transform<uchar_t> {};
template<> struct __make_unsigned<schar_t> : type_transform<uchar_t> {};
template<> struct __make_unsigned<short_t> : type_transform<ushort_t> {};
template<> struct __make_unsigned<ushort_t> : type_transform<ushort_t> {};
template<> struct __make_unsigned<uint_t> : type_transform<uint_t> {};
template<> struct __make_unsigned<int_t> : type_transform<uint_t> {};
template<> struct __make_unsigned<long_t> : type_transform<ulong_t> {};
template<> struct __make_unsigned<ulong_t> : type_transform<ulong_t> {};
template<> struct __make_unsigned<llong_t> : type_transform<ullong_t> {};
template<> struct __make_unsigned<ullong_t> : type_transform<ullong_t> {};
template<> struct __make_unsigned<char_t> : type_identity<uchar_t> {};
template<> struct __make_unsigned<uchar_t> : type_identity<uchar_t> {};
template<> struct __make_unsigned<schar_t> : type_identity<uchar_t> {};
template<> struct __make_unsigned<short_t> : type_identity<ushort_t> {};
template<> struct __make_unsigned<ushort_t> : type_identity<ushort_t> {};
template<> struct __make_unsigned<uint_t> : type_identity<uint_t> {};
template<> struct __make_unsigned<int_t> : type_identity<uint_t> {};
template<> struct __make_unsigned<long_t> : type_identity<ulong_t> {};
template<> struct __make_unsigned<ulong_t> : type_identity<ulong_t> {};
template<> struct __make_unsigned<llong_t> : type_identity<ullong_t> {};
template<> struct __make_unsigned<ullong_t> : type_identity<ullong_t> {};
template<typename> struct __make_signed : type_transform<undefined_t> {};
template<typename> struct __make_signed : type_identity<undefined_t> {};
template<> struct __make_signed<char_t> : type_transform<schar_t> {};
template<> struct __make_signed<uchar_t> : type_transform<schar_t> {};
template<> struct __make_signed<schar_t> : type_transform<schar_t> {};
template<> struct __make_signed<short_t> : type_transform<short_t> {};
template<> struct __make_signed<ushort_t> : type_transform<short_t> {};
template<> struct __make_signed<uint_t> : type_transform<int_t> {};
template<> struct __make_signed<int_t> : type_transform<int_t> {};
template<> struct __make_signed<long_t> : type_transform<long_t> {};
template<> struct __make_signed<ulong_t> : type_transform<long_t> {};
template<> struct __make_signed<llong_t> : type_transform<llong_t> {};
template<> struct __make_signed<ullong_t> : type_transform<llong_t> {};
template<> struct __make_signed<char_t> : type_identity<schar_t> {};
template<> struct __make_signed<uchar_t> : type_identity<schar_t> {};
template<> struct __make_signed<schar_t> : type_identity<schar_t> {};
template<> struct __make_signed<short_t> : type_identity<short_t> {};
template<> struct __make_signed<ushort_t> : type_identity<short_t> {};
template<> struct __make_signed<uint_t> : type_identity<int_t> {};
template<> struct __make_signed<int_t> : type_identity<int_t> {};
template<> struct __make_signed<long_t> : type_identity<long_t> {};
template<> struct __make_signed<ulong_t> : type_identity<long_t> {};
template<> struct __make_signed<llong_t> : type_identity<llong_t> {};
template<> struct __make_signed<ullong_t> : type_identity<llong_t> {};
}

View File

@@ -27,7 +27,7 @@ namespace fennec
namespace detail
{
template<typename FirstT, typename... RestT> struct __first_element : type_transform<FirstT>{};
template<typename FirstT, typename... RestT> struct __first_element : type_identity<FirstT>{};
}

View File

@@ -65,6 +65,9 @@ template<typename> struct __is_floating_point : false_type {};
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 T> struct __is_pointer<T*> : true_type {};
}
}

View File

@@ -0,0 +1,55 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_LANG_DETAIL_TYPE_TRANSFORMS_H
#define FENNEC_LANG_DETAIL_TYPE_TRANSFORMS_H
#include <fennec/lang/types.h>
namespace fennec
{
namespace detail
{
template<typename _Tp, typename = void>
struct __add_lvalue_reference {
using type = _Tp;
};
template<typename _Tp>
struct __add_lvalue_reference<_Tp, void_t<_Tp&>> {
using type = _Tp&;
};
template<typename _Tp, typename = void>
struct __add_rvalue_reference {
using type = _Tp;
};
template<typename _Tp>
struct __add_rvalue_reference<_Tp, void_t<_Tp&&>> {
using type = _Tp&&;
};
}
}
#endif // FENNEC_LANG_DETAIL_TYPE_TRANSFORMS_H

View File

@@ -0,0 +1,89 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_LANG_HASHING_H
#define FENNEC_LANG_HASHING_H
#include <fennec/lang/types.h>
#include <fennec/lang/type_traits.h>
namespace fennec
{
///
/// \brief Struct for hashing types, there is no default hashing function
/// \tparam Key The type to hash
template<typename Key> struct hash;
// Murmur3 Hash for 64-bit ints
template<>
struct hash<uint64_t> {
using type_t = uint64_t;
constexpr size_t operator()(uint64_t x) const {
// Murmur3
x ^= x >> 33U;
x *= 0xff51afd7ed558ccd;
x ^= x >> 33U;
x *= 0xc4ceb9fe1a85ec53;
x ^= x >> 33U;
return x;
}
};
// Wrapper for casting ints
template<typename IntT>
requires is_integral_v<IntT>
struct hash<IntT> : hash<uint64_t> {
using type_t = IntT;
};
// Wrapper for pointers
template<typename PtrT>
requires is_pointer_v<PtrT>
struct hash<PtrT> : hash<uintptr_t> {
};
// Float
template<>
struct hash<float> : hash<uint32_t> {
constexpr size_t operator()(float x) const {
return hash<uint32_t>::operator()(bit_cast<uint32_t>(x));
}
};
template<>
struct hash<double> : hash<uint64_t> {
constexpr size_t operator()(double x) const {
return hash<uint64_t>::operator()(bit_cast<uint64_t>(x));
}
};
///
/// \brief Pairs two hashes
/// \param x first hash
/// \param y second hash
/// \returns a pairing of the two hashes
constexpr size_t pair_hash(size_t x, size_t y) {
// Szudzik Pairing
return (x >= y ? (x * x) + x + y : (y * y) + x);
}
}
#endif // FENNEC_LANG_HASHING_H

View File

@@ -142,14 +142,44 @@
# define FENNEC_HAS_BUILTIN_IS_CLASS
#endif
// CONSTRUCTORS ========================================================================================================
// Difficult and Inconsistent without intrinsics
#if __has_builtin(__is_constructible)
# define FENNEC_HAS_BUILTIN_IS_CONSTRUCTIBLE 1
# define FENNEC_BUILTIN_IS_CONSTRUCTIBLE(type, ...) __is_constructible(type, __VA_ARGS__)
# define FENNEC_BUILTIN_IS_CONSTRUCTIBLE(type, ...) __is_constructible(type __VA_OPT__(,) __VA_ARGS__)
#else
# define FENNEC_HAS_BUILTIN_IS_CONSTRUCTIBLE 0
#endif
// Difficult and Inconsistent without intrinsics
#if __has_builtin(__is_trivially_constructible)
# define FENNEC_HAS_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE 1
# define FENNEC_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE(type) __is_trivially_constructible(type)
#else
# define FENNEC_HAS_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE 0
#endif
// Difficult and Inconsistent without intrinsics
#if __has_builtin(__has_trivial_destructor)
# define FENNEC_HAS_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE 1
# define FENNEC_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE(type) __has_trivial_destructor(type)
#else
# define FENNEC_HAS_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE 0
#endif
// ASSIGNMENTS =========================================================================================================
// Difficult and Inconsistent without intrinsics
#if __has_builtin(__is_assignable)
# define FENNEC_HAS_BUILTIN_IS_ASSIGNABLE 1
# define FENNEC_BUILTIN_IS_ASSIGNABLE(a, b) __is_assignable(a, b)
#else
# define FENNEC_HAS_BUILTIN_IS_ASSIGNABLE 0
#endif
// Type Traits
// can_convert is also very difficult to implement without intrinsics
#if __has_builtin(__is_convertible)

View File

@@ -0,0 +1,57 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_LANG_TYPE_IDENTITY_H
#define FENNEC_LANG_TYPE_IDENTITY_H
///
/// \page fennec_lang_type_identity Type Identity
///
/// \brief Part of the fennec metaprogramming library. This header defines structures for copying types with different traits
/// or rather, transform them, at compile time.
///
/// \code #include <fennec/lang/type_identity.h> \endcode
///
///
/// <table width="100%" class="fieldtable" id="table_fennec_lang_type_identity">
/// <tr><th style="vertical-align: top">Syntax
/// <th style="vertical-align: top">Description
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::type_identity "type_identity<TypeT>::type"<br>
/// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::type_identity
/// </table>
///
namespace fennec
{
///
/// \brief Base Class for Type Transformations
///
/// \details resembles a transformation from one type to T, the result is stored in the member type_transform::type
/// \tparam T Resultant Type
template<typename T> struct type_identity {
/// \brief the type to transform into
using type = T;
};
}
#endif // FENNEC_LANG_TYPE_IDENTITY_H

View File

@@ -272,6 +272,22 @@ template<typename T> struct is_floating_point
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
///
/// \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_pointer
: detail::__is_pointer<remove_cvr_t<T>>{};
///
/// \brief shorthand for ```is_floating_point<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_pointer_v = is_pointer<T> {};
// Arithmetic Types ====================================================================================================
@@ -339,7 +355,7 @@ template<typename FromT, typename ToT> struct is_convertible
template<typename FromT, typename ToT> constexpr bool_t is_convertible_v = is_convertible<FromT, ToT>{};
// fennec::is_constructible ===============================================================================================
// fennec::is_constructible ============================================================================================
///
/// \brief Check if `ClassT` can be constructed with `ArgsT,` i.e. `ClassT(ArgsT...)`.
@@ -354,7 +370,106 @@ template<typename ClassT, typename...ArgsT> struct is_constructible
template<typename ClassT, typename...ArgsT> constexpr bool_t is_constructible_v = is_constructible<ClassT, ArgsT...>{};
// fennec::
///
/// \brief Check if `ClassT` is default constructible
/// \tparam ClassT The class type to test
template<typename ClassT> struct is_default_constructible
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT,)> {};
///
/// \brief Shorthand for `is_default_constructible<ClassT>::value`
template<typename ClassT, typename...ArgsT> constexpr bool_t is_default_constructible_v = is_default_constructible<ClassT>{};
///
/// \brief Check if `ClassT` is copy constructible
/// \tparam ClassT The class type to test
template<typename ClassT> struct is_copy_constructible
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT, add_lvalue_reference_t<const ClassT>)> {};
///
/// \brief Shorthand for `is_copy_constructible<ClassT>::value`
template<typename ClassT, typename...ArgsT> constexpr bool_t is_copy_constructible_v = is_copy_constructible<ClassT>{};
///
/// \brief Check if `ClassT` is copy constructible
/// \tparam ClassT The class type to test
template<typename ClassT> struct is_move_constructible
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT, add_rvalue_reference_t<ClassT>)> {};
///
/// \brief Shorthand for `is_copy_constructible<ClassT>::value`
template<typename ClassT, typename...ArgsT> constexpr bool_t is_move_constructible_v = is_move_constructible<ClassT>{};
///
/// \brief Check if `ClassT` is trivially constructible
/// \tparam ClassT The class type to test
template<typename ClassT> struct is_trivially_constructible
: bool_constant<FENNEC_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE(ClassT)> {};
///
/// \brief Shorthand for `is_trivially_constructible<ClassT, ArgsT...>::value`
template<typename ClassT> constexpr bool_t is_trivially_constructible_v = is_trivially_constructible<ClassT>{};
// fennec::is_trivially_destructible ===================================================================================
///
/// \brief Check if `ClassT` is trivially destructible
/// \tparam ClassT The class type to test
template<typename ClassT> struct is_trivially_destructible
: bool_constant<FENNEC_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE(ClassT)> {};
///
/// \brief Shorthand for `is_trivially_destructible<ClassT, ArgsT...>::value`
template<typename ClassT> constexpr bool_t is_trivially_destructible_v = is_trivially_destructible<ClassT>{};
// fennec::is_assignable ===============================================================================================
///
/// \brief Check if `ClassT` can be constructed with `ArgsT,` i.e. `ClassT(ArgsT...)`.
/// This may be read as "is `ClassT` constructible with `ArgsT`"
/// \tparam ClassAT The class type to test
/// \tparam ClassBT The arguments for the specific constructor
template<typename ClassAT, typename ClassBT> struct is_assignable
: bool_constant<FENNEC_BUILTIN_IS_ASSIGNABLE(ClassAT, ClassBT)> {};
///
/// \brief Shorthand for `is_constructible<ClassT, ArgsT...>::value`
template<typename ClassT, typename...ArgsT> constexpr bool_t is_assignable_v = is_assignable<ClassT, ArgsT...>{};
// fennec::is_copy_assignable ==========================================================================================
///
/// \brief Check if `ClassT` is copy assignable
/// \tparam ClassT The class type to test
template<typename ClassT> struct is_copy_assignable
: bool_constant<FENNEC_BUILTIN_IS_ASSIGNABLE(add_lvalue_reference_t<ClassT>, add_lvalue_reference_t<const ClassT>)> {};
///
/// \brief Shorthand for `is_copy_assignable<ClassT>::value`
template<typename ClassT> constexpr bool_t is_copy_assignable_v = is_copy_assignable<ClassT>{};
// fennec::is_move_assignable ==========================================================================================
///
/// \brief Check if `ClassT` is move assignable
/// \tparam ClassT The class type to test
template<typename ClassT> struct is_move_assignable
: bool_constant<FENNEC_BUILTIN_IS_ASSIGNABLE(add_lvalue_reference_t<ClassT>, add_rvalue_reference_t<ClassT>)> {};
///
/// \brief Shorthand for `is_move_assignable<ClassT>::value`
template<typename ClassT> constexpr bool_t is_move_assignable_v = is_move_assignable<ClassT>{};
//

View File

@@ -31,6 +31,9 @@
#ifndef FENNEC_LANG_TYPE_TRANSFORMS_H
#define FENNEC_LANG_TYPE_TRANSFORMS_H
#include <fennec/lang/type_identity.h>
#include <fennec/lang/detail/__type_transforms.h>
///
/// \page fennec_lang_type_transforms Type Transforms
///
@@ -44,11 +47,6 @@
/// <tr><th style="vertical-align: top">Syntax
/// <th style="vertical-align: top">Description
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::type_transform "type_transform<TypeT>::type"<br>
/// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::type_transform
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::add_pointer "add_pointer<TypeT>::type"<br>
/// \ref fennec::add_pointer_t "add_pointer_t<TypeT>"
/// <td width="50%" style="vertical-align: top">
@@ -127,22 +125,6 @@
namespace fennec
{
// fennec::type_transform ==============================================================================================
///
/// \brief Base Class for Type Transformations
///
/// \details resembles a transformation from one type to T, the result is stored in the member type_transform::type
/// \tparam T Resultant Type
template<typename T> struct type_transform {
///
/// \brief the type to transform into
using type = T;
};
// Pointer Conversions =================================================================================================
///
@@ -150,7 +132,7 @@ template<typename T> struct type_transform {
///
/// \details adds a pointer to the provided type such that `T` becomes `T*`
/// \tparam T Resultant Type
template<typename T> struct add_pointer : type_transform<T*>{};
template<typename T> struct add_pointer : type_identity<T*>{};
///
/// \brief shorthand for `typename add_pointer<T>::type`
@@ -162,10 +144,10 @@ template<typename T> using add_pointer_t = typename add_pointer<T>::type;
///
/// \details removes a pointer from the provided type such that `T*` becomes `T`
/// \tparam T Resultant Type
template<typename T> struct remove_pointer : type_transform<T> {};
template<typename T> struct remove_pointer : type_identity<T> {};
// specialization for T*
template<typename T> struct remove_pointer<T*> : type_transform<T> {};
template<typename T> struct remove_pointer<T*> : type_identity<T> {};
///
/// \brief shorthand for `typename remove_pointer<T>::type`
@@ -180,7 +162,7 @@ template<typename T> using remove_pointer_t = typename remove_pointer<T>::type;
///
/// \details adds a pointer to the provided type such that `T` becomes `T&`
/// \tparam T Resultant Type
template<typename T> struct add_reference : type_transform<T&> {};
template<typename T> struct add_reference : type_identity<T&> {};
///
/// \brief shorthand for `typename add_reference<T>::type`
@@ -192,19 +174,43 @@ template<typename T> using add_reference_t = typename add_reference<T>::type;
///
/// \details removes references from the provided type such that `T&` and `T&&` become `T`
/// \tparam T Reference Type
template<typename T> struct remove_reference : type_transform<T> {};
template<typename T> struct remove_reference : type_identity<T> {};
// specialization for `T&`
template<typename T> struct remove_reference<T&> : type_transform<T> {};
template<typename T> struct remove_reference<T&> : type_identity<T> {};
// specialization for `T&&`
template<typename T> struct remove_reference<T&&> : type_transform<T> {};
template<typename T> struct remove_reference<T&&> : type_identity<T> {};
///
/// \brief shorthand for `typename remove_reference<T>::type`
template<typename T> using remove_reference_t = typename remove_reference<T>::type;
///
/// \brief add a lvalue reference to \p T
///
/// \details adds a lvalue reference to the provided type such that 'T' becomes 'T&'
/// \tparam T Reference Type
template<typename T> struct add_lvalue_reference : detail::__add_lvalue_reference<T> {};
///
/// \brief shorthand for `typename remove_reference<T>::type`
template<typename T> using add_lvalue_reference_t = typename add_lvalue_reference<T>::type;
///
/// \brief add a rvalue reference to \p T
///
/// \details adds a rvalue reference to the provided type such that 'T' becomes 'T&&'
/// \tparam T Reference Type
template<typename T> struct add_rvalue_reference : detail::__add_rvalue_reference<T> {};
///
/// \brief shorthand for `typename remove_reference<T>::type`
template<typename T> using add_rvalue_reference_t = typename add_rvalue_reference<T>::type;
// Const & Volatile Conversions ========================================================================================
@@ -213,14 +219,14 @@ template<typename T> using remove_reference_t = typename remove_reference<T>::t
///
/// \details adds const qualification to the provided type such that `T` becomes `const T`
/// \tparam T Reference Type
template<typename T> struct add_const : type_transform<const T> {};
template<typename T> struct add_const : type_identity<const T> {};
///
/// \brief shorthand for `typename add_const<T>::type`
template<typename T> using add_const_t = typename add_const<T>::type;
// specialization for const types
template<typename T> struct add_const<const T> : type_transform<const T> {};
template<typename T> struct add_const<const T> : type_identity<const T> {};
///
@@ -228,14 +234,14 @@ template<typename T> struct add_const<const T> : type_transform<const T> {};
///
/// \details removes const qualification from the provided type such that `const T` becomes `T`
/// \tparam T Reference Type
template<typename T> struct remove_const : type_transform<T> {};
template<typename T> struct remove_const : type_identity<T> {};
///
/// \brief shorthand for `typename remove_const<T>::type`
template<typename T> using remove_const_t = typename remove_const<T>::type;
// specialization for const types
template<typename T> struct remove_const<const T> : type_transform<T> {};
template<typename T> struct remove_const<const T> : type_identity<T> {};
@@ -244,14 +250,14 @@ template<typename T> struct remove_const<const T> : type_transform<T> {};
///
/// \details removes references from the provided type such that `T` becomes `volatile T`
/// \tparam T Reference Type
template<typename T> struct add_volatile : type_transform<volatile T> {};
template<typename T> struct add_volatile : type_identity<volatile T> {};
///
/// \brief shorthand for `typename add_volatile<T>::type`
template<typename T> using add_volatile_t = typename add_volatile<T>::type;
// specialization for volatile types
template<typename T> struct add_volatile<volatile T> : type_transform<volatile T> {};
template<typename T> struct add_volatile<volatile T> : type_identity<volatile T> {};
///
@@ -259,14 +265,14 @@ template<typename T> struct add_volatile<volatile T> : type_transform<volatile T
///
/// \details removes references from the provided type such that `volatile T` becomes `T`
/// \tparam T Reference Type
template<typename T> struct remove_volatile : type_transform<T> {};
template<typename T> struct remove_volatile : type_identity<T> {};
///
/// \brief shorthand for `typename remove_volatile<T>::type`
template<typename T> using remove_volatile_t = typename remove_volatile<T>::type;
// specialization for volatile types
template<typename T> struct remove_volatile<volatile T> : type_transform<T> {};
template<typename T> struct remove_volatile<volatile T> : type_identity<T> {};
@@ -276,20 +282,20 @@ template<typename T> struct remove_volatile<volatile T> : type_transform<T> {};
/// \details removes references from the provided type such that `T`, `const T`, and `volatile T` become
/// `const volatile T`
/// \tparam T Reference Type
template<typename T> struct add_cv : type_transform<const volatile T> {};
template<typename T> struct add_cv : type_identity<const volatile T> {};
///
/// \brief shorthand for `typename add_cv<T>::type`
template<typename T> using add_cv_t = typename add_cv<T>::type;
// specialization for const types
template<typename T> struct add_cv<const T> : type_transform<const volatile T> {};
template<typename T> struct add_cv<const T> : type_identity<const volatile T> {};
// specialization for volatile types
template<typename T> struct add_cv<volatile T> : type_transform<const volatile T> {};
template<typename T> struct add_cv<volatile T> : type_identity<const volatile T> {};
// specialization for const volatile types
template<typename T> struct add_cv<const volatile T> : type_transform<const volatile T> {};
template<typename T> struct add_cv<const volatile T> : type_identity<const volatile T> {};
@@ -299,16 +305,16 @@ template<typename T> struct add_cv<const volatile T> : type_transform<const vola
/// \details removes const and volatile from the provided type such that `const T`, `volatile T`, and
/// `const volatile T` become `T`
/// \tparam T Reference Type
template<typename T> struct remove_cv : type_transform<T> {};
template<typename T> struct remove_cv : type_identity<T> {};
// specialization for const types
template<typename T> struct remove_cv<const T> : type_transform<T> {};
template<typename T> struct remove_cv<const T> : type_identity<T> {};
// specialization for volatile types
template<typename T> struct remove_cv<volatile T> : type_transform<T> {};
template<typename T> struct remove_cv<volatile T> : type_identity<T> {};
// specialization for const volatile types
template<typename T> struct remove_cv<const volatile T> : type_transform<T> {};
template<typename T> struct remove_cv<const volatile T> : type_identity<T> {};
///
/// \brief shorthand for `typename remove_cv<T>::type`
@@ -321,7 +327,7 @@ template<typename T> using remove_cv_t = typename remove_cv<T>::type;
///
/// \details adds references and const volatile qualifiers to the provided type.
/// \tparam T Reference Type
template<typename T> struct add_cvr : type_transform<add_reference_t<add_cv_t<T>>> {};
template<typename T> struct add_cvr : type_identity<add_reference_t<add_cv_t<T>>> {};
///
/// \brief shorthand for `typename add_cvr<T>::type`
@@ -334,7 +340,7 @@ template<typename T> using add_cvr_t = typename add_cvr<T>::type;
///
/// \details removes const and volatile from the provided type such that
/// \tparam T Reference Type
template<typename T> struct remove_cvr : type_transform<remove_cv_t<remove_reference_t<T>>> {};
template<typename T> struct remove_cvr : type_identity<remove_cv_t<remove_reference_t<T>>> {};
///

View File

@@ -242,7 +242,6 @@ namespace fennec
/// \name Special Types
/// @{
using nullptr_t = decltype(nullptr); ///< \brief Null Pointer Type
using intptr_t = intptr_t; ///< \brief Signed Integer Capable of Holding a Pointer to void
using uintptr_t = uintptr_t; ///< \brief Unsigned Integer Capable of Holding a Pointer to void
@@ -251,6 +250,7 @@ namespace fennec
using size_t = size_t; ///< \brief Unsigned Integer Type Returned By `sizeof`, `sizeof...`, and `alignof`
using ptrdiff_t = __PTRDIFF_TYPE__; ///< \brief Signed Integer Type Returned by the Subtraction of two Pointers
class undefined_t; ///< \brief undefined class for SFINAE
template<typename...> using void_t = void; ///< \brief Void type used for SFINAE
@@ -263,15 +263,15 @@ namespace fennec
/// \name Sized Integer Types
/// @{
using int8_t = schar_t; ///< \brief Signed 8-bit integer
using int16_t = short_t; ///< \brief Signed 16-bit integer
using int32_t = conditional_t<sizeof(int_t) == 4, int_t, long_t>; ///< \brief Signed 32-bit integer
using int64_t = llong_t; ///< \brief Signed 64-bit integer
using int8_t = schar_t; ///< \brief Signed 8-bit integer
using int16_t = short_t; ///< \brief Signed 16-bit integer
using int32_t = conditional_t<sizeof(int_t) == 4, int_t, long_t>; ///< \brief Signed 32-bit integer
using int64_t = conditional_t<sizeof(long_t) == 8, long_t, llong_t>; ///< \brief Signed 64-bit integer
using uint8_t = uchar_t; ///< \brief Unsigned 8-bit integer
using uint16_t = ushort_t; ///< \brief Unsigned 16-bit integer
using uint32_t = conditional_t<sizeof(uint_t) == 4, uint_t, ulong_t>; ///< \brief Unsigned 32-bit integer
using uint64_t = ullong_t; ///< \brief Unsigned 64-bit integer
using uint8_t = uchar_t; ///< \brief Unsigned 8-bit integer
using uint16_t = ushort_t; ///< \brief Unsigned 16-bit integer
using uint32_t = conditional_t<sizeof(uint_t) == 4, uint_t, ulong_t>; ///< \brief Unsigned 32-bit integer
using uint64_t = conditional_t<sizeof(ulong_t) == 8, ulong_t, ullong_t>; ///< \brief Unsigned 64-bit integer
/// @}

View File

@@ -60,6 +60,7 @@
///
#include <fennec/lang/type_transforms.h>
#include <fennec/lang/type_traits.h>
namespace fennec
{
@@ -104,6 +105,29 @@ template<typename T> constexpr const remove_reference_t<T>& copy(T&& x) noexcept
return x;
}
///
/// \brief Swaps x and y
/// \tparam T the fundamental type
/// \param x first value
/// \param y second value
template<typename T> requires is_fundamental_v<T>
constexpr void swap(T& x, T& y) noexcept {
T a = x;
x = y;
y = a;
}
///
/// \brief Swaps x and y without invoking destructor
/// \tparam T the type
/// \param x first value
/// \param y second value
template<typename T> constexpr void swap(T& x, T& y) noexcept {
T a = fennec::move(x);
x = fennec::move(y);
y = fennec::move(a);
}
}
#endif // FENNEC_LANG_UTILITY_H