Added typetraits.h

This commit is contained in:
Бранимир Караџић
2022-08-31 21:29:57 -07:00
parent 70239c9fee
commit 274771cb46
5 changed files with 1401 additions and 21 deletions

View File

@@ -17,6 +17,7 @@
#include "constants.h"
#include "macros.h"
#include "debug.h"
#include "typetraits.h"
///
#define BX_COUNTOF(_x) sizeof(bx::CountOfRequireArrayArgumentT(_x) )
@@ -37,14 +38,6 @@
namespace bx
{
/// Returns true if type `Ty` is trivially copyable / POD type.
template<typename Ty>
constexpr bool isTriviallyCopyable();
/// Returns true if type `Ty` is signed type.
template<typename Ty>
constexpr bool isSigned();
/// Arithmetic type `Ty` limits.
template<typename Ty, bool SignT = isSigned<Ty>()>
struct LimitsT;

View File

@@ -27,18 +27,6 @@ namespace bx
return _x;
}
template<typename Ty>
inline constexpr bool isTriviallyCopyable()
{
return __is_trivially_copyable(Ty);
}
template<typename Ty>
constexpr bool isSigned()
{
return Ty(-1) < Ty(0);
}
template<typename Ty>
inline Ty* addressOf(Ty& _a)
{
@@ -74,7 +62,7 @@ namespace bx
template<typename Ty>
inline void swap(Ty& _a, Ty& _b)
{
Ty tmp = _a; _a = _b; _b = tmp;
Ty tmp = move(_a); _a = move(_b); _b = move(tmp);
}
template<typename Ty>

View File

@@ -0,0 +1,462 @@
/*
* Copyright 2010-2022 Branimir Karadzic. All rights reserved.
* License: https://github.com/bkaradzic/bx/blob/master/LICENSE
*/
#ifndef BX_TYPETRAITS_H_HEADER_GUARD
# error "Must be included from bx/typetraits.h!"
#endif // BX_TYPETRAITS_H_HEADER_GUARD
namespace bx
{
// Reference(s):
//
// - GCC type traits compiler intrisics
// https://gcc.gnu.org/onlinedocs/gcc-11.1.0/gcc/Type-Traits.html
//
// - Clang type trait primitives
// https://clang.llvm.org/docs/LanguageExtensions.html#type-trait-primitives
//---
template<typename Ty, Ty ValueT>
struct IntegralConstantT
{
using ValueType = Ty;
static constexpr Ty value = ValueT;
};
template<bool BoolT>
using BoolConstantT = IntegralConstantT<bool, BoolT>;
using FalseConstant = BoolConstantT<false>;
using TrueConstant = BoolConstantT<true >;
//---
template<typename Ty> struct TypeIdentityT { using Type = Ty; };
template<typename Ty> using TypeIdentityType = typename TypeIdentityT<Ty>::Type;
//---
template<bool BoolT, typename Ty, typename Uy> struct ConditionalT { using type = Ty; };
template< typename Ty, typename Uy> struct ConditionalT<false, Ty, Uy> { using type = Uy; };
template<bool BoolT, typename Ty, typename Uy> using ConditionalType = typename ConditionalT<BoolT, Ty, Uy>::Type;
//---
template<bool BoolT, typename Ty = void> struct EnableIfT { };
template< typename Ty > struct EnableIfT<true, Ty> { using type = Ty; };
template<bool BoolT, typename Ty > using EnableIfType = typename EnableIfT<BoolT, Ty>::Type;
//---
template<typename Ty> struct AddLvalueReferenceT { using Type = Ty&; };
template<typename Ty> struct AddLvalueReferenceT<Ty&> { using Type = Ty&; };
template<> struct AddLvalueReferenceT< void> { using Type = void; };
template<> struct AddLvalueReferenceT<const void> { using Type = const void; };
template<> struct AddLvalueReferenceT<volatile void> { using Type = volatile void; };
template<> struct AddLvalueReferenceT<const volatile void> { using Type = const volatile void; };
template<typename Ty> using AddLvalueReferenceType = typename AddLvalueReferenceT<Ty>::Type;
//---
template<typename Ty> struct AddRvalueReferenceT { using Type = Ty&&; };
template<typename Ty> struct AddRvalueReferenceT<Ty&> { using Type = Ty&; };
template<> struct AddRvalueReferenceT< void> { using Type = void; };
template<> struct AddRvalueReferenceT<const void> { using Type = const void; };
template<> struct AddRvalueReferenceT<volatile void> { using Type = volatile void; };
template<> struct AddRvalueReferenceT<const volatile void> { using Type = const volatile void; };
template<typename Ty> using AddRvalueReferenceType = typename AddRvalueReferenceT<Ty>::Type;
//---
template<typename Ty> struct RemoveReferenceT { using Type = Ty; };
template<typename Ty> struct RemoveReferenceT<Ty&> { using Type = Ty; };
template<typename Ty> struct RemoveReferenceT<Ty&&> { using Type = Ty; };
template<typename Ty> using RemoveReferenceType = typename RemoveReferenceT<Ty>::Type;
//---
template<typename Ty> struct AddPointerT { using Type = TypeIdentityType<RemoveReferenceType<Ty>*>; };
template<typename Ty> using AddPointerType = typename AddPointerT<Ty>::Type;
//---
template<typename Ty> struct RemovePointerT { using Type = Ty; };
template<typename Ty> struct RemovePointerT< Ty* > { using Type = Ty; };
template<typename Ty> struct RemovePointerT< const Ty* > { using Type = Ty; };
template<typename Ty> struct RemovePointerT< volatile Ty* > { using Type = Ty; };
template<typename Ty> struct RemovePointerT<const volatile Ty* > { using Type = Ty; };
template<typename Ty> struct RemovePointerT<const volatile Ty* const > { using Type = Ty; };
template<typename Ty> struct RemovePointerT< Ty* const > { using Type = Ty; };
template<typename Ty> struct RemovePointerT< Ty* volatile> { using Type = Ty; };
template<typename Ty> struct RemovePointerT< Ty* const volatile> { using Type = Ty; };
template<typename Ty> using RemovePointerType = typename RemovePointerT<Ty>::Type;
//---
template<typename Ty> struct AddCvT { using Type = const volatile Ty; };
template<typename Ty> using AddCvType = typename AddCvT<Ty>::Type;
//---
template<typename Ty> struct RemoveCvT { using Type = Ty; };
template<typename Ty> struct RemoveCvT<const Ty> { using Type = Ty; };
template<typename Ty> struct RemoveCvT<volatile Ty> { using Type = Ty; };
template<typename Ty> struct RemoveCvT<const volatile Ty> { using Type = Ty; };
template<typename Ty> using RemoveCvType = typename RemoveCvT<Ty>::Type;
//---
template<typename Ty> struct AddConstT { using Type = const Ty; };
template<typename Ty> using AddConstType = typename AddConstT<Ty>::Type;
//---
template<typename Ty> struct RemoveConstT { using Type = Ty; };
template<typename Ty> struct RemoveConstT<const Ty> { using Type = Ty; };
template<typename Ty> using RemoveConstType = typename RemoveConstT<Ty>::Type;
//---
template<typename Ty> struct AddVolatileT { using Type = volatile Ty; };
template<typename Ty> using AddVolatileType = typename AddVolatileT<Ty>::Type;
//---
template<typename Ty> struct RemoveVolatileT { using Type = Ty; };
template<typename Ty> struct RemoveVolatileT<volatile Ty> { using Type = Ty; };
template<typename Ty> using RemoveVolatileType = typename RemoveVolatileT<Ty>::Type;
//---
template<typename Ty> struct IsBoundedArrayT : FalseConstant {};
template<typename Ty, size_t SizeT> struct IsBoundedArrayT<Ty[SizeT]> : TrueConstant {};
template<typename Ty>
inline constexpr bool isBoundedArray()
{
return IsBoundedArrayT<Ty>::value;
}
template<typename Ty> struct IsUnboundedArrayT : FalseConstant {};
template<typename Ty> struct IsUnboundedArrayT<Ty[]> : TrueConstant {};
template<typename Ty>
inline constexpr bool isUnboundedArray()
{
return IsUnboundedArrayT<Ty>::value;
}
template<typename Ty>
inline constexpr bool isArray()
{
return isBoundedArray<Ty>()
|| isUnboundedArray<Ty>()
;
}
template<typename Ty>
constexpr bool isEnum()
{
return __is_enum(Ty);
}
template<typename Ty>
inline constexpr bool isUnion()
{
return __is_union(Ty);
}
template<typename Ty>
inline constexpr bool isAbstract()
{
return __is_abstract(Ty);
}
template<typename Ty>
inline constexpr bool isAggregate()
{
return __is_aggregate(Ty);
}
template<typename BaseT, typename DerivedT>
inline constexpr bool isBaseOf()
{
return __is_base_of(BaseT, DerivedT);
}
template<typename Ty>
inline constexpr bool isPolymorphic()
{
return __is_polymorphic(Ty);
}
template<typename Ty>
inline constexpr bool isDestructorVirtual()
{
return __has_virtual_destructor(Ty);
}
template<typename Ty>
inline constexpr bool isClass()
{
return __is_class(Ty);
}
template<typename Ty>
inline constexpr bool isFinal()
{
return __is_final(Ty);
}
template<typename Ty>
inline constexpr bool isEmpty()
{
return __is_empty(Ty);
}
template<typename Ty>
inline constexpr bool isStandardLayout()
{
return __is_standard_layout(Ty);
}
template<typename Ty>
inline constexpr bool isTrivial()
{
return __is_trivial(Ty);
}
template<typename Ty>
inline constexpr bool isPod()
{
return isStandardLayout<Ty>()
&& isTrivial<Ty>()
;
}
template<typename Ty, typename FromT>
inline constexpr bool isAssignable()
{
return __is_assignable(Ty, FromT);
}
template<typename Ty>
inline constexpr bool isCopyAssignable()
{
return isAssignable<
AddLvalueReferenceType<Ty>
, AddLvalueReferenceType<const Ty>
>();
}
template<typename Ty>
inline constexpr bool isMoveAssignable()
{
return isAssignable<
AddLvalueReferenceType<Ty>
, AddRvalueReferenceType<Ty>
>();
}
template<typename Ty, typename FromT>
inline constexpr bool isTriviallyAssignable()
{
return __is_trivially_assignable(Ty, FromT);
}
template<typename Ty>
inline constexpr bool isTriviallyCopyAssignable()
{
return isTriviallyAssignable<
AddLvalueReferenceType<Ty>
, AddRvalueReferenceType<const Ty>
>();
}
template<typename Ty>
inline constexpr bool isTriviallyMoveAssignable()
{
return isTriviallyAssignable<
AddLvalueReferenceType<Ty>
, AddRvalueReferenceType<Ty>
>();
}
template<typename Ty, typename... ArgsT>
inline constexpr bool isConstructible()
{
return __is_constructible(Ty, ArgsT...);
}
template<typename Ty>
inline constexpr bool isCopyConstructible()
{
return isConstructible<Ty, AddLvalueReferenceType<Ty>>();
}
template<typename Ty>
inline constexpr bool isMoveConstructible()
{
return isConstructible<Ty>();
}
template<typename Ty, typename... ArgsT>
inline constexpr bool isTriviallyConstructible()
{
return __is_trivially_constructible(Ty, ArgsT...);
}
template<typename Ty>
inline constexpr bool isTriviallyCopyConstructible()
{
return isTriviallyConstructible<Ty, AddLvalueReferenceType<Ty>>();
}
template<typename Ty>
inline constexpr bool isTriviallyMoveConstructible()
{
return isTriviallyConstructible<Ty, AddRvalueReferenceType<Ty>>();
}
template<typename Ty>
inline constexpr bool isTriviallyCopyable()
{
return __is_trivially_copyable(Ty);
}
template<typename Ty>
inline constexpr bool isTriviallyDestructible()
{
#if BX_COMPILER_GCC
return __has_trivial_destructor(Ty);
#else
return __is_trivially_destructible(Ty);
#endif // BX_COMPILER_GCC
}
template<typename Ty> struct IsConstT : FalseConstant {};
template<typename Ty> struct IsConstT<const Ty> : TrueConstant {};
template<typename Ty>
inline constexpr bool isConst()
{
return IsConstT<Ty>::value;
}
template<typename Ty> struct IsVolatileT : FalseConstant {};
template<typename Ty> struct IsVolatileT<volatile Ty> : TrueConstant {};
template<typename Ty>
inline constexpr bool isVolatile()
{
return IsVolatileT<Ty>::value;
}
template<typename Ty> struct IsLvalueReferenceT : FalseConstant {};
template<typename Ty> struct IsLvalueReferenceT<Ty&> : TrueConstant {};
template<typename Ty>
inline constexpr bool isLvalueReference()
{
return IsLvalueReferenceT<Ty>::value;
}
template<typename Ty> struct IsRvalueReferenceT : FalseConstant {};
template<typename Ty> struct IsRvalueReferenceT<Ty&&> : TrueConstant {};
template<typename Ty>
inline constexpr bool isRvalueReference()
{
return IsRvalueReferenceT<Ty>::value;
}
template<typename Ty>
inline constexpr bool isReference()
{
return isLvalueReference<Ty>()
|| isRvalueReference<Ty>()
;
}
template<typename Ty> struct IsPointerT : FalseConstant {};
template<typename Ty> struct IsPointerT<Ty*> : TrueConstant {};
template<typename Ty> struct IsPointerT<Ty* const> : TrueConstant {};
template<typename Ty> struct IsPointerT<Ty* volatile> : TrueConstant {};
template<typename Ty> struct IsPointerT<Ty* const volatile> : TrueConstant {};
template<typename Ty>
inline constexpr bool isPointer()
{
return IsPointerT<Ty>::value;
}
template<typename Ty>
inline constexpr bool isSigned()
{
return Ty(-1) < Ty(0);
}
template<typename Ty>
inline constexpr bool isUnsigned()
{
return Ty(-1) > Ty(0);
}
template<typename Ty> struct IsIntegerT : FalseConstant {};
template<> struct IsIntegerT<bool > : TrueConstant {};
template<> struct IsIntegerT<char > : TrueConstant {};
template<> struct IsIntegerT<char16_t > : TrueConstant {};
template<> struct IsIntegerT<char32_t > : TrueConstant {};
template<> struct IsIntegerT<wchar_t > : TrueConstant {};
template<> struct IsIntegerT< signed char > : TrueConstant {};
template<> struct IsIntegerT<unsigned char > : TrueConstant {};
template<> struct IsIntegerT< short > : TrueConstant {};
template<> struct IsIntegerT<unsigned short > : TrueConstant {};
template<> struct IsIntegerT< int > : TrueConstant {};
template<> struct IsIntegerT<unsigned int > : TrueConstant {};
template<> struct IsIntegerT< long > : TrueConstant {};
template<> struct IsIntegerT<unsigned long > : TrueConstant {};
template<> struct IsIntegerT< long long> : TrueConstant {};
template<> struct IsIntegerT<unsigned long long> : TrueConstant {};
template<typename Ty>
inline constexpr bool isInteger()
{
return IsIntegerT<Ty>::value;
}
template<typename Ty> struct IsFloatingPointT : FalseConstant {};
template<> struct IsFloatingPointT<float > : TrueConstant {};
template<> struct IsFloatingPointT< double> : TrueConstant {};
template<> struct IsFloatingPointT<long double> : TrueConstant {};
template<typename Ty>
inline constexpr bool isFloatingPoint()
{
return IsFloatingPointT<Ty>::value;
}
template<typename Ty>
inline constexpr bool isArithmetic()
{
return isInteger<Ty>()
|| isFloatingPoint<Ty>()
;
}
template<typename Ty, typename Uy> struct IsSameT : FalseConstant {};
template<typename Ty> struct IsSameT<Ty, Ty> : TrueConstant {};
template<typename Ty, typename Uy>
inline constexpr bool isSame()
{
return IsSameT<Ty, Uy>::value;
}
template<typename Ty>
constexpr RemoveReferenceType<Ty>&& move(Ty&& _a)
{
return static_cast<RemoveReferenceType<Ty>&&>(_a);
}
template<typename Ty>
inline constexpr Ty&& forward(RemoveReferenceType<Ty>& _a)
{
return static_cast<Ty&&>(_a);
}
template<typename Ty>
inline constexpr Ty&& forward(RemoveReferenceType<Ty>&& _a)
{
BX_STATIC_ASSERT(!isLvalueReference<Ty>(), "Can not forward an Rvalue as an Lvalue.");
return static_cast<Ty&&>(_a);
}
} // namespace bx

280
include/bx/typetraits.h Normal file
View File

@@ -0,0 +1,280 @@
/*
* Copyright 2010-2022 Branimir Karadzic. All rights reserved.
* License: https://github.com/bkaradzic/bx/blob/master/LICENSE
*/
#ifndef BX_TYPETRAITS_H_HEADER_GUARD
#define BX_TYPETRAITS_H_HEADER_GUARD
namespace bx
{
/// Returns true if type `Ty` is array type with known bound, otherwise returns false.
template<typename Ty>
constexpr bool isBoundedArray();
/// Returns true if type `Ty` is array type with unknown bound, otherwise returns false.
template<typename Ty>
constexpr bool isUnboundedArray();
/// Returns true if type `Ty` is array type (bounded, or unbounded array), otherwise returns false.
template<typename Ty>
constexpr bool isArray();
/// Returns true if type `Ty` is enumeration type, otherwise returns false.
template<typename Ty>
constexpr bool isEnum();
/// Returns true if type `Ty` is union type, otherwise returns false.
template<typename Ty>
constexpr bool isUnion();
/// Returns true if type `Ty` is non-union class type, otherwise returns false.
template<typename Ty>
constexpr bool isClass();
/// Returns true if type `Ty` is abstract class type, otherwise returns false.
template<typename Ty>
constexpr bool isAbstract();
/// Returns true if type `Ty` is aggregate class type, otherwise returns false.
template<typename Ty>
constexpr bool isAggregate();
/// Returns true if type `DerivedT` is derived from `BaseT` type, or if both are the same
/// non-union type, otherwise returns false.
template<typename BaseT, typename DerivedT>
constexpr bool isBaseOf();
/// Returns true if type `Ty` is polymorphic class (if it has virtual function table) type,
/// otherwise returns false.
template<typename Ty>
constexpr bool isPolymorphic();
/// Returns true if type `Ty` has virtual destructor, otherwise returns false.
template<typename Ty>
constexpr bool isDestructorVirtual();
/// Returns true if type `Ty` is class type with final specifier, otherwise returns false.
template<typename Ty>
constexpr bool isFinal();
/// Returns true if type `Ty` is non-union class type with no non-static
/// members (a.k.a. sizeof(Ty) is zero), otherwise returns false.
template<typename Ty>
constexpr bool isEmpty();
/// Returns true if type `Ty` is standard-layout type, otherwise returns false.
template<typename Ty>
constexpr bool isStandardLayout();
/// Returns true if type `Ty` is trivial type, otherwise returns false.
template<typename Ty>
constexpr bool isTrivial();
/// Returns true if type `Ty` is POD (standard-layout, and trivial type), otherwise returns false.
template<typename Ty>
constexpr bool isPod();
/// Returns true if type `FromT` can be assigned to type `Ty`, otherwise returns false.
template<typename Ty, typename FromT>
constexpr bool isAssignable();
/// Returns true if type `Ty` has copy assignment operator, otherwise returns false.
template<typename Ty, typename Uy>
constexpr bool isCopyAssignable();
/// Returns true if type `Ty` has move assignment operator, otherwise returns false.
template<typename Ty, typename Uy>
constexpr bool isMoveAssignable();
/// Returns true if type `FromT` can be trivially assigned to type `Ty`, otherwise returns false.
template<typename Ty, typename FromT>
constexpr bool isTriviallyAssignable();
/// Returns true if type `Ty` is trivially copy-assignable type, otherwise returns false.
template<typename Ty>
constexpr bool isTriviallyCopyAssignable();
/// Returns true if type `Ty` is trivially move-assignable type, otherwise returns false.
template<typename Ty>
constexpr bool isTriviallyMoveAssignable();
/// Returns true if type `Ty` is constructible when the specified argument types are used,
/// otherwise returns false.
template<typename Ty, typename... ArgsT>
constexpr bool isConstructible();
/// Returns true if type `Ty` has copy constructor, otherwise returns false.
template<typename Ty>
constexpr bool isCopyConstructible();
/// Returns true if type `Ty` has move constructor, otherwise returns false.
template<typename Ty>
constexpr bool isMoveConstructible();
/// Returns true if type `Ty` is trivially constructible when the specified argument types are used,
/// otherwise returns false.
template<typename T, typename... ArgsT>
constexpr bool isTriviallyConstructible();
/// Returns true if type `Ty` has trivial copy constructor, otherwise returns false.
template<typename Ty>
constexpr bool isTriviallyCopyConstructible();
/// Returns true if type `Ty` has trivial move constructor, otherwise returns false.
template<typename Ty>
constexpr bool isTriviallyMoveConstructible();
/// Returns true if type `Ty` is trivially copyable / POD type, otherwise returns false.
template<typename Ty>
constexpr bool isTriviallyCopyable();
/// Returns true if type `Ty` has trivial destructor, otherwise returns false.
template<typename Ty>
constexpr bool isTriviallyDestructible();
/// Returns true if type `Ty` is const-qualified type, otherwise returns false.
template<typename Ty>
constexpr bool isConst();
/// Returns true if type `Ty` is volatile-qualified type, otherwise returns false.
template<typename Ty>
constexpr bool isVolatile();
/// Returns true if type `Ty` is an reference type, otherwise returns false.
template<typename Ty>
constexpr bool isReference();
/// Returns true if type `Ty` is an Lvalue reference type, otherwise returns false.
template<typename Ty>
constexpr bool isLvalueReference();
/// Returns true if type `Ty` is an Rvalue reference type, otherwise returns false.
template<typename Ty>
constexpr bool isRvalueReference();
/// Returns true if type `Ty` is an pointer type, otherwise returns false.
template<typename Ty>
constexpr bool isPointer();
/// Returns true if type `Ty` is signed integer or floating-point type, otherwise returns false.
template<typename Ty>
constexpr bool isSigned();
/// Returns true if type `Ty` is unsigned integer type, otherwise returns false.
template<typename Ty>
constexpr bool isUnsigned();
/// Returns true if type `Ty` is integer type, otherwise returns false.
template<typename Ty>
constexpr bool isInteger();
/// Returns true if type `Ty` is floating-point type, otherwise returns false.
template<typename Ty>
constexpr bool isFloatingPoint();
/// Returns true if type `Ty` is arithmetic type, otherwise returns false.
template<typename Ty>
constexpr bool isArithmetic();
/// Returns true if type `Ty` and type `Uy` are the same type, otherwise returns false.
template<typename Ty, typename Uy>
constexpr bool isSame();
} // namespace bx
#include "inline/typetraits.inl"
namespace bx
{
/// Compile-time constant of specified type `Ty` with specified value `ValueT`.
template<typename Ty, Ty ValueT>
struct IntegralConstantT;
/// Alias of IntegralConstantT<bool, bool ValueT>.
template<bool BoolT>
using BoolConstantT = IntegralConstantT<bool, BoolT>;
/// Alias of BoolConstantT<bool, false>.
using FalseConstant = BoolConstantT<false>;
/// Alias of BoolConstantT<bool, true>.
using TrueConstant = BoolConstantT<true>;
/// Provides the member `Type` that names `Ty`.
template<typename Ty>
using TypeIdentityType = typename TypeIdentityT<Ty>::Type;
/// Conditionally selects `Ty` if `BoolT` is true, otherwise selects `Uy` type.
template<bool BoolT, typename Ty, typename Uy>
using ConditionalType = typename ConditionalT<BoolT, Ty, Uy>::Type;
/// If `BoolT` condition is true it provides `Ty` as `Type`, otherwise `Type` is undefined.
template<bool BoolT, typename Ty>
using EnableIfType = typename EnableIfT<BoolT, Ty>::Type;
/// If `Ty` is an object type or a function type that has no cv- or ref- qualifier, provides
/// a member `Type` which is `Ty&`. If `Ty` is an Rvalue reference to some type `Uy`, then
/// type is `Uy&`, otherwise type is `Ty`.
template<typename Ty>
using AddLvalueReferenceType = typename AddLvalueReferenceT<Ty>::Type;
/// If `Ty` is an object type or a function type that has no cv- or ref- qualifier, provides
/// a member `Type` which is `Ty&&`, otherwise type is `Ty`.
template<typename Ty>
using AddRvalueReferenceType = typename AddRvalueReferenceT<Ty>::Type;
/// If the type `Ty` is a reference type, provides the member typedef `Type`
/// which is the type referred to by `Ty`, otherwise type is `Ty`.
template<typename Ty>
using RemoveReferenceType = typename RemoveReferenceT<Ty>::Type;
/// If the type `Ty` is a reference type, provides the member typedef `Type`
/// which is a pointer to the referred type.
template<typename Ty>
using AddPointerType = typename AddPointerT<Ty>::Type;
/// If the type `Ty` is a pointer type, provides the member typedef `Type`
/// which is the type pointed to by `Ty`, otherwise type is `Ty`.
template<typename Ty>
using RemovePointerType = typename RemovePointerT<Ty>::Type;
/// Adds both `const`, and `volatile` to type `Ty`.
template<typename Ty>
using AddCvType = typename AddCvT<Ty>::Type;
/// Removes the topmost `const`, or the topmost `volatile`, or both, from type `Ty` if present.
template<typename Ty>
using RemoveCvType = typename RemoveCvT<Ty>::Type;
/// Adds `const` to type `Ty`.
template<typename Ty>
using AddConstType = typename AddConstT<Ty>::Type;
/// Removes the topmost `const` from type `Ty` if present.
template<typename Ty>
using RemoveConstType = typename RemoveConstT<Ty>::Type;
/// Adds `volatile` to type `Ty`.
template<typename Ty>
using AddVolatileType = typename AddVolatileT<Ty>::Type;
/// Removes the topmost `volatile` from type `Ty` if present.
template<typename Ty>
using RemoveVolatileType = typename RemoveVolatileT<Ty>::Type;
/// Removes reference from type `Ty` if present.
template<typename Ty>
constexpr RemoveReferenceType<Ty>&& move(Ty&& _a);
/// Forwards Lvalues as either Lvalues or as Rvalues.
template<typename Ty>
constexpr Ty&& forward(RemoveReferenceType<Ty>& _type);
/// Forwards Rvalues as Rvalues and prohibits forwarding of Rvalues as Lvalues.
template<typename Ty>
constexpr Ty&& forward(RemoveReferenceT<Ty>&& _type);
} // namespace bx
#endif // BX_TYPETRAITS_H_HEADER_GUARD