michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "mozilla/Assertions.h" michael@0: #include "mozilla/TypeTraits.h" michael@0: michael@0: using mozilla::IsArray; michael@0: using mozilla::IsBaseOf; michael@0: using mozilla::IsClass; michael@0: using mozilla::IsConvertible; michael@0: using mozilla::IsEmpty; michael@0: using mozilla::IsLvalueReference; michael@0: using mozilla::IsReference; michael@0: using mozilla::IsRvalueReference; michael@0: using mozilla::IsSame; michael@0: using mozilla::IsSigned; michael@0: using mozilla::IsUnsigned; michael@0: using mozilla::MakeSigned; michael@0: using mozilla::MakeUnsigned; michael@0: michael@0: static_assert(!IsArray::value, "bool not an array"); michael@0: static_assert(IsArray::value, "bool[] is an array"); michael@0: static_assert(IsArray::value, "bool[5] is an array"); michael@0: michael@0: static_assert(!IsLvalueReference::value, "bool not an lvalue reference"); michael@0: static_assert(!IsLvalueReference::value, "bool* not an lvalue reference"); michael@0: static_assert(IsLvalueReference::value, "bool& is an lvalue reference"); michael@0: static_assert(!IsLvalueReference::value, "bool&& not an lvalue reference"); michael@0: michael@0: static_assert(!IsLvalueReference::value, "void not an lvalue reference"); michael@0: static_assert(!IsLvalueReference::value, "void* not an lvalue reference"); michael@0: michael@0: static_assert(!IsLvalueReference::value, "int not an lvalue reference"); michael@0: static_assert(!IsLvalueReference::value, "int* not an lvalue reference"); michael@0: static_assert(IsLvalueReference::value, "int& is an lvalue reference"); michael@0: static_assert(!IsLvalueReference::value, "int&& not an lvalue reference"); michael@0: michael@0: static_assert(!IsRvalueReference::value, "bool not an rvalue reference"); michael@0: static_assert(!IsRvalueReference::value, "bool* not an rvalue reference"); michael@0: static_assert(!IsRvalueReference::value, "bool& not an rvalue reference"); michael@0: static_assert(IsRvalueReference::value, "bool&& is an rvalue reference"); michael@0: michael@0: static_assert(!IsRvalueReference::value, "void not an rvalue reference"); michael@0: static_assert(!IsRvalueReference::value, "void* not an rvalue reference"); michael@0: michael@0: static_assert(!IsRvalueReference::value, "int not an rvalue reference"); michael@0: static_assert(!IsRvalueReference::value, "int* not an rvalue reference"); michael@0: static_assert(!IsRvalueReference::value, "int& not an rvalue reference"); michael@0: static_assert(IsRvalueReference::value, "int&& is an rvalue reference"); michael@0: michael@0: static_assert(!IsReference::value, "bool not a reference"); michael@0: static_assert(!IsReference::value, "bool* not a reference"); michael@0: static_assert(IsReference::value, "bool& is a reference"); michael@0: static_assert(IsReference::value, "bool&& is a reference"); michael@0: michael@0: static_assert(!IsReference::value, "void not a reference"); michael@0: static_assert(!IsReference::value, "void* not a reference"); michael@0: michael@0: static_assert(!IsReference::value, "int not a reference"); michael@0: static_assert(!IsReference::value, "int* not a reference"); michael@0: static_assert(IsReference::value, "int& is a reference"); michael@0: static_assert(IsReference::value, "int&& is a reference"); michael@0: michael@0: struct S1 {}; michael@0: union U1 { int x; }; michael@0: michael@0: static_assert(!IsClass::value, "int isn't a class"); michael@0: static_assert(IsClass::value, "S is a class"); michael@0: static_assert(!IsClass::value, "U isn't a class"); michael@0: michael@0: static_assert(!mozilla::IsEmpty::value, "not a class => not empty"); michael@0: static_assert(!mozilla::IsEmpty::value, "not a class => not empty"); michael@0: michael@0: static_assert(!mozilla::IsEmpty::value, "not a class => not empty"); michael@0: michael@0: struct E1 {}; michael@0: struct E2 { int : 0; }; michael@0: struct E3 : E1 {}; michael@0: struct E4 : E2 {}; michael@0: michael@0: static_assert(IsEmpty::value, "S should be empty"); michael@0: michael@0: static_assert(mozilla::IsEmpty::value && michael@0: mozilla::IsEmpty::value && michael@0: mozilla::IsEmpty::value && michael@0: mozilla::IsEmpty::value, michael@0: "all empty"); michael@0: michael@0: union U2 { E1 e1; }; michael@0: static_assert(!mozilla::IsEmpty::value, "not a class => not empty"); michael@0: michael@0: struct NE1 { int x; }; michael@0: struct NE2 : virtual E1 {}; michael@0: struct NE3 : E2 { virtual ~NE3() {} }; michael@0: struct NE4 { virtual void f() {} }; michael@0: michael@0: static_assert(!mozilla::IsEmpty::value && michael@0: !mozilla::IsEmpty::value && michael@0: !mozilla::IsEmpty::value && michael@0: !mozilla::IsEmpty::value, michael@0: "all empty"); michael@0: michael@0: static_assert(!IsSigned::value, "bool shouldn't be signed"); michael@0: static_assert(IsUnsigned::value, "bool should be unsigned"); michael@0: michael@0: static_assert(!IsSigned::value, "const bool shouldn't be signed"); michael@0: static_assert(IsUnsigned::value, "const bool should be unsigned"); michael@0: michael@0: static_assert(!IsSigned::value, "volatile bool shouldn't be signed"); michael@0: static_assert(IsUnsigned::value, "volatile bool should be unsigned"); michael@0: michael@0: static_assert(!IsSigned::value, "unsigned char shouldn't be signed"); michael@0: static_assert(IsUnsigned::value, "unsigned char should be unsigned"); michael@0: static_assert(IsSigned::value, "signed char should be signed"); michael@0: static_assert(!IsUnsigned::value, "signed char shouldn't be unsigned"); michael@0: michael@0: static_assert(!IsSigned::value, "unsigned short shouldn't be signed"); michael@0: static_assert(IsUnsigned::value, "unsigned short should be unsigned"); michael@0: static_assert(IsSigned::value, "short should be signed"); michael@0: static_assert(!IsUnsigned::value, "short shouldn't be unsigned"); michael@0: michael@0: static_assert(!IsSigned::value, "unsigned int shouldn't be signed"); michael@0: static_assert(IsUnsigned::value, "unsigned int should be unsigned"); michael@0: static_assert(IsSigned::value, "int should be signed"); michael@0: static_assert(!IsUnsigned::value, "int shouldn't be unsigned"); michael@0: michael@0: static_assert(!IsSigned::value, "unsigned long shouldn't be signed"); michael@0: static_assert(IsUnsigned::value, "unsigned long should be unsigned"); michael@0: static_assert(IsSigned::value, "long should be signed"); michael@0: static_assert(!IsUnsigned::value, "long shouldn't be unsigned"); michael@0: michael@0: static_assert(IsSigned::value, "float should be signed"); michael@0: static_assert(!IsUnsigned::value, "float shouldn't be unsigned"); michael@0: michael@0: static_assert(IsSigned::value, "const float should be signed"); michael@0: static_assert(!IsUnsigned::value, "const float shouldn't be unsigned"); michael@0: michael@0: static_assert(IsSigned::value, "double should be signed"); michael@0: static_assert(!IsUnsigned::value, "double shouldn't be unsigned"); michael@0: michael@0: static_assert(IsSigned::value, "volatile double should be signed"); michael@0: static_assert(!IsUnsigned::value, "volatile double shouldn't be unsigned"); michael@0: michael@0: static_assert(IsSigned::value, "long double should be signed"); michael@0: static_assert(!IsUnsigned::value, "long double shouldn't be unsigned"); michael@0: michael@0: static_assert(IsSigned::value, michael@0: "const volatile long double should be signed"); michael@0: static_assert(!IsUnsigned::value, michael@0: "const volatile long double shouldn't be unsigned"); michael@0: michael@0: namespace CPlusPlus11IsBaseOf { michael@0: michael@0: // Adapted from C++11 ยง 20.9.6. michael@0: struct B {}; michael@0: struct B1 : B {}; michael@0: struct B2 : B {}; michael@0: struct D : private B1, private B2 {}; michael@0: michael@0: static void michael@0: StandardIsBaseOfTests() michael@0: { michael@0: static_assert((IsBaseOf::value) == true, "IsBaseOf fails on diamond"); michael@0: static_assert((IsBaseOf::value) == true, "IsBaseOf fails on diamond plus constness change"); michael@0: static_assert((IsBaseOf::value) == true, "IsBaseOf fails on diamond plus constness change"); michael@0: static_assert((IsBaseOf::value) == true, "IsBaseOf fails on constness change"); michael@0: static_assert((IsBaseOf::value) == false, "IsBaseOf got the direction of inheritance wrong"); michael@0: static_assert((IsBaseOf::value) == false, "IsBaseOf should return false on references"); michael@0: static_assert((IsBaseOf::value) == false, "IsBaseOf should return false on arrays"); michael@0: // We fail at the following test. To fix it, we need to specialize IsBaseOf michael@0: // for all built-in types. michael@0: // static_assert((IsBaseOf::value) == false); michael@0: } michael@0: michael@0: } /* namespace CPlusPlus11IsBaseOf */ michael@0: michael@0: class A { }; michael@0: class B : public A { }; michael@0: class C : private A { }; michael@0: class D { }; michael@0: class E : public A { }; michael@0: class F : public B, public E { }; michael@0: michael@0: static void michael@0: TestIsBaseOf() michael@0: { michael@0: static_assert((IsBaseOf::value), michael@0: "A is a base of B"); michael@0: static_assert((!IsBaseOf::value), michael@0: "B is not a base of A"); michael@0: static_assert((IsBaseOf::value), michael@0: "A is a base of C"); michael@0: static_assert((!IsBaseOf::value), michael@0: "C is not a base of A"); michael@0: static_assert((IsBaseOf::value), michael@0: "A is a base of F"); michael@0: static_assert((!IsBaseOf::value), michael@0: "F is not a base of A"); michael@0: static_assert((!IsBaseOf::value), michael@0: "A is not a base of D"); michael@0: static_assert((!IsBaseOf::value), michael@0: "D is not a base of A"); michael@0: static_assert((IsBaseOf::value), michael@0: "B is the same as B (and therefore, a base of B)"); michael@0: } michael@0: michael@0: static void michael@0: TestIsConvertible() michael@0: { michael@0: // Pointer type convertibility michael@0: static_assert((IsConvertible::value), michael@0: "A* should convert to A*"); michael@0: static_assert((IsConvertible::value), michael@0: "B* should convert to A*"); michael@0: static_assert((!IsConvertible::value), michael@0: "A* shouldn't convert to B*"); michael@0: static_assert((!IsConvertible::value), michael@0: "A* shouldn't convert to C*"); michael@0: static_assert((!IsConvertible::value), michael@0: "A* shouldn't convert to unrelated D*"); michael@0: static_assert((!IsConvertible::value), michael@0: "D* shouldn't convert to unrelated A*"); michael@0: michael@0: // Instance type convertibility michael@0: static_assert((IsConvertible::value), michael@0: "A is A"); michael@0: static_assert((IsConvertible::value), michael@0: "B converts to A"); michael@0: static_assert((!IsConvertible::value), michael@0: "D and A are unrelated"); michael@0: static_assert((!IsConvertible::value), michael@0: "A and D are unrelated"); michael@0: michael@0: // These cases seem to require C++11 support to properly implement them, so michael@0: // for now just disable them. michael@0: //static_assert((!IsConvertible::value), michael@0: // "C* shouldn't convert to A* (private inheritance)"); michael@0: //static_assert((!IsConvertible::value), michael@0: // "C doesn't convert to A (private inheritance)"); michael@0: } michael@0: michael@0: static_assert(IsSame::Type, const signed char>::value, michael@0: "const unsigned char won't signify correctly"); michael@0: static_assert(IsSame::Type, volatile signed short>::value, michael@0: "volatile unsigned short won't signify correctly"); michael@0: static_assert(IsSame::Type, const volatile signed int>::value, michael@0: "const volatile unsigned int won't signify correctly"); michael@0: static_assert(IsSame::Type, signed long>::value, michael@0: "unsigned long won't signify correctly"); michael@0: static_assert(IsSame::Type, const signed char>::value, michael@0: "const signed char won't signify correctly"); michael@0: michael@0: static_assert(IsSame::Type, volatile signed short>::value, michael@0: "volatile signed short won't signify correctly"); michael@0: static_assert(IsSame::Type, const volatile signed int>::value, michael@0: "const volatile signed int won't signify correctly"); michael@0: static_assert(IsSame::Type, signed long>::value, michael@0: "signed long won't signify correctly"); michael@0: michael@0: static_assert(IsSame::Type, signed char>::value, michael@0: "char won't signify correctly"); michael@0: static_assert(IsSame::Type, volatile signed char>::value, michael@0: "volatile char won't signify correctly"); michael@0: static_assert(IsSame::Type, const signed char>::value, michael@0: "const char won't signify correctly"); michael@0: michael@0: static_assert(IsSame::Type, const unsigned char>::value, michael@0: "const signed char won't unsignify correctly"); michael@0: static_assert(IsSame::Type, volatile unsigned short>::value, michael@0: "volatile signed short won't unsignify correctly"); michael@0: static_assert(IsSame::Type, const volatile unsigned int>::value, michael@0: "const volatile signed int won't unsignify correctly"); michael@0: static_assert(IsSame::Type, unsigned long>::value, michael@0: "signed long won't unsignify correctly"); michael@0: michael@0: static_assert(IsSame::Type, const unsigned char>::value, michael@0: "const unsigned char won't unsignify correctly"); michael@0: michael@0: static_assert(IsSame::Type, volatile unsigned short>::value, michael@0: "volatile unsigned short won't unsignify correctly"); michael@0: static_assert(IsSame::Type, const volatile unsigned int>::value, michael@0: "const volatile unsigned int won't unsignify correctly"); michael@0: static_assert(IsSame::Type, unsigned long>::value, michael@0: "signed long won't unsignify correctly"); michael@0: michael@0: static_assert(IsSame::Type, unsigned char>::value, michael@0: "char won't unsignify correctly"); michael@0: static_assert(IsSame::Type, volatile unsigned char>::value, michael@0: "volatile char won't unsignify correctly"); michael@0: static_assert(IsSame::Type, const unsigned char>::value, michael@0: "const char won't unsignify correctly"); michael@0: michael@0: int michael@0: main() michael@0: { michael@0: CPlusPlus11IsBaseOf::StandardIsBaseOfTests(); michael@0: TestIsBaseOf(); michael@0: TestIsConvertible(); michael@0: }