mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-06 15:01:28 +12:00
Type hacks removed
This commit is contained in:
parent
2d512121f1
commit
949200cd3e
5 changed files with 403 additions and 530 deletions
|
@ -4,20 +4,20 @@
|
|||
#include <climits>
|
||||
#include <type_traits>
|
||||
|
||||
using schar = signed char;
|
||||
using uchar = unsigned char;
|
||||
using schar = signed char;
|
||||
using uchar = unsigned char;
|
||||
using ushort = unsigned short;
|
||||
using uint = unsigned int;
|
||||
using ulong = unsigned long;
|
||||
using uint = unsigned int;
|
||||
using ulong = unsigned long;
|
||||
using ullong = unsigned long long;
|
||||
using llong = long long;
|
||||
using llong = long long;
|
||||
|
||||
using u8 = std::uint8_t;
|
||||
using u8 = std::uint8_t;
|
||||
using u16 = std::uint16_t;
|
||||
using u32 = std::uint32_t;
|
||||
using u64 = std::uint64_t;
|
||||
|
||||
using s8 = std::int8_t;
|
||||
using s8 = std::int8_t;
|
||||
using s16 = std::int16_t;
|
||||
using s32 = std::int32_t;
|
||||
using s64 = std::int64_t;
|
||||
|
@ -28,63 +28,63 @@ namespace gsl
|
|||
}
|
||||
|
||||
// Formatting helper, type-specific preprocessing for improving safety and functionality
|
||||
template<typename T, typename = void>
|
||||
template <typename T, typename = void>
|
||||
struct fmt_unveil;
|
||||
|
||||
struct fmt_type_info;
|
||||
|
||||
namespace fmt
|
||||
{
|
||||
template<typename... Args>
|
||||
template <typename... Args>
|
||||
const fmt_type_info* get_type_info();
|
||||
}
|
||||
|
||||
template<typename T, std::size_t Align = alignof(T), std::size_t Size = sizeof(T)>
|
||||
template <typename T, std::size_t Align = alignof(T), std::size_t Size = sizeof(T)>
|
||||
struct se_storage;
|
||||
|
||||
template<typename T, bool Se = true, std::size_t Align = alignof(T)>
|
||||
template <typename T, bool Se = true, std::size_t Align = alignof(T)>
|
||||
class se_t;
|
||||
|
||||
template<typename T, std::size_t Size = sizeof(T)>
|
||||
template <typename T, std::size_t Size = sizeof(T)>
|
||||
struct atomic_storage;
|
||||
|
||||
template<typename T1, typename T2, typename = void>
|
||||
template <typename T1, typename T2, typename = void>
|
||||
struct atomic_add;
|
||||
|
||||
template<typename T1, typename T2, typename = void>
|
||||
template <typename T1, typename T2, typename = void>
|
||||
struct atomic_sub;
|
||||
|
||||
template<typename T1, typename T2, typename = void>
|
||||
template <typename T1, typename T2, typename = void>
|
||||
struct atomic_and;
|
||||
|
||||
template<typename T1, typename T2, typename = void>
|
||||
template <typename T1, typename T2, typename = void>
|
||||
struct atomic_or;
|
||||
|
||||
template<typename T1, typename T2, typename = void>
|
||||
template <typename T1, typename T2, typename = void>
|
||||
struct atomic_xor;
|
||||
|
||||
template<typename T, typename = void>
|
||||
template <typename T, typename = void>
|
||||
struct atomic_pre_inc;
|
||||
|
||||
template<typename T, typename = void>
|
||||
template <typename T, typename = void>
|
||||
struct atomic_post_inc;
|
||||
|
||||
template<typename T, typename = void>
|
||||
template <typename T, typename = void>
|
||||
struct atomic_pre_dec;
|
||||
|
||||
template<typename T, typename = void>
|
||||
template <typename T, typename = void>
|
||||
struct atomic_post_dec;
|
||||
|
||||
template<typename T1, typename T2, typename = void>
|
||||
template <typename T1, typename T2, typename = void>
|
||||
struct atomic_test_and_set;
|
||||
|
||||
template<typename T1, typename T2, typename = void>
|
||||
template <typename T1, typename T2, typename = void>
|
||||
struct atomic_test_and_reset;
|
||||
|
||||
template<typename T1, typename T2, typename = void>
|
||||
template <typename T1, typename T2, typename = void>
|
||||
struct atomic_test_and_complement;
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
class atomic_t;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
@ -92,30 +92,32 @@ using std::void_t;
|
|||
#else
|
||||
namespace void_details
|
||||
{
|
||||
template<class... >
|
||||
template <typename...>
|
||||
struct make_void
|
||||
{
|
||||
using type = void;
|
||||
};
|
||||
}
|
||||
|
||||
template<class... T> using void_t = typename void_details::make_void<T...>::type;
|
||||
template <typename... T>
|
||||
using void_t = typename void_details::make_void<T...>::type;
|
||||
#endif
|
||||
|
||||
// Extract T::simple_type if available, remove cv qualifiers
|
||||
template<typename T, typename = void>
|
||||
template <typename T, typename = void>
|
||||
struct simple_type_helper
|
||||
{
|
||||
using type = typename std::remove_cv<T>::type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
struct simple_type_helper<T, void_t<typename T::simple_type>>
|
||||
{
|
||||
using type = typename T::simple_type;
|
||||
};
|
||||
|
||||
template<typename T> using simple_t = typename simple_type_helper<T>::type;
|
||||
template <typename T>
|
||||
using simple_t = typename simple_type_helper<T>::type;
|
||||
|
||||
// Bool type equivalent
|
||||
class b8
|
||||
|
@ -172,87 +174,87 @@ struct alignas(16) u128
|
|||
{
|
||||
}
|
||||
|
||||
friend u128 operator +(const u128& l, const u128& r)
|
||||
friend u128 operator+(const u128& l, const u128& r)
|
||||
{
|
||||
u128 value;
|
||||
_addcarry_u64(_addcarry_u64(0, r.lo, l.lo, &value.lo), r.hi, l.hi, &value.hi);
|
||||
return value;
|
||||
}
|
||||
|
||||
friend u128 operator +(const u128& l, u64 r)
|
||||
friend u128 operator+(const u128& l, u64 r)
|
||||
{
|
||||
u128 value;
|
||||
_addcarry_u64(_addcarry_u64(0, r, l.lo, &value.lo), l.hi, 0, &value.hi);
|
||||
return value;
|
||||
}
|
||||
|
||||
friend u128 operator +(u64 l, const u128& r)
|
||||
friend u128 operator+(u64 l, const u128& r)
|
||||
{
|
||||
u128 value;
|
||||
_addcarry_u64(_addcarry_u64(0, r.lo, l, &value.lo), 0, r.hi, &value.hi);
|
||||
return value;
|
||||
}
|
||||
|
||||
friend u128 operator -(const u128& l, const u128& r)
|
||||
friend u128 operator-(const u128& l, const u128& r)
|
||||
{
|
||||
u128 value;
|
||||
_subborrow_u64(_subborrow_u64(0, r.lo, l.lo, &value.lo), r.hi, l.hi, &value.hi);
|
||||
return value;
|
||||
}
|
||||
|
||||
friend u128 operator -(const u128& l, u64 r)
|
||||
friend u128 operator-(const u128& l, u64 r)
|
||||
{
|
||||
u128 value;
|
||||
_subborrow_u64(_subborrow_u64(0, r, l.lo, &value.lo), 0, l.hi, &value.hi);
|
||||
return value;
|
||||
}
|
||||
|
||||
friend u128 operator -(u64 l, const u128& r)
|
||||
friend u128 operator-(u64 l, const u128& r)
|
||||
{
|
||||
u128 value;
|
||||
_subborrow_u64(_subborrow_u64(0, r.lo, l, &value.lo), r.hi, 0, &value.hi);
|
||||
return value;
|
||||
}
|
||||
|
||||
u128 operator +() const
|
||||
u128 operator+() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
u128 operator -() const
|
||||
u128 operator-() const
|
||||
{
|
||||
u128 value;
|
||||
_subborrow_u64(_subborrow_u64(0, lo, 0, &value.lo), hi, 0, &value.hi);
|
||||
return value;
|
||||
}
|
||||
|
||||
u128& operator ++()
|
||||
u128& operator++()
|
||||
{
|
||||
_addcarry_u64(_addcarry_u64(0, 1, lo, &lo), 0, hi, &hi);
|
||||
return *this;
|
||||
}
|
||||
|
||||
u128 operator ++(int)
|
||||
u128 operator++(int)
|
||||
{
|
||||
u128 value = *this;
|
||||
_addcarry_u64(_addcarry_u64(0, 1, lo, &lo), 0, hi, &hi);
|
||||
return value;
|
||||
}
|
||||
|
||||
u128& operator --()
|
||||
u128& operator--()
|
||||
{
|
||||
_subborrow_u64(_subborrow_u64(0, 1, lo, &lo), 0, hi, &hi);
|
||||
return *this;
|
||||
}
|
||||
|
||||
u128 operator --(int)
|
||||
u128 operator--(int)
|
||||
{
|
||||
u128 value = *this;
|
||||
_subborrow_u64(_subborrow_u64(0, 1, lo, &lo), 0, hi, &hi);
|
||||
return value;
|
||||
}
|
||||
|
||||
u128 operator ~() const
|
||||
u128 operator~() const
|
||||
{
|
||||
u128 value;
|
||||
value.lo = ~lo;
|
||||
|
@ -260,7 +262,7 @@ struct alignas(16) u128
|
|||
return value;
|
||||
}
|
||||
|
||||
friend u128 operator &(const u128& l, const u128& r)
|
||||
friend u128 operator&(const u128& l, const u128& r)
|
||||
{
|
||||
u128 value;
|
||||
value.lo = l.lo & r.lo;
|
||||
|
@ -268,7 +270,7 @@ struct alignas(16) u128
|
|||
return value;
|
||||
}
|
||||
|
||||
friend u128 operator |(const u128& l, const u128& r)
|
||||
friend u128 operator|(const u128& l, const u128& r)
|
||||
{
|
||||
u128 value;
|
||||
value.lo = l.lo | r.lo;
|
||||
|
@ -276,7 +278,7 @@ struct alignas(16) u128
|
|||
return value;
|
||||
}
|
||||
|
||||
friend u128 operator ^(const u128& l, const u128& r)
|
||||
friend u128 operator^(const u128& l, const u128& r)
|
||||
{
|
||||
u128 value;
|
||||
value.lo = l.lo ^ r.lo;
|
||||
|
@ -284,33 +286,33 @@ struct alignas(16) u128
|
|||
return value;
|
||||
}
|
||||
|
||||
u128& operator +=(const u128& r)
|
||||
u128& operator+=(const u128& r)
|
||||
{
|
||||
_addcarry_u64(_addcarry_u64(0, r.lo, lo, &lo), r.hi, hi, &hi);
|
||||
return *this;
|
||||
}
|
||||
|
||||
u128& operator +=(uint64_t r)
|
||||
u128& operator+=(uint64_t r)
|
||||
{
|
||||
_addcarry_u64(_addcarry_u64(0, r, lo, &lo), 0, hi, &hi);
|
||||
return *this;
|
||||
}
|
||||
|
||||
u128& operator &=(const u128& r)
|
||||
u128& operator&=(const u128& r)
|
||||
{
|
||||
lo &= r.lo;
|
||||
hi &= r.hi;
|
||||
return *this;
|
||||
}
|
||||
|
||||
u128& operator |=(const u128& r)
|
||||
u128& operator|=(const u128& r)
|
||||
{
|
||||
lo |= r.lo;
|
||||
hi |= r.hi;
|
||||
return *this;
|
||||
}
|
||||
|
||||
u128& operator ^=(const u128& r)
|
||||
u128& operator^=(const u128& r)
|
||||
{
|
||||
lo ^= r.lo;
|
||||
hi ^= r.hi;
|
||||
|
@ -340,47 +342,8 @@ struct alignas(16) s128
|
|||
};
|
||||
#endif
|
||||
|
||||
namespace std
|
||||
{
|
||||
/* Let's hack. */
|
||||
|
||||
template<>
|
||||
struct is_integral<u128> : true_type
|
||||
{
|
||||
};
|
||||
|
||||
template<>
|
||||
struct is_integral<s128> : true_type
|
||||
{
|
||||
};
|
||||
|
||||
template<>
|
||||
struct make_unsigned<u128>
|
||||
{
|
||||
using type = u128;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct make_unsigned<s128>
|
||||
{
|
||||
using type = u128;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct make_signed<u128>
|
||||
{
|
||||
using type = s128;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct make_signed<s128>
|
||||
{
|
||||
using type = s128;
|
||||
};
|
||||
}
|
||||
|
||||
static_assert(std::is_arithmetic<u128>::value && std::is_integral<u128>::value && alignof(u128) == 16 && sizeof(u128) == 16, "Wrong u128 implementation");
|
||||
static_assert(std::is_arithmetic<s128>::value && std::is_integral<s128>::value && alignof(s128) == 16 && sizeof(s128) == 16, "Wrong s128 implementation");
|
||||
static_assert(alignof(u128) == 16 && sizeof(u128) == 16, "Wrong u128 implementation");
|
||||
static_assert(alignof(s128) == 16 && sizeof(s128) == 16, "Wrong s128 implementation");
|
||||
|
||||
union alignas(2) f16
|
||||
{
|
||||
|
@ -396,9 +359,9 @@ union alignas(2) f16
|
|||
{
|
||||
// See http://stackoverflow.com/a/26779139
|
||||
// The conversion doesn't handle NaN/Inf
|
||||
u32 raw = ((_u16 & 0x8000) << 16) | // Sign (just moved)
|
||||
(((_u16 & 0x7c00) + 0x1C000) << 13) | // Exponent ( exp - 15 + 127)
|
||||
((_u16 & 0x03FF) << 13); // Mantissa
|
||||
u32 raw = ((_u16 & 0x8000) << 16) | // Sign (just moved)
|
||||
(((_u16 & 0x7c00) + 0x1C000) << 13) | // Exponent ( exp - 15 + 127)
|
||||
((_u16 & 0x03FF) << 13); // Mantissa
|
||||
return (float&)raw;
|
||||
}
|
||||
};
|
||||
|
@ -408,13 +371,13 @@ using f64 = double;
|
|||
|
||||
struct ignore
|
||||
{
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
ignore(T)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
|
||||
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
|
||||
constexpr T align(const T& value, std::uint64_t align)
|
||||
{
|
||||
return static_cast<T>((value + (align - 1)) & ~(align - 1));
|
||||
|
@ -423,12 +386,74 @@ constexpr T align(const T& value, std::uint64_t align)
|
|||
namespace fmt
|
||||
{
|
||||
[[noreturn]] void raw_error(const char* msg);
|
||||
|
||||
[[noreturn]] void raw_verify_error(const char* msg, uint position);
|
||||
[[noreturn]] void raw_narrow_error(const char* msg, const fmt_type_info* sup, u64 arg);
|
||||
}
|
||||
|
||||
struct verify_func
|
||||
{
|
||||
template <typename T>
|
||||
bool operator()(T&& value) const
|
||||
{
|
||||
if (std::forward<T>(value))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <uint N>
|
||||
struct verify_impl
|
||||
{
|
||||
const char* cause;
|
||||
|
||||
template <typename T>
|
||||
auto operator,(T&& value) const
|
||||
{
|
||||
// Verification (can be safely disabled)
|
||||
if (!verify_func()(std::forward<T>(value)))
|
||||
{
|
||||
fmt::raw_verify_error(cause, N);
|
||||
}
|
||||
|
||||
return verify_impl<N + 1>{cause};
|
||||
}
|
||||
};
|
||||
|
||||
// Verification helper, checks several conditions delimited with comma operator
|
||||
inline auto verify(const char* cause)
|
||||
{
|
||||
return verify_impl<0>{cause};
|
||||
}
|
||||
|
||||
// Verification helper (returns value or lvalue reference, may require to use verify_move instead)
|
||||
template <typename F = verify_func, typename T>
|
||||
inline T verify(T&& value, const char* cause, F&& func = F())
|
||||
{
|
||||
if (!func(std::forward<T>(value)))
|
||||
{
|
||||
fmt::raw_verify_error(cause, 0);
|
||||
}
|
||||
|
||||
return std::forward<T>(value);
|
||||
}
|
||||
|
||||
// Verification helper (must be used in return expression or in place of std::move)
|
||||
template <typename F = verify_func, typename T>
|
||||
inline std::remove_reference_t<T>&& verify_move(T&& value, const char* cause, F&& func = F())
|
||||
{
|
||||
if (!func(std::forward<T>(value)))
|
||||
{
|
||||
fmt::raw_verify_error(cause, 0);
|
||||
}
|
||||
|
||||
return std::move(value);
|
||||
}
|
||||
|
||||
// Narrow cast (throws on failure)
|
||||
template<typename To = void, typename From, typename = decltype(static_cast<To>(std::declval<From>()))>
|
||||
template <typename To = void, typename From, typename = decltype(static_cast<To>(std::declval<From>()))>
|
||||
inline To narrow(const From& value, const char* msg = nullptr)
|
||||
{
|
||||
// Allow "narrowing to void" and ensure it always fails in this case
|
||||
|
@ -443,32 +468,32 @@ inline To narrow(const From& value, const char* msg = nullptr)
|
|||
}
|
||||
|
||||
// Returns u32 size() for container
|
||||
template<typename CT, typename = decltype(static_cast<u32>(std::declval<CT>().size()))>
|
||||
template <typename CT, typename = decltype(static_cast<u32>(std::declval<CT>().size()))>
|
||||
inline u32 size32(const CT& container, const char* msg = nullptr)
|
||||
{
|
||||
return narrow<u32>(container.size(), msg);
|
||||
}
|
||||
|
||||
// Returns u32 size for an array
|
||||
template<typename T, std::size_t Size>
|
||||
constexpr u32 size32(const T(&)[Size], const char* msg = nullptr)
|
||||
template <typename T, std::size_t Size>
|
||||
constexpr u32 size32(const T (&)[Size], const char* msg = nullptr)
|
||||
{
|
||||
return static_cast<u32>(Size);
|
||||
}
|
||||
|
||||
template<typename T1, typename = std::enable_if_t<std::is_integral<T1>::value>>
|
||||
template <typename T1, typename = std::enable_if_t<std::is_integral<T1>::value>>
|
||||
constexpr bool test(const T1& value)
|
||||
{
|
||||
return value != 0;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2, typename = std::enable_if_t<std::is_integral<T1>::value && std::is_integral<T2>::value>>
|
||||
template <typename T1, typename T2, typename = std::enable_if_t<std::is_integral<T1>::value && std::is_integral<T2>::value>>
|
||||
constexpr bool test(const T1& lhs, const T2& rhs)
|
||||
{
|
||||
return (lhs & rhs) != 0;
|
||||
}
|
||||
|
||||
template<typename T, typename T2, typename = std::enable_if_t<std::is_integral<T>::value && std::is_integral<T2>::value>>
|
||||
template <typename T, typename T2, typename = std::enable_if_t<std::is_integral<T>::value && std::is_integral<T2>::value>>
|
||||
inline bool test_and_set(T& lhs, const T2& rhs)
|
||||
{
|
||||
const bool result = (lhs & rhs) != 0;
|
||||
|
@ -476,7 +501,7 @@ inline bool test_and_set(T& lhs, const T2& rhs)
|
|||
return result;
|
||||
}
|
||||
|
||||
template<typename T, typename T2, typename = std::enable_if_t<std::is_integral<T>::value && std::is_integral<T2>::value>>
|
||||
template <typename T, typename T2, typename = std::enable_if_t<std::is_integral<T>::value && std::is_integral<T2>::value>>
|
||||
inline bool test_and_reset(T& lhs, const T2& rhs)
|
||||
{
|
||||
const bool result = (lhs & rhs) != 0;
|
||||
|
@ -484,7 +509,7 @@ inline bool test_and_reset(T& lhs, const T2& rhs)
|
|||
return result;
|
||||
}
|
||||
|
||||
template<typename T, typename T2, typename = std::enable_if_t<std::is_integral<T>::value && std::is_integral<T2>::value>>
|
||||
template <typename T, typename T2, typename = std::enable_if_t<std::is_integral<T>::value && std::is_integral<T2>::value>>
|
||||
inline bool test_and_complement(T& lhs, const T2& rhs)
|
||||
{
|
||||
const bool result = (lhs & rhs) != 0;
|
||||
|
@ -493,7 +518,7 @@ inline bool test_and_complement(T& lhs, const T2& rhs)
|
|||
}
|
||||
|
||||
// Simplified hash algorithm for pointers. May be used in std::unordered_(map|set).
|
||||
template<typename T, std::size_t Align = alignof(T)>
|
||||
template <typename T, std::size_t Align = alignof(T)>
|
||||
struct pointer_hash
|
||||
{
|
||||
std::size_t operator()(T* ptr) const
|
||||
|
@ -502,7 +527,7 @@ struct pointer_hash
|
|||
}
|
||||
};
|
||||
|
||||
template<typename T, std::size_t Shift = 0>
|
||||
template <typename T, std::size_t Shift = 0>
|
||||
struct value_hash
|
||||
{
|
||||
std::size_t operator()(T value) const
|
||||
|
@ -513,26 +538,26 @@ struct value_hash
|
|||
|
||||
// Contains value of any POD type with fixed size and alignment. TT<> is the type converter applied.
|
||||
// For example, `simple_t` may be used to remove endianness.
|
||||
template<template<typename> class TT, std::size_t S, std::size_t A = S>
|
||||
template <template <typename> class TT, std::size_t S, std::size_t A = S>
|
||||
struct alignas(A) any_pod
|
||||
{
|
||||
std::aligned_storage_t<S, A> data;
|
||||
|
||||
any_pod() = default;
|
||||
|
||||
template<typename T, typename T2 = TT<T>, typename = std::enable_if_t<std::is_pod<T2>::value && sizeof(T2) == S && alignof(T2) <= A>>
|
||||
template <typename T, typename T2 = TT<T>, typename = std::enable_if_t<std::is_pod<T2>::value && sizeof(T2) == S && alignof(T2) <= A>>
|
||||
any_pod(const T& value)
|
||||
{
|
||||
reinterpret_cast<T2&>(data) = value;
|
||||
}
|
||||
|
||||
template<typename T, typename T2 = TT<T>, typename = std::enable_if_t<std::is_pod<T2>::value && sizeof(T2) == S && alignof(T2) <= A>>
|
||||
template <typename T, typename T2 = TT<T>, typename = std::enable_if_t<std::is_pod<T2>::value && sizeof(T2) == S && alignof(T2) <= A>>
|
||||
T2& as()
|
||||
{
|
||||
return reinterpret_cast<T2&>(data);
|
||||
}
|
||||
|
||||
template<typename T, typename T2 = TT<T>, typename = std::enable_if_t<std::is_pod<T2>::value && sizeof(T2) == S && alignof(T2) <= A>>
|
||||
template <typename T, typename T2 = TT<T>, typename = std::enable_if_t<std::is_pod<T2>::value && sizeof(T2) == S && alignof(T2) <= A>>
|
||||
const T2& as() const
|
||||
{
|
||||
return reinterpret_cast<const T2&>(data);
|
||||
|
@ -553,13 +578,13 @@ struct cmd64 : any64
|
|||
|
||||
cmd64() = default;
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
cmd64(const T& value)
|
||||
: any64(value)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
template <typename T1, typename T2>
|
||||
cmd64(const T1& arg1, const T2& arg2)
|
||||
: any64(pair_t{arg1, arg2})
|
||||
{
|
||||
|
@ -572,25 +597,25 @@ struct cmd64 : any64
|
|||
|
||||
// TODO: compatibility with std::pair/std::tuple?
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
decltype(auto) arg1()
|
||||
{
|
||||
return as<pair_t>().arg1.as<T>();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
decltype(auto) arg1() const
|
||||
{
|
||||
return as<const pair_t>().arg1.as<const T>();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
decltype(auto) arg2()
|
||||
{
|
||||
return as<pair_t>().arg2.as<T>();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
decltype(auto) arg2() const
|
||||
{
|
||||
return as<const pair_t>().arg2.as<const T>();
|
||||
|
@ -600,7 +625,7 @@ struct cmd64 : any64
|
|||
static_assert(sizeof(cmd64) == 8 && std::is_pod<cmd64>::value, "Incorrect cmd64 type");
|
||||
|
||||
// Allows to define integer convertible to multiple types
|
||||
template<typename T, T Value, typename T1 = void, typename... Ts>
|
||||
template <typename T, T Value, typename T1 = void, typename... Ts>
|
||||
struct multicast : multicast<T, Value, Ts...>
|
||||
{
|
||||
constexpr multicast() = default;
|
||||
|
@ -613,11 +638,11 @@ struct multicast : multicast<T, Value, Ts...>
|
|||
};
|
||||
|
||||
// Recursion terminator
|
||||
template<typename T, T Value>
|
||||
template <typename T, T Value>
|
||||
struct multicast<T, Value, void>
|
||||
{
|
||||
constexpr multicast() = default;
|
||||
|
||||
|
||||
// Explicit conversion to base type
|
||||
explicit constexpr operator T() const
|
||||
{
|
||||
|
@ -626,23 +651,25 @@ struct multicast<T, Value, void>
|
|||
};
|
||||
|
||||
// Tagged ID type
|
||||
template<typename T = void, typename ID = u32>
|
||||
template <typename T = void, typename ID = u32>
|
||||
class id_value
|
||||
{
|
||||
// Initial value
|
||||
mutable ID m_value{ static_cast<ID>(-1) };
|
||||
mutable ID m_value{static_cast<ID>(-1)};
|
||||
|
||||
// Allow access for ID manager
|
||||
friend class idm;
|
||||
|
||||
// Update ID
|
||||
void operator =(const ID& value) const
|
||||
void operator=(const ID& value) const
|
||||
{
|
||||
m_value = value;
|
||||
}
|
||||
|
||||
public:
|
||||
constexpr id_value() {}
|
||||
constexpr id_value()
|
||||
{
|
||||
}
|
||||
|
||||
// Get the value
|
||||
operator ID() const
|
||||
|
@ -651,7 +678,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
template<typename T, typename ID>
|
||||
template <typename T, typename ID>
|
||||
struct fmt_unveil<id_value<T, ID>>
|
||||
{
|
||||
using type = typename fmt_unveil<ID>::type;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue