text: #include "TypeTraits.h"
  #include "Core.h"
  
  class Foo {};
  
  class PodFoo1 { int a; };
  
  class PodFoo2 : public PodFoo1 {};
  
  class PodFoo3 : public PodFoo1 { public: void foo() {} };
  
  class NPodFoo1 { NPodFoo1() {} };
  
  class NPodFoo2 { ~NPodFoo2() {} };
  
  class NPodFoo3 { NPodFoo3(const NPodFoo3& other) { UNUSED(other); } };
  
  class NPodFoo4 { NPodFoo4& operator=(const NPodFoo4& other) { UNUSED(other); } };
  
  class NPodFoo5 { virtual void foo() {} };
  
  class Base {};
  
  class Derived : public Base {};
  
  class OperatorFoo
  {
  public:
  	bool operator==(const OperatorFoo& other) { UNUSED(other); };
  };
  
  class ConstructibleFoo
  {
  public:
  	ConstructibleFoo() {}
  	ConstructibleFoo(int a) { UNUSED(a); }
  	ConstructibleFoo(float a) { UNUSED(a); }
  	ConstructibleFoo(double a) { UNUSED(a); }
  
  private:
  	ConstructibleFoo(Foo a) { UNUSED(a); }
  };
  
  class NConstructibleFoo
  {
  public:
  	NConstructibleFoo() = delete;
  };
  
  class DefaultConstructibleFoo
  {};
  
  class NDefaultConstructibleFoo
  {
  public:
  	NDefaultConstructibleFoo() = delete;
  };
  
  class DefaultCopyAssignableFoo
  {};
  
  class CopyAssignableFoo
  {
  public:
  	CopyAssignableFoo& operator=(const CopyAssignableFoo& other) { UNUSED(other); };
  };
  
  class NCopyAssignableFoo
  {
  public:
  	NCopyAssignableFoo& operator=(const NCopyAssignableFoo& other) = delete;
  };
  
  class DefaultCopyConstructibleFoo
  {};
  
  class CopyConstructibleFoo
  {
  public:
  	CopyConstructibleFoo(const CopyConstructibleFoo& other) { UNUSED(other); }
  };
  
  class NCopyConstructibleFoo
  {
  public:
  	NCopyConstructibleFoo(const NCopyConstructibleFoo& other) = delete;
  };
  
  class DefaultDestructibleFoo
  {};
  
  class DestructibleFoo
  {
  public:
  	~DestructibleFoo() {}
  };
  
  class NDestructibleFoo
  {
  public:
  	~NDestructibleFoo() = delete;
  };
  
  class DefaultMoveAssignableFoo
  {};
  
  class MoveAssignableFoo
  {
  public:
  	MoveAssignableFoo& operator=(MoveAssignableFoo&& other) { UNUSED(other); }
  };
  
  class NMoveAssignableFoo
  {
  public:
  	NMoveAssignableFoo& operator=(NMoveAssignableFoo&& other) = delete;
  };
  
  class DefaultMoveConstructibleFoo
  {};
  
  class MoveConstructibleFoo
  {
  public:
  	MoveConstructibleFoo(MoveConstructibleFoo&& other) { UNUSED(other); }
  };
  
  class NMoveConstructibleFoo
  {
  public:
  	NMoveConstructibleFoo(NMoveConstructibleFoo&& other) = delete;
  };
  
  void Test()
  {
  	// void
  	static_assert(IsVoid<void>::value, "");
  	static_assert(!IsVoid<Foo>::value, "");
  
  	// integer
  	static_assert(IsInteger<int>::value, "");
  	static_assert(IsInteger<unsigned>::value, "");
  	static_assert(IsInteger<unsigned int>::value, "");
  	static_assert(IsInteger<short>::value, "");
  	static_assert(IsInteger<long>::value, "");
  	static_assert(IsInteger<long long>::value, "");
  	static_assert(IsInteger<unsigned long>::value, "");
  	static_assert(!IsInteger<float>::value, "");
  	static_assert(!IsInteger<double>::value, "");
  	static_assert(!IsInteger<long double>::value, "");
  	static_assert(!IsInteger<Foo>::value, "");
  
  	// float
  	static_assert(IsFloat<float>::value, "");
  	static_assert(IsFloat<double>::value, "");
  	static_assert(IsFloat<long double>::value, "");
  	static_assert(!IsFloat<int>::value, "");
  	static_assert(!IsFloat<unsigned>::value, "");
  	static_assert(!IsFloat<unsigned int>::value, "");
  	static_assert(!IsFloat<short>::value, "");
  	static_assert(!IsFloat<long>::value, "");
  	static_assert(!IsFloat<long long>::value, "");
  	static_assert(!IsFloat<unsigned long>::value, "");
  
  	// number
  	static_assert(IsNumber<float>::value, "");
  	static_assert(IsNumber<double>::value, "");
  	static_assert(IsNumber<long double>::value, "");
  	static_assert(IsNumber<int>::value, "");
  	static_assert(IsNumber<unsigned>::value, "");
  	static_assert(IsNumber<unsigned int>::value, "");
  	static_assert(IsNumber<short>::value, "");
  	static_assert(IsNumber<long>::value, "");
  	static_assert(IsNumber<long long>::value, "");
  	static_assert(IsNumber<unsigned long>::value, "");
  	static_assert(!IsNumber<Foo>::value, "");
  
  	// built-in type
  	static_assert(IsBuiltIn<void>::value, "");
  	static_assert(IsBuiltIn<nullptr_t>::value, "");
  	static_assert(IsBuiltIn<float>::value, "");
  	static_assert(IsBuiltIn<double>::value, "");
  	static_assert(IsBuiltIn<long double>::value, "");
  	static_assert(IsBuiltIn<int>::value, "");
  	static_assert(IsBuiltIn<unsigned>::value, "");
  	static_assert(IsBuiltIn<unsigned int>::value, "");
  	static_assert(IsBuiltIn<short>::value, "");
  	static_assert(IsBuiltIn<long>::value, "");
  	static_assert(IsBuiltIn<long long>::value, "");
  	static_assert(IsBuiltIn<unsigned long>::value, "");
  
  	// pod type
  	static_assert(!IsPod<void>::value, "");
  	static_assert(IsPod<nullptr_t>::value, "");
  	static_assert(IsPod<float>::value, "");
  	static_assert(IsPod<double>::value, "");
  	static_assert(IsPod<long double>::value, "");
  	static_assert(IsPod<int>::value, "");
  	static_assert(IsPod<unsigned>::value, "");
  	static_assert(IsPod<unsigned int>::value, "");
  	static_assert(IsPod<short>::value, "");
  	static_assert(IsPod<long>::value, "");
  	static_assert(IsPod<long long>::value, "");
  	static_assert(IsPod<unsigned long>::value, "");
  	static_assert(IsPod<PodFoo1>::value, "");
  	static_assert(IsPod<PodFoo2>::value, "");
  	static_assert(IsPod<PodFoo3>::value, "");
  	static_assert(!IsPod<NPodFoo1>::value, "");
  	static_assert(!IsPod<NPodFoo2>::value, "");
  	static_assert(!IsPod<NPodFoo3>::value, "");
  	static_assert(!IsPod<NPodFoo4>::value, "");
  	static_assert(!IsPod<NPodFoo5>::value, "");
  
  	// ptr
  	static_assert(!IsPointer<Foo>::value, "");
  	static_assert(IsPointer<Foo*>::value, "");
  
  	// nullptr_t
  	static_assert(!IsNullPointer<Foo*>::value, "");
  	static_assert(IsNullPointer<nullptr_t>::value, "");
  
  	// is same
  	static_assert(IsSame<int, int>::value, "");
  	static_assert(!IsSame<int, float>::value, "");
  
  	// is any of
  	static_assert(!IsAnyOf<Foo, int, float, double, Base, Derived>::value, "");
  	static_assert(IsAnyOf<Foo, int, float, double, Foo, Derived>::value, "");
  
  	// remove const
  	static_assert(IsSame<RemoveConst<Foo>::Type, Foo>::value, "");
  	static_assert(IsSame<RemoveConst<const Foo>::Type, Foo>::value, "");
  	static_assert(IsSame<RemoveConst<volatile const Foo>::Type, volatile Foo>::value, "");
  
  	// remove volatile
  	static_assert(IsSame<RemoveVolatile<volatile const Foo>::Type, const Foo>::value, "");
  
  	// remove cv
  	static_assert(IsSame<RemoveCV<Foo>::Type, Foo>::value, "");
  	static_assert(IsSame<RemoveCV<const Foo>::Type, Foo>::value, "");
  	static_assert(IsSame<RemoveCV<volatile const Foo>::Type, Foo>::value, "");
  
  	// remove reference
  	static_assert(IsSame<RemoveReference<Foo*&>::Type, Foo*>::value, "");
  	static_assert(IsSame<RemoveReference<Foo&>::Type, Foo>::value, "");
  	static_assert(IsSame<RemoveReference<Foo&&>::Type, Foo>::value, "");
  	static_assert(IsSame<RemoveReference<Foo&&>::Type, Foo>::value, "");
  
  	// add reference
  	using RefRemovedType = RemoveReference<Foo&&>::Type;
  	using LFoo = AddReference<RefRemovedType>::Lvalue;
  	using RFoo = AddReference<RefRemovedType>::Rvalue;
  	static_assert(IsSame<LFoo, Foo&>::value, "");
  	static_assert(IsSame<RFoo, Foo&&>::value, "");
  
  	// operator==
  	static_assert(!OperatorTraits::HasEqual<Foo>::value, "");
  	static_assert(OperatorTraits::HasEqual<OperatorFoo>::value, "");
  
  	// constructible
  	static_assert(IsConstructible<ConstructibleFoo>::value, "");
  	static_assert(IsConstructible<ConstructibleFoo, int>::value, "");
  	static_assert(IsConstructible<ConstructibleFoo, float>::value, "");
  	static_assert(IsConstructible<ConstructibleFoo, double>::value, "");
  	static_assert(!IsConstructible<ConstructibleFoo, Foo>::value, "");
  	static_assert(!IsConstructible<NConstructibleFoo>::value, "");
  
  	static_assert(IsConstructible<Foo>::value, "");
  	static_assert(IsConstructible<int>::value, "");
  	static_assert(IsConstructible<int, float>::value, "");
  	static_assert(IsConstructible<int, short>::value, "");
  	static_assert(IsConstructible<int, double>::value, "");
  
  	// default constructible
  	static_assert(IsDefaultConstructible<DefaultConstructibleFoo>::value, "");
  	static_assert(IsDefaultConstructible<ConstructibleFoo>::value, "");
  	static_assert(!IsDefaultConstructible<NDefaultConstructibleFoo>::value, "");
  
  	static_assert(IsDefaultConstructible<int>::value, "");
  	static_assert(IsDefaultConstructible<Foo>::value, "");
  
  	// copy assignable
  	static_assert(IsCopyAssignable<DefaultCopyAssignableFoo>::value, "");
  	static_assert(IsCopyAssignable<CopyAssignableFoo>::value, "");
  	static_assert(!IsCopyAssignable<NCopyAssignableFoo>::value, "");
  
  	static_assert(!IsCopyAssignable<DefaultCopyAssignableFoo, int>::value, "");
  	static_assert(!IsCopyAssignable<CopyAssignableFoo, Foo>::value, "");
  
  	static_assert(IsCopyAssignable<int, int>::value, "");
  	static_assert(IsCopyAssignable<int, double>::value, "");
  	static_assert(IsCopyAssignable<double, int>::value, "");
  	static_assert(IsCopyAssignable<int, float>::value, "");
  	static_assert(!IsCopyAssignable<int, Foo>::value, "");
  
  	// copy constructible
  	static_assert(IsCopyConstructible<DefaultCopyConstructibleFoo>::value, "");
  	static_assert(IsCopyConstructible<CopyConstructibleFoo>::value, "");
  	static_assert(!IsCopyConstructible<NCopyConstructibleFoo>::value, "");
  
  	static_assert(IsCopyConstructible<int>::value, "");
  	static_assert(IsCopyConstructible<double>::value, "");
  	static_assert(IsCopyConstructible<float>::value, "");
  
  	// destructible
  	static_assert(IsDestructible<DefaultDestructibleFoo>::value, "");
  	static_assert(IsDestructible<DestructibleFoo>::value, "");
  	static_assert(!IsDestructible<NDestructibleFoo>::value, "");
  
  	static_assert(IsDestructible<int>::value, "");
  	static_assert(IsDestructible<double>::value, "");
  	static_assert(IsDestructible<float>::value, "");
  
  	// move assignable
  	static_assert(IsMoveAssignable<DefaultMoveAssignableFoo>::value, "");
  	static_assert(IsMoveAssignable<MoveAssignableFoo>::value, "");
  	static_assert(!IsMoveAssignable<NMoveAssignableFoo>::value, "");
  
  	static_assert(!IsMoveAssignable<int>::value, "");
  	static_assert(!IsMoveAssignable<double>::value, "");
  	static_assert(!IsMoveAssignable<float>::value, "");
  
  	// move constructible
  	static_assert(IsMoveConstructible<DefaultMoveConstructibleFoo>::value, "");
  	static_assert(IsMoveConstructible<MoveConstructibleFoo>::value, "");
  	static_assert(!IsMoveConstructible<NMoveConstructibleFoo>::value, "");
  
  	static_assert(IsMoveConstructible<int>::value, "");
  	static_assert(IsMoveConstructible<double>::value, "");
  	static_assert(IsMoveConstructible<float>::value, "");
  
  	// trivially assignable
  	static_assert(IsTriviallyAssignable<DefaultCopyAssignableFoo>::value, "");
  	static_assert(IsTriviallyAssignable<DefaultMoveAssignableFoo>::value, "");
  	static_assert(!IsTriviallyAssignable<CopyAssignableFoo>::value, "");
  	static_assert(!IsTriviallyAssignable<MoveAssignableFoo>::value, "");
  
  	// trivially move assignable
  	static_assert(IsTriviallyMoveAssignable<DefaultMoveAssignableFoo>::value, "");
  	static_assert(!IsTriviallyMoveAssignable<MoveAssignableFoo>::value, "");
  
  	// trivially copy assignable
  	static_assert(IsTriviallyCopyAssignable<DefaultCopyAssignableFoo>::value, "");
  	static_assert(!IsTriviallyCopyAssignable<CopyAssignableFoo>::value, "");
  
  	// trivially constructible
  	static_assert(IsTriviallyConstructible<DefaultConstructibleFoo>::value, "");
  	static_assert(IsTriviallyConstructible<DefaultCopyConstructibleFoo>::value, "");
  	static_assert(IsTriviallyConstructible<DefaultMoveConstructibleFoo>::value, "");
  	static_assert(!IsTriviallyConstructible<CopyConstructibleFoo>::value, "");
  	static_assert(!IsTriviallyConstructible<MoveConstructibleFoo>::value, "");
  
  	// trivially default constructible
  	static_assert(IsTriviallyDefaultConstructible<DefaultConstructibleFoo>::value, "");
  	static_assert(!IsTriviallyDefaultConstructible<ConstructibleFoo>::value, "");
  
  	// trivially copy constructible
  	static_assert(IsTriviallyCopyConstructible<DefaultCopyConstructibleFoo>::value, "");
  	static_assert(!IsTriviallyCopyConstructible<CopyConstructibleFoo>::value, "");
  
  	// trivially move constructible
  	static_assert(IsTriviallyMoveConstructible<DefaultMoveConstructibleFoo>::value, "");
  	static_assert(!IsTriviallyMoveConstructible<MoveConstructibleFoo>::value, "");
  
  	// trivially destructible
  	static_assert(IsTriviallyDestructible<DefaultDestructibleFoo>::value, "");
  	static_assert(!IsTriviallyDestructible<DestructibleFoo>::value, "");
  }