- Adjusted Formatting of tests
- Finished map implementation and unit tests TODO: Threading
This commit is contained in:
123
include/fennec/lang/compare.h
Normal file
123
include/fennec/lang/compare.h
Normal file
@@ -0,0 +1,123 @@
|
||||
// =====================================================================================================================
|
||||
// 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_COMPARE_H
|
||||
#define FENNEC_LANG_COMPARE_H
|
||||
|
||||
#include <fennec/lang/type_operators.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
// equality ============================================================================================================
|
||||
|
||||
template<typename T0, typename T1 = T0> struct equality;
|
||||
|
||||
template<typename T0, typename T1> requires has_equals_v<T0, T1>
|
||||
struct equality<T0, T1> {
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return x == y;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T0, typename T1> requires(not has_equals_v<T0, T1>
|
||||
and has_less_v<T0, T1> and has_less_v<T1, T0>)
|
||||
struct equality<T0, T1> {
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return not(x < y) and not(y < x);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T0, typename T1> requires(not(has_equals_v<T0, T1>)
|
||||
and(not has_less_v<T0, T1> or not has_less_v<T1, T0>)
|
||||
and(has_greater_v<T0, T1> and has_greater_v<T1, T0>))
|
||||
struct equality<T0, T1> {
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return not(x > y) and not(y > x);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// inequality ==========================================================================================================
|
||||
|
||||
template<typename T0, typename T1 = T0> struct inequality;
|
||||
|
||||
template<typename T0, typename T1> requires has_nequals_v<T0, T1>
|
||||
struct inequality<T0, T1> {
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return x != y;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T0, typename T1> requires has_less_v<T0, T1> and has_less_v<T1, T0>
|
||||
struct inequality<T0, T1> {
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return (x < y) or (y < x);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T0, typename T1> requires has_greater_v<T0, T1> and has_greater_v<T1, T0>
|
||||
struct inequality<T0, T1> {
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return (x > y) or (y > x);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// less ================================================================================================================
|
||||
|
||||
template<typename T0, typename T1 = T0> requires has_less_v<T0, T1>
|
||||
struct less {
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return x < y;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// less_equal ==========================================================================================================
|
||||
|
||||
template<typename T0, typename T1 = T0> requires has_less_equals_v<T0, T1>
|
||||
struct less_equals {
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return x <= y;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// less ================================================================================================================
|
||||
|
||||
template<typename T0, typename T1 = T0> requires has_greater_v<T0, T1>
|
||||
struct greater {
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return x < y;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// less_equal ==========================================================================================================
|
||||
|
||||
template<typename T0, typename T1 = T0> requires has_greater_equals_v<T0, T1>
|
||||
struct greater_equals {
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return x <= y;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANG_COMPARE_H
|
||||
@@ -21,123 +21,118 @@
|
||||
|
||||
#include <fennec/lang/types.h>
|
||||
|
||||
namespace fennec
|
||||
namespace fennec::detail
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// helper for bitwise and for 1 byte
|
||||
constexpr size_t __bit_and_8(void* dst, const void* src) {
|
||||
*static_cast<uint8_t*>(dst) = *static_cast<uint8_t*>(dst) & *static_cast<const uint8_t*>(src); return 1;
|
||||
}
|
||||
|
||||
// helper for bitwise and 2 bytes at once
|
||||
constexpr size_t __bit_and_16(void* dst, const void* src) {
|
||||
*static_cast<uint16_t*>(dst) = *static_cast<uint16_t*>(dst) & *static_cast<const uint16_t*>(src); return 2;
|
||||
}
|
||||
|
||||
// helper for bitwise and 4 bytes at once
|
||||
constexpr size_t __bit_and_32(void* dst, const void* src) {
|
||||
*static_cast<uint32_t*>(dst) = *static_cast<uint32_t*>(dst) & *static_cast<const uint32_t*>(src); return 4;
|
||||
}
|
||||
|
||||
// helper for bitwise and 8 bytes at once
|
||||
constexpr size_t __bit_and_64(void* dst, const void* src) {
|
||||
*static_cast<uint64_t*>(dst) = *static_cast<uint64_t*>(dst) & *static_cast<const uint64_t*>(src); return 8;
|
||||
}
|
||||
|
||||
// helper for selecting size
|
||||
constexpr size_t __bit_and(void* dst, const void* src, size_t n) {
|
||||
switch (n) {
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
return __bit_and_8(dst, src);
|
||||
case 2: case 3:
|
||||
return __bit_and_16(dst, src);
|
||||
case 4: case 5: case 6: case 7:
|
||||
return __bit_and_32(dst, src);
|
||||
default:
|
||||
return __bit_and_64(dst, src);
|
||||
// helper for bitwise and for 1 byte
|
||||
constexpr size_t __bit_and_8(void* dst, const void* src) {
|
||||
*static_cast<uint8_t*>(dst) = *static_cast<uint8_t*>(dst) & *static_cast<const uint8_t*>(src); return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// helper for bitwise or for 1 byte
|
||||
constexpr size_t __bit_or_8(void* dst, const void* src) {
|
||||
*static_cast<uint8_t*>(dst) = *static_cast<uint8_t*>(dst) | *static_cast<const uint8_t*>(src); return 1;
|
||||
}
|
||||
|
||||
// helper for bitwise or 2 bytes at once
|
||||
constexpr size_t __bit_or_16(void* dst, const void* src) {
|
||||
*static_cast<uint16_t*>(dst) = *static_cast<uint16_t*>(dst) | *static_cast<const uint16_t*>(src); return 2;
|
||||
}
|
||||
|
||||
// helper for bitwise or 4 bytes at once
|
||||
constexpr size_t __bit_or_32(void* dst, const void* src) {
|
||||
*static_cast<uint32_t*>(dst) = *static_cast<uint32_t*>(dst) | *static_cast<const uint32_t*>(src); return 4;
|
||||
}
|
||||
|
||||
// helper for bitwise or 8 bytes at once
|
||||
constexpr size_t __bit_or_64(void* dst, const void* src) {
|
||||
*static_cast<uint64_t*>(dst) = *static_cast<uint64_t*>(dst) | *static_cast<const uint64_t*>(src); return 8;
|
||||
}
|
||||
|
||||
// helper for selecting size
|
||||
constexpr size_t __bit_or(void* dst, const void* src, size_t n) {
|
||||
switch (n) {
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
return __bit_or_8(dst, src);
|
||||
case 2: case 3:
|
||||
return __bit_or_16(dst, src);
|
||||
case 4: case 5: case 6: case 7:
|
||||
return __bit_or_32(dst, src);
|
||||
default:
|
||||
return __bit_or_64(dst, src);
|
||||
// helper for bitwise and 2 bytes at once
|
||||
constexpr size_t __bit_and_16(void* dst, const void* src) {
|
||||
*static_cast<uint16_t*>(dst) = *static_cast<uint16_t*>(dst) & *static_cast<const uint16_t*>(src); return 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// helper for bitwise and 1 byte
|
||||
constexpr size_t __bit_xor_8(void* dst, const void* src) {
|
||||
*static_cast<uint8_t*>(dst) = *static_cast<uint8_t*>(dst) ^ *static_cast<const uint8_t*>(src); return 1;
|
||||
}
|
||||
|
||||
// helper for bitwise xor 2 bytes at once
|
||||
constexpr size_t __bit_xor_16(void* dst, const void* src) {
|
||||
*static_cast<uint16_t*>(dst) = *static_cast<uint16_t*>(dst) ^ *static_cast<const uint16_t*>(src); return 2;
|
||||
}
|
||||
|
||||
// helper for bitwise xor 4 bytes at once
|
||||
constexpr size_t __bit_xor_32(void* dst, const void* src) {
|
||||
*static_cast<uint32_t*>(dst) = *static_cast<uint32_t*>(dst) ^ *static_cast<const uint32_t*>(src); return 4;
|
||||
}
|
||||
|
||||
// helper for bitwise xor 8 bytes at once
|
||||
constexpr size_t __bit_xor_64(void* dst, const void* src) {
|
||||
*static_cast<uint64_t*>(dst) = *static_cast<uint64_t*>(dst) ^ *static_cast<const uint64_t*>(src); return 8;
|
||||
}
|
||||
|
||||
// helper for selecting size
|
||||
constexpr size_t __bit_xor(void* dst, const void* src, size_t n) {
|
||||
switch (n) {
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
return __bit_xor_8(dst, src);
|
||||
case 2: case 3:
|
||||
return __bit_xor_16(dst, src);
|
||||
case 4: case 5: case 6: case 7:
|
||||
return __bit_xor_32(dst, src);
|
||||
default:
|
||||
return __bit_xor_64(dst, src);
|
||||
// helper for bitwise and 4 bytes at once
|
||||
constexpr size_t __bit_and_32(void* dst, const void* src) {
|
||||
*static_cast<uint32_t*>(dst) = *static_cast<uint32_t*>(dst) & *static_cast<const uint32_t*>(src); return 4;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// helper for bitwise and 8 bytes at once
|
||||
constexpr size_t __bit_and_64(void* dst, const void* src) {
|
||||
*static_cast<uint64_t*>(dst) = *static_cast<uint64_t*>(dst) & *static_cast<const uint64_t*>(src); return 8;
|
||||
}
|
||||
|
||||
// helper for selecting size
|
||||
constexpr size_t __bit_and(void* dst, const void* src, size_t n) {
|
||||
switch (n) {
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
return __bit_and_8(dst, src);
|
||||
case 2: case 3:
|
||||
return __bit_and_16(dst, src);
|
||||
case 4: case 5: case 6: case 7:
|
||||
return __bit_and_32(dst, src);
|
||||
default:
|
||||
return __bit_and_64(dst, src);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// helper for bitwise or for 1 byte
|
||||
constexpr size_t __bit_or_8(void* dst, const void* src) {
|
||||
*static_cast<uint8_t*>(dst) = *static_cast<uint8_t*>(dst) | *static_cast<const uint8_t*>(src); return 1;
|
||||
}
|
||||
|
||||
// helper for bitwise or 2 bytes at once
|
||||
constexpr size_t __bit_or_16(void* dst, const void* src) {
|
||||
*static_cast<uint16_t*>(dst) = *static_cast<uint16_t*>(dst) | *static_cast<const uint16_t*>(src); return 2;
|
||||
}
|
||||
|
||||
// helper for bitwise or 4 bytes at once
|
||||
constexpr size_t __bit_or_32(void* dst, const void* src) {
|
||||
*static_cast<uint32_t*>(dst) = *static_cast<uint32_t*>(dst) | *static_cast<const uint32_t*>(src); return 4;
|
||||
}
|
||||
|
||||
// helper for bitwise or 8 bytes at once
|
||||
constexpr size_t __bit_or_64(void* dst, const void* src) {
|
||||
*static_cast<uint64_t*>(dst) = *static_cast<uint64_t*>(dst) | *static_cast<const uint64_t*>(src); return 8;
|
||||
}
|
||||
|
||||
// helper for selecting size
|
||||
constexpr size_t __bit_or(void* dst, const void* src, size_t n) {
|
||||
switch (n) {
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
return __bit_or_8(dst, src);
|
||||
case 2: case 3:
|
||||
return __bit_or_16(dst, src);
|
||||
case 4: case 5: case 6: case 7:
|
||||
return __bit_or_32(dst, src);
|
||||
default:
|
||||
return __bit_or_64(dst, src);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// helper for bitwise and 1 byte
|
||||
constexpr size_t __bit_xor_8(void* dst, const void* src) {
|
||||
*static_cast<uint8_t*>(dst) = *static_cast<uint8_t*>(dst) ^ *static_cast<const uint8_t*>(src); return 1;
|
||||
}
|
||||
|
||||
// helper for bitwise xor 2 bytes at once
|
||||
constexpr size_t __bit_xor_16(void* dst, const void* src) {
|
||||
*static_cast<uint16_t*>(dst) = *static_cast<uint16_t*>(dst) ^ *static_cast<const uint16_t*>(src); return 2;
|
||||
}
|
||||
|
||||
// helper for bitwise xor 4 bytes at once
|
||||
constexpr size_t __bit_xor_32(void* dst, const void* src) {
|
||||
*static_cast<uint32_t*>(dst) = *static_cast<uint32_t*>(dst) ^ *static_cast<const uint32_t*>(src); return 4;
|
||||
}
|
||||
|
||||
// helper for bitwise xor 8 bytes at once
|
||||
constexpr size_t __bit_xor_64(void* dst, const void* src) {
|
||||
*static_cast<uint64_t*>(dst) = *static_cast<uint64_t*>(dst) ^ *static_cast<const uint64_t*>(src); return 8;
|
||||
}
|
||||
|
||||
// helper for selecting size
|
||||
constexpr size_t __bit_xor(void* dst, const void* src, size_t n) {
|
||||
switch (n) {
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
return __bit_xor_8(dst, src);
|
||||
case 2: case 3:
|
||||
return __bit_xor_16(dst, src);
|
||||
case 4: case 5: case 6: case 7:
|
||||
return __bit_xor_32(dst, src);
|
||||
default:
|
||||
return __bit_xor_64(dst, src);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -22,42 +22,37 @@
|
||||
#include <fennec/lang/types.h>
|
||||
#include <fennec/lang/type_transforms.h>
|
||||
|
||||
namespace fennec
|
||||
namespace fennec::detail
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template<typename> struct __make_unsigned : type_identity<undefined_t> {};
|
||||
|
||||
template<typename> struct __make_unsigned : type_identity<undefined_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<> 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_identity<undefined_t> {};
|
||||
template<typename> struct __make_signed : type_identity<undefined_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> {};
|
||||
|
||||
}
|
||||
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> {};
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -21,16 +21,20 @@
|
||||
|
||||
#include <fennec/lang/type_transforms.h>
|
||||
|
||||
namespace fennec
|
||||
namespace fennec::detail
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template<typename FirstT, typename... RestT> struct __first_element : type_identity<FirstT> {};
|
||||
|
||||
template<typename FirstT, typename... RestT> struct __first_element : type_identity<FirstT>{};
|
||||
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> {};
|
||||
|
||||
template<size_t n, size_t i, typename HeadT, typename...RestT>
|
||||
struct __nth_element<n, i, HeadT, RestT...> : conditional<
|
||||
n == i, type_identity<HeadT>,
|
||||
__nth_element<n, i + 1, RestT...>
|
||||
> {};
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANG_DETAIL_TYPE_SEQUENCES_H
|
||||
|
||||
@@ -22,53 +22,53 @@
|
||||
#include <fennec/lang/constants.h>
|
||||
#include <fennec/lang/float.h>
|
||||
|
||||
namespace fennec
|
||||
namespace fennec::detail
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// Nothing interesting to note here
|
||||
template<typename> struct __is_void : false_type {};
|
||||
template<> struct __is_void<void> : true_type {};
|
||||
|
||||
// Nothing interesting to note here
|
||||
template<typename> struct __is_void : false_type {};
|
||||
template<> struct __is_void<void> : true_type {};
|
||||
template<typename> struct __is_bool : false_type {};
|
||||
template<> struct __is_bool<bool_t> : true_type {};
|
||||
|
||||
template<typename> struct __is_bool : false_type {};
|
||||
template<> struct __is_bool<bool_t> : true_type {};
|
||||
template<typename> struct __is_null_pointer : false_type {};
|
||||
template<> struct __is_null_pointer<nullptr_t> : true_type {};
|
||||
|
||||
template<typename> struct __is_null_pointer : false_type {};
|
||||
template<> struct __is_null_pointer<nullptr_t> : true_type {};
|
||||
// Provides definitions for all builtin int types
|
||||
template<typename> struct __is_integral : false_type {};
|
||||
template<> struct __is_integral<bool_t> : true_type {};
|
||||
template<> struct __is_integral<char_t> : true_type {};
|
||||
template<> struct __is_integral<char8_t> : true_type {};
|
||||
template<> struct __is_integral<char16_t> : true_type {};
|
||||
template<> struct __is_integral<char32_t> : true_type {};
|
||||
template<> struct __is_integral<schar_t> : true_type {};
|
||||
template<> struct __is_integral<uchar_t> : true_type {};
|
||||
template<> struct __is_integral<wchar_t> : true_type {};
|
||||
template<> struct __is_integral<short_t> : true_type {};
|
||||
template<> struct __is_integral<ushort_t> : true_type {};
|
||||
template<> struct __is_integral<int_t> : true_type {};
|
||||
template<> struct __is_integral<uint_t> : true_type {};
|
||||
template<> struct __is_integral<long_t> : true_type {};
|
||||
template<> struct __is_integral<ulong_t> : true_type {};
|
||||
template<> struct __is_integral<llong_t> : true_type {};
|
||||
template<> struct __is_integral<ullong_t> : true_type {};
|
||||
|
||||
// Provides definitions for all builtin int types
|
||||
template<typename> struct __is_integral : false_type {};
|
||||
template<> struct __is_integral<bool_t> : true_type {};
|
||||
template<> struct __is_integral<char_t> : true_type {};
|
||||
template<> struct __is_integral<char8_t> : true_type {};
|
||||
template<> struct __is_integral<char16_t> : true_type {};
|
||||
template<> struct __is_integral<char32_t> : true_type {};
|
||||
template<> struct __is_integral<schar_t> : true_type {};
|
||||
template<> struct __is_integral<uchar_t> : true_type {};
|
||||
template<> struct __is_integral<wchar_t> : true_type {};
|
||||
template<> struct __is_integral<short_t> : true_type {};
|
||||
template<> struct __is_integral<ushort_t> : true_type {};
|
||||
template<> struct __is_integral<int_t> : true_type {};
|
||||
template<> struct __is_integral<uint_t> : true_type {};
|
||||
template<> struct __is_integral<long_t> : true_type {};
|
||||
template<> struct __is_integral<ulong_t> : true_type {};
|
||||
template<> struct __is_integral<llong_t> : true_type {};
|
||||
template<> struct __is_integral<ullong_t> : true_type {};
|
||||
// Most unsigned types will underflow `-1` to the types maximum value
|
||||
template<typename TypeT> struct __is_signed : bool_constant<TypeT(-1) < TypeT(0)> {};
|
||||
template<typename TypeT> struct __is_unsigned : bool_constant<TypeT(-1) >= TypeT(0)> {};
|
||||
|
||||
// Most unsigned types will underflow `-1` to the types maximum value
|
||||
template<typename TypeT> struct __is_signed : bool_constant<TypeT(-1) < TypeT(0)> {};
|
||||
template<typename TypeT> struct __is_unsigned : bool_constant<TypeT(-1) >= TypeT(0)> {};
|
||||
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_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 {};
|
||||
|
||||
template<typename> struct __is_pointer : false_type {};
|
||||
template<typename T> struct __is_pointer<T*> : true_type {};
|
||||
template<typename T, typename U = T&&> U __declval(int);
|
||||
template<typename T> T __declval(long);
|
||||
|
||||
}
|
||||
template<typename T> struct __declval_protector : bool_constant<false> {};
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -21,34 +21,29 @@
|
||||
|
||||
#include <fennec/lang/types.h>
|
||||
|
||||
namespace fennec
|
||||
namespace fennec::detail
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template<typename _Tp, typename = void>
|
||||
struct __add_lvalue_reference {
|
||||
using type = _Tp;
|
||||
};
|
||||
|
||||
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>
|
||||
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, typename = void>
|
||||
struct __add_rvalue_reference {
|
||||
using type = _Tp;
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
struct __add_rvalue_reference<_Tp, void_t<_Tp&&>> {
|
||||
using type = _Tp&&;
|
||||
};
|
||||
|
||||
}
|
||||
template<typename _Tp>
|
||||
struct __add_rvalue_reference<_Tp, void_t<_Tp&&>> {
|
||||
using type = _Tp&&;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
112
include/fennec/lang/type_operators.h
Normal file
112
include/fennec/lang/type_operators.h
Normal file
@@ -0,0 +1,112 @@
|
||||
// =====================================================================================================================
|
||||
// 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_OPERATORS_H
|
||||
#define FENNEC_LANG_TYPE_OPERATORS_H
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
// https://stackoverflow.com/questions/6534041/how-to-check-whether-operator-exists
|
||||
|
||||
// has_equals ==========================================================================================================
|
||||
|
||||
template<typename T0, typename T1 = T0>
|
||||
struct has_equals {
|
||||
// Use SFINAE to check for the operator
|
||||
template<typename U, typename V> static auto test(U*) -> decltype(declval<U>() == declval<V>());
|
||||
template<typename, typename> static auto test(...) -> false_type;
|
||||
|
||||
static constexpr bool value = is_same_v<bool, decltype(test<T0, T1>(0))>;
|
||||
};
|
||||
|
||||
template<typename T0, typename T1 = T0> constexpr bool has_equals_v = has_equals<T0, T1>::value;
|
||||
|
||||
// has_nequals =========================================================================================================
|
||||
|
||||
template<typename T0, typename T1 = T0>
|
||||
struct has_nequals {
|
||||
// Use SFINAE to check for the operator
|
||||
template<typename U, typename V> static auto test(U*) -> decltype(declval<U>() != declval<V>());
|
||||
template<typename, typename> static auto test(...) -> false_type;
|
||||
|
||||
static constexpr bool value = is_same_v<bool, decltype(test<T0, T1>(0))>;
|
||||
};
|
||||
|
||||
template<typename T0, typename T1 = T0> constexpr bool has_nequals_v = has_nequals<T0, T1>::value;
|
||||
|
||||
|
||||
// has_less ============================================================================================================
|
||||
|
||||
template<typename T0, typename T1 = T0>
|
||||
struct has_less {
|
||||
// Use SFINAE to check for the operator
|
||||
template<typename U, typename V> static auto test(U*) -> decltype(declval<U>() < declval<V>());
|
||||
template<typename, typename> static auto test(...) -> false_type;
|
||||
|
||||
static constexpr bool value = is_same_v<bool, decltype(test<T0, T1>(0))>;
|
||||
};
|
||||
|
||||
template<typename T0, typename T1 = T0> constexpr bool has_less_v = has_less<T0, T1>::value;
|
||||
|
||||
|
||||
// has_less_equals =====================================================================================================
|
||||
|
||||
template<typename T0, typename T1 = T0>
|
||||
struct has_less_equals {
|
||||
// Use SFINAE to check for the operator
|
||||
template<typename U, typename V> static auto test(U*) -> decltype(declval<U>() <= declval<V>());
|
||||
template<typename, typename> static auto test(...) -> false_type;
|
||||
|
||||
static constexpr bool value = is_same_v<bool, decltype(test<T0, T1>(0))>;
|
||||
};
|
||||
|
||||
template<typename T0, typename T1 = T0> constexpr bool has_less_equals_v = has_less_equals<T0, T1>::value;
|
||||
|
||||
|
||||
// has_greater =========================================================================================================
|
||||
|
||||
template<typename T0, typename T1 = T0>
|
||||
struct has_greater {
|
||||
// Use SFINAE to check for the operator
|
||||
template<typename U, typename V> static auto test(U*) -> decltype(declval<U>() > declval<V>());
|
||||
template<typename, typename> static auto test(...) -> false_type;
|
||||
|
||||
static constexpr bool value = is_same_v<bool, decltype(test<T0, T1>(0))>;
|
||||
};
|
||||
|
||||
template<typename T0, typename T1 = T0> constexpr bool has_greater_v = has_greater<T0, T1>::value;
|
||||
|
||||
|
||||
// has_greater_equals ==================================================================================================
|
||||
|
||||
template<typename T0, typename T1 = T0>
|
||||
struct has_greater_equals {
|
||||
// Use SFINAE to check for the operator
|
||||
template<typename U, typename V> static auto test(U*) -> decltype(declval<U>() >= declval<V>());
|
||||
template<typename, typename> static auto test(...) -> false_type;
|
||||
|
||||
static constexpr bool value = is_same_v<bool, decltype(test<T0, T1>(0))>;
|
||||
};
|
||||
|
||||
template<typename T0, typename T1 = T0> constexpr bool has_greater_equals_v = has_greater_equals<T0, T1>::value;
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANG_TYPE_OPERATORS_H
|
||||
@@ -69,6 +69,8 @@ template<typename...TypesT> struct first_element : detail::__first_element<Types
|
||||
template<typename...TypesT> using first_element_t = typename first_element<TypesT...>::type;
|
||||
|
||||
|
||||
template<size_t n, typename...TypesT> struct nth_element : detail::__nth_element<n, 0, TypesT...> {};
|
||||
|
||||
|
||||
///
|
||||
/// \brief Take a Template with a Pack `ClassT<ArgsT...>` and replace the first `ArgT` of `ArgsT...` with `SubT`
|
||||
|
||||
@@ -112,6 +112,14 @@
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
// fennec::declval =====================================================================================================
|
||||
|
||||
template<typename T> auto declval() noexcept -> decltype(detail::__declval<T>(0)) {
|
||||
static_assert(detail::__declval_protector<T>{}, "declval must not be used");
|
||||
return detail::__declval<T>(0);
|
||||
}
|
||||
|
||||
|
||||
// fennec::is_void =====================================================================================================
|
||||
|
||||
///
|
||||
|
||||
Reference in New Issue
Block a user