Added MakeSignedT and MakeUnsignedT to type traits.

This commit is contained in:
Бранимир Караџић
2024-05-03 14:44:57 -07:00
parent b95012f14b
commit 6cddfa90f3
5 changed files with 158 additions and 14 deletions

View File

@@ -6,6 +6,12 @@ Base X-platform library.
[![License](https://img.shields.io/badge/license-BSD--2%20clause-blue.svg)](https://bkaradzic.github.io/bgfx/license.html)
[![Join the chat at https://discord.gg/9eMbv7J](https://img.shields.io/discord/712512073522872352?color=%237289DA&label=bx&logo=discord&logoColor=white)](https://discord.gg/9eMbv7J)
Goals:
- Provide OS/runtime/compiler independent core functionality to be able to
write cross-platform applications.
- Compile without C Runtime (CRT) and without C++ Standard Library (STL).
Contact
-------

View File

@@ -464,6 +464,58 @@ namespace bx
return IsUnsignedT<Ty>::value;
}
//---
template<typename Ty> struct MakeSignedT { using Type = Ty; };
template<typename Ty> using MakeSignedType = typename MakeSignedT<Ty>::Type;
template<typename Ty> struct MakeSignedT<const Ty> : AddConstType <MakeSignedType<Ty>> {};
template<typename Ty> struct MakeSignedT<volatile Ty> : AddVolatileType<MakeSignedType<Ty>> {};
template<typename Ty> struct MakeSignedT<const volatile Ty> : AddCvType <MakeSignedType<Ty>> {};
template<> struct MakeSignedT< char > { using Type = signed char; };
template<> struct MakeSignedT< signed char > { using Type = signed char; };
template<> struct MakeSignedT<unsigned char > { using Type = signed char; };
template<> struct MakeSignedT< short > { using Type = signed short; };
template<> struct MakeSignedT<unsigned short > { using Type = signed short; };
template<> struct MakeSignedT< int > { using Type = signed int; };
template<> struct MakeSignedT<unsigned int > { using Type = signed int; };
template<> struct MakeSignedT< long > { using Type = signed long; };
template<> struct MakeSignedT<unsigned long > { using Type = signed long; };
template<> struct MakeSignedT< long long> { using Type = signed long long; };
template<> struct MakeSignedT<unsigned long long> { using Type = signed long long; };
template<typename Ty>
inline constexpr auto asSigned(Ty _t)
{
return MakeSignedType<Ty>(_t);
}
//---
template<typename Ty> struct MakeUnsignedT { using Type = Ty; };
template<typename Ty> using MakeUnsignedType = typename MakeUnsignedT<Ty>::Type;
template<typename Ty> struct MakeUnsignedT<const Ty> : AddConstType <MakeUnsignedType<Ty>> {};
template<typename Ty> struct MakeUnsignedT<volatile Ty> : AddVolatileType<MakeUnsignedType<Ty>> {};
template<typename Ty> struct MakeUnsignedT<const volatile Ty> : AddCvType <MakeUnsignedType<Ty>> {};
template<> struct MakeUnsignedT< char > { using Type = unsigned char; };
template<> struct MakeUnsignedT< signed char > { using Type = unsigned char; };
template<> struct MakeUnsignedT<unsigned char > { using Type = unsigned char; };
template<> struct MakeUnsignedT< short > { using Type = unsigned short; };
template<> struct MakeUnsignedT<unsigned short > { using Type = unsigned short; };
template<> struct MakeUnsignedT< int > { using Type = unsigned int; };
template<> struct MakeUnsignedT<unsigned int > { using Type = unsigned int; };
template<> struct MakeUnsignedT< long > { using Type = unsigned long; };
template<> struct MakeUnsignedT<unsigned long > { using Type = unsigned long; };
template<> struct MakeUnsignedT< long long> { using Type = unsigned long long; };
template<> struct MakeUnsignedT<unsigned long long> { using Type = unsigned long long; };
template<typename Ty>
inline constexpr auto asUnsigned(Ty _t)
{
return MakeUnsignedType<Ty>(_t);
}
//---
template<typename Ty> struct IsIntegerT : FalseConstant {};
template<> struct IsIntegerT<bool > : TrueConstant {};

View File

@@ -165,6 +165,14 @@ namespace bx
template<typename Ty>
constexpr bool isUnsigned();
/// Returns value of `_t` as signed type value.
template<typename Ty>
constexpr auto asSigned(Ty _t);
/// Returns value of `_t` as unsigned type value.
template<typename Ty>
constexpr auto asUnsigned(Ty _t);
/// Returns true if type `Ty` is integer type, otherwise returns false.
template<typename Ty>
constexpr bool isInteger();

View File

@@ -8,8 +8,6 @@
#include <bx/string.h>
#include <bx/uint32_t.h>
#include <type_traits>
namespace bx
{
/*
@@ -481,12 +479,8 @@ namespace bx
return 0;
}
_max = toString(_dst + 1
, _max - 1
, typename std::make_unsigned<Ty>::type(-_value)
, _base
, _separator
);
_max = toString(_dst + 1, _max - 1, asUnsigned(-_value), _base, _separator);
if (_max == 0)
{
return 0;
@@ -496,12 +490,7 @@ namespace bx
return int32_t(_max + 1);
}
return toString(_dst
, _max
, typename std::make_unsigned<Ty>::type(_value)
, _base
, _separator
);
return toString(_dst, _max, asUnsigned(_value), _base, _separator);
}
int32_t toString(char* _dst, int32_t _max, int32_t _value, uint32_t _base, char _separator)

View File

@@ -299,6 +299,95 @@ TEST_CASE("type-traits isUnsigned", "")
STATIC_REQUIRE(!bx::isUnsigned<long double >() );
}
TEST_CASE("type-traits MakeSignedT", "")
{
STATIC_REQUIRE(bx::isSigned<bx::MakeSignedT<char >::Type >() );
STATIC_REQUIRE(bx::isSigned<bx::MakeSignedT<signed char >::Type >() );
STATIC_REQUIRE(bx::isSigned<bx::MakeSignedT<unsigned char >::Type >() );
STATIC_REQUIRE(bx::isSigned<bx::MakeSignedT<short >::Type >() );
STATIC_REQUIRE(bx::isSigned<bx::MakeSignedT<unsigned short >::Type >() );
STATIC_REQUIRE(bx::isSigned<bx::MakeSignedT<int >::Type >() );
STATIC_REQUIRE(bx::isSigned<bx::MakeSignedT<unsigned int >::Type >() );
STATIC_REQUIRE(bx::isSigned<bx::MakeSignedT<long >::Type >() );
STATIC_REQUIRE(bx::isSigned<bx::MakeSignedT<unsigned long >::Type >() );
STATIC_REQUIRE(bx::isSigned<bx::MakeSignedT<long long >::Type >() );
STATIC_REQUIRE(bx::isSigned<bx::MakeSignedT<unsigned long long >::Type >() );
STATIC_REQUIRE(bx::isSigned<bx::MakeSignedT<long long int >::Type >() );
STATIC_REQUIRE(bx::isSigned<bx::MakeSignedT<unsigned long long int >::Type >() );
STATIC_REQUIRE(bx::isSigned<bx::MakeSignedT<int8_t >::Type >() );
STATIC_REQUIRE(bx::isSigned<bx::MakeSignedT<uint8_t >::Type >() );
STATIC_REQUIRE(bx::isSigned<bx::MakeSignedT<int16_t >::Type >() );
STATIC_REQUIRE(bx::isSigned<bx::MakeSignedT<uint16_t >::Type >() );
STATIC_REQUIRE(bx::isSigned<bx::MakeSignedT<int32_t >::Type >() );
STATIC_REQUIRE(bx::isSigned<bx::MakeSignedT<uint32_t >::Type >() );
STATIC_REQUIRE(bx::isSigned<bx::MakeSignedT<int64_t >::Type >() );
STATIC_REQUIRE(bx::isSigned<bx::MakeSignedT<uint64_t >::Type >() );
STATIC_REQUIRE(bx::isSigned<bx::MakeSignedT<intmax_t >::Type >() );
STATIC_REQUIRE(bx::isSigned<bx::MakeSignedT<uintmax_t >::Type >() );
STATIC_REQUIRE(bx::isSigned<bx::MakeSignedT<uintptr_t >::Type >() );
STATIC_REQUIRE(bx::isSigned<bx::MakeSignedT<ptrdiff_t >::Type >() );
STATIC_REQUIRE(bx::isSigned<bx::MakeSignedT<size_t >::Type >() );
STATIC_REQUIRE(bx::isSigned<bx::MakeSignedT<float >::Type >() );
STATIC_REQUIRE(bx::isSigned<bx::MakeSignedT<double >::Type >() );
STATIC_REQUIRE(bx::isSigned<bx::MakeSignedT<long double >::Type >() );
enum struct E : unsigned short {};
using char_type = std::make_signed_t<unsigned char>;
using int_type = std::make_signed_t<unsigned int>;
using long_type = std::make_signed_t<volatile unsigned long>;
using enum_type = std::make_signed_t<E>;
STATIC_REQUIRE(true
&& bx::isSame<char_type, signed char>()
&& bx::isSame<int_type, signed int>()
&& bx::isSame<long_type, volatile signed long>()
&& bx::isSame<enum_type, signed short>()
);
}
TEST_CASE("type-traits MakeUnsignedT", "")
{
STATIC_REQUIRE(bx::isUnsigned<bx::MakeUnsignedT<char >::Type >() );
STATIC_REQUIRE(bx::isUnsigned<bx::MakeUnsignedT<signed char >::Type >() );
STATIC_REQUIRE(bx::isUnsigned<bx::MakeUnsignedT<unsigned char >::Type >() );
STATIC_REQUIRE(bx::isUnsigned<bx::MakeUnsignedT<short >::Type >() );
STATIC_REQUIRE(bx::isUnsigned<bx::MakeUnsignedT<unsigned short >::Type >() );
STATIC_REQUIRE(bx::isUnsigned<bx::MakeUnsignedT<int >::Type >() );
STATIC_REQUIRE(bx::isUnsigned<bx::MakeUnsignedT<unsigned int >::Type >() );
STATIC_REQUIRE(bx::isUnsigned<bx::MakeUnsignedT<long >::Type >() );
STATIC_REQUIRE(bx::isUnsigned<bx::MakeUnsignedT<unsigned long >::Type >() );
STATIC_REQUIRE(bx::isUnsigned<bx::MakeUnsignedT<long long >::Type >() );
STATIC_REQUIRE(bx::isUnsigned<bx::MakeUnsignedT<unsigned long long >::Type >() );
STATIC_REQUIRE(bx::isUnsigned<bx::MakeUnsignedT<long long int >::Type >() );
STATIC_REQUIRE(bx::isUnsigned<bx::MakeUnsignedT<unsigned long long int >::Type >() );
STATIC_REQUIRE(bx::isUnsigned<bx::MakeUnsignedT<int8_t >::Type >() );
STATIC_REQUIRE(bx::isUnsigned<bx::MakeUnsignedT<uint8_t >::Type >() );
STATIC_REQUIRE(bx::isUnsigned<bx::MakeUnsignedT<int16_t >::Type >() );
STATIC_REQUIRE(bx::isUnsigned<bx::MakeUnsignedT<uint16_t >::Type >() );
STATIC_REQUIRE(bx::isUnsigned<bx::MakeUnsignedT<int32_t >::Type >() );
STATIC_REQUIRE(bx::isUnsigned<bx::MakeUnsignedT<uint32_t >::Type >() );
STATIC_REQUIRE(bx::isUnsigned<bx::MakeUnsignedT<int64_t >::Type >() );
STATIC_REQUIRE(bx::isUnsigned<bx::MakeUnsignedT<uint64_t >::Type >() );
STATIC_REQUIRE(bx::isUnsigned<bx::MakeUnsignedT<intmax_t >::Type >() );
STATIC_REQUIRE(bx::isUnsigned<bx::MakeUnsignedT<uintmax_t >::Type >() );
STATIC_REQUIRE(bx::isUnsigned<bx::MakeUnsignedT<uintptr_t >::Type >() );
STATIC_REQUIRE(bx::isUnsigned<bx::MakeUnsignedT<ptrdiff_t >::Type >() );
STATIC_REQUIRE(bx::isUnsigned<bx::MakeUnsignedT<size_t >::Type >() );
using uchar_type = std::make_unsigned_t<char>;
using uint_type = std::make_unsigned_t<int>;
using ulong_type = std::make_unsigned_t<volatile long>;
STATIC_REQUIRE(true
&& bx::isSame<uchar_type, unsigned char>()
&& bx::isSame<uint_type, unsigned int>()
&& bx::isSame<ulong_type, volatile unsigned long>()
);
}
TEST_CASE("type-traits isInteger", "")
{
STATIC_REQUIRE( bx::isInteger<bool >() );