blob: 13bb1505a1327be8477f7eb14ff8497332dfc41a [file] [log] [blame]
// Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ----
// Author: Matt Austern
#include "config.h"
#include <stdlib.h> // for exit()
#include <stdio.h>
#include <string>
#include <vector>
#include <google/type_traits.h>
using STL_NAMESPACE::string;
using STL_NAMESPACE::vector;
using STL_NAMESPACE::pair;
#define ASSERT_TRUE(cond) do { \
if ( !(cond) ) { \
printf("Test failed: " #cond "\n"); \
exit(1); \
} \
} while (0)
#define ASSERT_FALSE(cond) ASSERT_TRUE(!(cond))
// A user-defined POD type.
struct A {
int n_;
};
// A user-defined non-POD type with a trivial copy constructor.
class B {
public:
explicit B(int n) : n_(n) { }
private:
int n_;
};
// Another user-defined non-POD type with a trivial copy constructor.
// We will explicitly declare C to have a trivial copy constructor
// by specializing has_trivial_copy.
class C {
public:
explicit C(int n) : n_(n) { }
private:
int n_;
};
_START_GOOGLE_NAMESPACE_
template<> struct has_trivial_copy<C> : true_type { };
_END_GOOGLE_NAMESPACE_
// Another user-defined non-POD type with a trivial assignment operator.
// We will explicitly declare C to have a trivial assignment operator
// by specializing has_trivial_assign.
class D {
public:
explicit D(int n) : n_(n) { }
private:
int n_;
};
_START_GOOGLE_NAMESPACE_
template<> struct has_trivial_assign<D> : true_type { };
_END_GOOGLE_NAMESPACE_
// Another user-defined non-POD type with a trivial constructor.
// We will explicitly declare E to have a trivial constructor
// by specializing has_trivial_constructor.
class E {
public:
int n_;
};
_START_GOOGLE_NAMESPACE_
template<> struct has_trivial_constructor<E> : true_type { };
_END_GOOGLE_NAMESPACE_
// Another user-defined non-POD type with a trivial destructor.
// We will explicitly declare E to have a trivial destructor
// by specializing has_trivial_destructor.
class F {
public:
explicit F(int n) : n_(n) { }
private:
int n_;
};
_START_GOOGLE_NAMESPACE_
template<> struct has_trivial_destructor<F> : true_type { };
_END_GOOGLE_NAMESPACE_
namespace {
// type_equals_ is a template type comparator, similar to Loki IsSameType.
// type_equals_<A, B>::value is true iff "A" is the same type as "B".
template<typename A, typename B>
struct type_equals_ : public GOOGLE_NAMESPACE::false_type {
};
template<typename A>
struct type_equals_<A, A> : public GOOGLE_NAMESPACE::true_type {
};
// A base class and a derived class that inherits from it, used for
// testing conversion type traits.
class Base {
public:
virtual ~Base() { }
};
class Derived : public Base {
};
// This assertion produces errors like "error: invalid use of
// undefined type 'struct <unnamed>::AssertTypesEq<const int, int>'"
// when it fails.
template<typename T, typename U> struct AssertTypesEq;
template<typename T> struct AssertTypesEq<T, T> {};
#define COMPILE_ASSERT_TYPES_EQ(T, U) AssertTypesEq<T, U>()
class TypeTraitsTest {
public:
static void TestIsInteger() {
// Verify that is_integral is true for all integer types.
ASSERT_TRUE(GOOGLE_NAMESPACE::is_integral<bool>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_integral<char>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_integral<unsigned char>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_integral<signed char>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_integral<wchar_t>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_integral<int>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_integral<unsigned int>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_integral<short>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_integral<unsigned short>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_integral<long>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_integral<unsigned long>::value);
// Verify that is_integral is false for a few non-integer types.
ASSERT_FALSE(GOOGLE_NAMESPACE::is_integral<void>::value);
ASSERT_FALSE(GOOGLE_NAMESPACE::is_integral<float>::value);
ASSERT_FALSE(GOOGLE_NAMESPACE::is_integral<string>::value);
ASSERT_FALSE(GOOGLE_NAMESPACE::is_integral<int*>::value);
ASSERT_FALSE(GOOGLE_NAMESPACE::is_integral<A>::value);
ASSERT_FALSE((GOOGLE_NAMESPACE::is_integral<pair<int, int> >::value));
}
static void TestIsFloating() {
// Verify that is_floating_point is true for all floating-point types.
ASSERT_TRUE(GOOGLE_NAMESPACE::is_floating_point<float>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_floating_point<double>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_floating_point<long double>::value);
// Verify that is_floating_point is false for a few non-float types.
ASSERT_FALSE(GOOGLE_NAMESPACE::is_floating_point<void>::value);
ASSERT_FALSE(GOOGLE_NAMESPACE::is_floating_point<long>::value);
ASSERT_FALSE(GOOGLE_NAMESPACE::is_floating_point<string>::value);
ASSERT_FALSE(GOOGLE_NAMESPACE::is_floating_point<float*>::value);
ASSERT_FALSE(GOOGLE_NAMESPACE::is_floating_point<A>::value);
ASSERT_FALSE((GOOGLE_NAMESPACE::is_floating_point<pair<int, int> >::value));
}
static void TestIsReference() {
// Verifies that is_reference is true for all reference types.
ASSERT_TRUE(GOOGLE_NAMESPACE::is_reference<float&>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_reference<const int&>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_reference<const int*&>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_reference<int (&)(bool)>::value);
// Verifies that is_reference is false for all non-reference types.
ASSERT_FALSE(GOOGLE_NAMESPACE::is_reference<float>::value);
ASSERT_FALSE(GOOGLE_NAMESPACE::is_reference<const int*>::value);
ASSERT_FALSE(GOOGLE_NAMESPACE::is_reference<int()>::value);
ASSERT_FALSE(GOOGLE_NAMESPACE::is_reference<void(*)(const char&)>::value);
}
static void TestIsPod() {
// Verify that arithmetic types and pointers are marked as PODs.
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<bool>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<char>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<unsigned char>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<signed char>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<wchar_t>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<int>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<unsigned int>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<short>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<unsigned short>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<long>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<unsigned long>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<float>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<double>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<long double>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<string*>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<A*>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<const B*>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::is_pod<C**>::value);
// Verify that some non-POD types are not marked as PODs.
ASSERT_FALSE(GOOGLE_NAMESPACE::is_pod<void>::value);
ASSERT_FALSE(GOOGLE_NAMESPACE::is_pod<string>::value);
ASSERT_FALSE((GOOGLE_NAMESPACE::is_pod<pair<int, int> >::value));
ASSERT_FALSE(GOOGLE_NAMESPACE::is_pod<A>::value);
ASSERT_FALSE(GOOGLE_NAMESPACE::is_pod<B>::value);
ASSERT_FALSE(GOOGLE_NAMESPACE::is_pod<C>::value);
}
static void TestHasTrivialCopy() {
// Verify that arithmetic types and pointers have trivial copy
// constructors.
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<bool>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<char>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<unsigned char>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<signed char>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<wchar_t>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<int>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<unsigned int>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<short>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<unsigned short>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<long>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<unsigned long>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<float>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<double>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<long double>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<string*>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<A*>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<const B*>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<C**>::value);
// Verify that pairs and arrays of such types have trivial
// copy constructors.
typedef int int10[10];
ASSERT_TRUE((GOOGLE_NAMESPACE::has_trivial_copy<pair<int, char*> >::value));
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<int10>::value);
// Verify that types without trivial copy constructors are
// correctly marked as such.
ASSERT_FALSE(GOOGLE_NAMESPACE::has_trivial_copy<string>::value);
ASSERT_FALSE(GOOGLE_NAMESPACE::has_trivial_copy<vector<int> >::value);
// Verify that pairs of types without trivial copy constructors
// are not marked as trivial.
ASSERT_FALSE((GOOGLE_NAMESPACE::has_trivial_copy<pair<int, string> >::value));
ASSERT_FALSE((GOOGLE_NAMESPACE::has_trivial_copy<pair<string, int> >::value));
// Verify that C, which we have declared to have a trivial
// copy constructor, is correctly marked as such.
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_copy<C>::value);
}
static void TestHasTrivialConstructor() {
// Verify that arithmetic types and pointers have trivial constructors.
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<bool>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<char>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<unsigned char>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<signed char>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<wchar_t>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<int>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<unsigned int>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<short>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<unsigned short>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<long>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<unsigned long>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<float>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<double>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<long double>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<string*>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<A*>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<const B*>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<C**>::value);
// Verify that pairs and arrays of such types have trivial
// constructors.
typedef int int10[10];
ASSERT_TRUE((GOOGLE_NAMESPACE::has_trivial_constructor<pair<int, char*> >::value));
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<int10>::value);
// Verify that pairs of types without trivial constructors
// are not marked as trivial.
ASSERT_FALSE((GOOGLE_NAMESPACE::has_trivial_constructor<pair<int, string> >::value));
ASSERT_FALSE((GOOGLE_NAMESPACE::has_trivial_constructor<pair<string, int> >::value));
// Verify that types without trivial constructors are
// correctly marked as such.
ASSERT_FALSE(GOOGLE_NAMESPACE::has_trivial_constructor<string>::value);
ASSERT_FALSE(GOOGLE_NAMESPACE::has_trivial_constructor<vector<int> >::value);
// Verify that E, which we have declared to have a trivial
// constructor, is correctly marked as such.
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_constructor<E>::value);
}
static void TestHasTrivialAssign() {
// Verify that arithmetic types and pointers have trivial assignment
// operators.
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<bool>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<char>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<unsigned char>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<signed char>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<wchar_t>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<int>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<unsigned int>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<short>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<unsigned short>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<long>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<unsigned long>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<float>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<double>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<long double>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<string*>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<A*>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<const B*>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<C**>::value);
// Verify that pairs and arrays of such types have trivial
// assignment operators.
typedef int int10[10];
ASSERT_TRUE((GOOGLE_NAMESPACE::has_trivial_assign<pair<int, char*> >::value));
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<int10>::value);
// Verify that pairs of types without trivial assignment operators
// are not marked as trivial.
ASSERT_FALSE((GOOGLE_NAMESPACE::has_trivial_assign<pair<int, string> >::value));
ASSERT_FALSE((GOOGLE_NAMESPACE::has_trivial_assign<pair<string, int> >::value));
// Verify that types without trivial assignment operators are
// correctly marked as such.
ASSERT_FALSE(GOOGLE_NAMESPACE::has_trivial_assign<string>::value);
ASSERT_FALSE(GOOGLE_NAMESPACE::has_trivial_assign<vector<int> >::value);
// Verify that D, which we have declared to have a trivial
// assignment operator, is correctly marked as such.
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_assign<D>::value);
}
static void TestHasTrivialDestructor() {
// Verify that arithmetic types and pointers have trivial destructors.
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<bool>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<char>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<unsigned char>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<signed char>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<wchar_t>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<int>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<unsigned int>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<short>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<unsigned short>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<long>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<unsigned long>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<float>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<double>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<long double>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<string*>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<A*>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<const B*>::value);
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<C**>::value);
// Verify that pairs and arrays of such types have trivial
// destructors.
typedef int int10[10];
ASSERT_TRUE((GOOGLE_NAMESPACE::has_trivial_destructor<pair<int, char*> >::value));
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<int10>::value);
// Verify that pairs of types without trivial destructors
// are not marked as trivial.
ASSERT_FALSE((GOOGLE_NAMESPACE::has_trivial_destructor<pair<int, string> >::value));
ASSERT_FALSE((GOOGLE_NAMESPACE::has_trivial_destructor<pair<string, int> >::value));
// Verify that types without trivial destructors are
// correctly marked as such.
ASSERT_FALSE(GOOGLE_NAMESPACE::has_trivial_destructor<string>::value);
ASSERT_FALSE(GOOGLE_NAMESPACE::has_trivial_destructor<vector<int> >::value);
// Verify that F, which we have declared to have a trivial
// destructor, is correctly marked as such.
ASSERT_TRUE(GOOGLE_NAMESPACE::has_trivial_destructor<F>::value);
}
// Tests remove_pointer.
static void TestRemovePointer() {
COMPILE_ASSERT_TYPES_EQ(int, GOOGLE_NAMESPACE::remove_pointer<int>::type);
COMPILE_ASSERT_TYPES_EQ(int, GOOGLE_NAMESPACE::remove_pointer<int*>::type);
COMPILE_ASSERT_TYPES_EQ(const int, GOOGLE_NAMESPACE::remove_pointer<const int*>::type);
COMPILE_ASSERT_TYPES_EQ(int, GOOGLE_NAMESPACE::remove_pointer<int* const>::type);
COMPILE_ASSERT_TYPES_EQ(int, GOOGLE_NAMESPACE::remove_pointer<int* volatile>::type);
}
static void TestRemoveConst() {
COMPILE_ASSERT_TYPES_EQ(int, GOOGLE_NAMESPACE::remove_const<int>::type);
COMPILE_ASSERT_TYPES_EQ(int, GOOGLE_NAMESPACE::remove_const<const int>::type);
COMPILE_ASSERT_TYPES_EQ(int *, GOOGLE_NAMESPACE::remove_const<int * const>::type);
// TR1 examples.
COMPILE_ASSERT_TYPES_EQ(const int *, GOOGLE_NAMESPACE::remove_const<const int *>::type);
COMPILE_ASSERT_TYPES_EQ(volatile int,
GOOGLE_NAMESPACE::remove_const<const volatile int>::type);
}
static void TestRemoveVolatile() {
COMPILE_ASSERT_TYPES_EQ(int, GOOGLE_NAMESPACE::remove_volatile<int>::type);
COMPILE_ASSERT_TYPES_EQ(int, GOOGLE_NAMESPACE::remove_volatile<volatile int>::type);
COMPILE_ASSERT_TYPES_EQ(int *, GOOGLE_NAMESPACE::remove_volatile<int * volatile>::type);
// TR1 examples.
COMPILE_ASSERT_TYPES_EQ(volatile int *,
GOOGLE_NAMESPACE::remove_volatile<volatile int *>::type);
COMPILE_ASSERT_TYPES_EQ(const int,
GOOGLE_NAMESPACE::remove_volatile<const volatile int>::type);
}
static void TestRemoveReference() {
COMPILE_ASSERT_TYPES_EQ(int, GOOGLE_NAMESPACE::remove_reference<int>::type);
COMPILE_ASSERT_TYPES_EQ(int, GOOGLE_NAMESPACE::remove_reference<int&>::type);
COMPILE_ASSERT_TYPES_EQ(const int, GOOGLE_NAMESPACE::remove_reference<const int&>::type);
COMPILE_ASSERT_TYPES_EQ(int*, GOOGLE_NAMESPACE::remove_reference<int * &>::type);
}
static void TestRemoveCV() {
COMPILE_ASSERT_TYPES_EQ(int, GOOGLE_NAMESPACE::remove_cv<int>::type);
COMPILE_ASSERT_TYPES_EQ(int, GOOGLE_NAMESPACE::remove_cv<volatile int>::type);
COMPILE_ASSERT_TYPES_EQ(int, GOOGLE_NAMESPACE::remove_cv<const int>::type);
COMPILE_ASSERT_TYPES_EQ(int *, GOOGLE_NAMESPACE::remove_cv<int * const volatile>::type);
// TR1 examples.
COMPILE_ASSERT_TYPES_EQ(const volatile int *,
GOOGLE_NAMESPACE::remove_cv<const volatile int *>::type);
COMPILE_ASSERT_TYPES_EQ(int,
GOOGLE_NAMESPACE::remove_cv<const volatile int>::type);
}
static void TestIsSame() {
typedef int int32;
typedef long int64;
ASSERT_TRUE((GOOGLE_NAMESPACE::is_same<int32, int32>::value));
ASSERT_FALSE((GOOGLE_NAMESPACE::is_same<int32, int64>::value));
ASSERT_FALSE((GOOGLE_NAMESPACE::is_same<int64, int32>::value));
ASSERT_FALSE((GOOGLE_NAMESPACE::is_same<int, const int>::value));
ASSERT_TRUE((GOOGLE_NAMESPACE::is_same<void, void>::value));
ASSERT_FALSE((GOOGLE_NAMESPACE::is_same<void, int>::value));
ASSERT_FALSE((GOOGLE_NAMESPACE::is_same<int, void>::value));
ASSERT_TRUE((GOOGLE_NAMESPACE::is_same<int*, int*>::value));
ASSERT_TRUE((GOOGLE_NAMESPACE::is_same<void*, void*>::value));
ASSERT_FALSE((GOOGLE_NAMESPACE::is_same<int*, void*>::value));
ASSERT_FALSE((GOOGLE_NAMESPACE::is_same<void*, int*>::value));
ASSERT_FALSE((GOOGLE_NAMESPACE::is_same<void*, const void*>::value));
ASSERT_FALSE((GOOGLE_NAMESPACE::is_same<void*, void* const>::value));
ASSERT_TRUE((GOOGLE_NAMESPACE::is_same<Base*, Base*>::value));
ASSERT_TRUE((GOOGLE_NAMESPACE::is_same<Derived*, Derived*>::value));
ASSERT_FALSE((GOOGLE_NAMESPACE::is_same<Base*, Derived*>::value));
ASSERT_FALSE((GOOGLE_NAMESPACE::is_same<Derived*, Base*>::value));
}
static void TestIsConvertible() {
#ifndef _MSC_VER
ASSERT_TRUE((GOOGLE_NAMESPACE::is_convertible<int, int>::value));
ASSERT_TRUE((GOOGLE_NAMESPACE::is_convertible<int, long>::value));
ASSERT_TRUE((GOOGLE_NAMESPACE::is_convertible<long, int>::value));
ASSERT_TRUE((GOOGLE_NAMESPACE::is_convertible<int*, void*>::value));
ASSERT_FALSE((GOOGLE_NAMESPACE::is_convertible<void*, int*>::value));
ASSERT_TRUE((GOOGLE_NAMESPACE::is_convertible<Derived*, Base*>::value));
ASSERT_FALSE((GOOGLE_NAMESPACE::is_convertible<Base*, Derived*>::value));
ASSERT_TRUE((GOOGLE_NAMESPACE::is_convertible<Derived*, const Base*>::value));
ASSERT_FALSE((GOOGLE_NAMESPACE::is_convertible<const Derived*, Base*>::value));
#endif // #ifdef MSC_VER
}
}; // end class TypeTraitsTest
} // end anonymous namespace
int main(int argc, char **argv) {
TypeTraitsTest::TestIsInteger();
TypeTraitsTest::TestIsFloating();
TypeTraitsTest::TestIsReference();
TypeTraitsTest::TestIsPod();
TypeTraitsTest::TestHasTrivialCopy();
TypeTraitsTest::TestHasTrivialConstructor();
TypeTraitsTest::TestHasTrivialAssign();
TypeTraitsTest::TestHasTrivialDestructor();
TypeTraitsTest::TestRemovePointer();
TypeTraitsTest::TestRemoveConst();
TypeTraitsTest::TestRemoveVolatile();
TypeTraitsTest::TestRemoveReference();
TypeTraitsTest::TestRemoveCV();
TypeTraitsTest::TestIsSame();
TypeTraitsTest::TestIsConvertible();
printf("PASS\n");
return 0;
}