瀏覽代碼

Added MakeSignedT and MakeUnsignedT to type traits.

Бранимир Караџић 1 年之前
父節點
當前提交
6cddfa90f3
共有 5 個文件被更改,包括 158 次插入14 次删除
  1. 6 0
      README.md
  2. 52 0
      include/bx/inline/typetraits.inl
  3. 8 0
      include/bx/typetraits.h
  4. 3 14
      src/dtoa.cpp
  5. 89 0
      tests/typetraits_test.cpp

+ 6 - 0
README.md

@@ -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)
 [![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)
 [![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
 Contact
 -------
 -------
 
 

+ 52 - 0
include/bx/inline/typetraits.inl

@@ -464,6 +464,58 @@ namespace bx
 		return IsUnsignedT<Ty>::value;
 		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<typename Ty> struct IsIntegerT                     : FalseConstant {};
 	template<>            struct IsIntegerT<bool              > :  TrueConstant {};
 	template<>            struct IsIntegerT<bool              > :  TrueConstant {};

+ 8 - 0
include/bx/typetraits.h

@@ -165,6 +165,14 @@ namespace bx
 	template<typename Ty>
 	template<typename Ty>
 	constexpr bool isUnsigned();
 	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.
 	/// Returns true if type `Ty` is integer type, otherwise returns false.
 	template<typename Ty>
 	template<typename Ty>
 	constexpr bool isInteger();
 	constexpr bool isInteger();

+ 3 - 14
src/dtoa.cpp

@@ -8,8 +8,6 @@
 #include <bx/string.h>
 #include <bx/string.h>
 #include <bx/uint32_t.h>
 #include <bx/uint32_t.h>
 
 
-#include <type_traits>
-
 namespace bx
 namespace bx
 {
 {
 	/*
 	/*
@@ -481,12 +479,8 @@ namespace bx
 				return 0;
 				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)
 			if (_max == 0)
 			{
 			{
 				return 0;
 				return 0;
@@ -496,12 +490,7 @@ namespace bx
 			return int32_t(_max + 1);
 			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)
 	int32_t toString(char* _dst, int32_t _max, int32_t _value, uint32_t _base, char _separator)

+ 89 - 0
tests/typetraits_test.cpp

@@ -299,6 +299,95 @@ TEST_CASE("type-traits isUnsigned", "")
 	STATIC_REQUIRE(!bx::isUnsigned<long double            >() );
 	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", "")
 TEST_CASE("type-traits isInteger", "")
 {
 {
 	STATIC_REQUIRE( bx::isInteger<bool                   >() );
 	STATIC_REQUIRE( bx::isInteger<bool                   >() );