// 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 #include // for exit() #include #include #include #include #include typedef int int32; // IBM AIX typedefs `int64` in `sys/inttypes.h`, included transitively above. #ifndef _AIX typedef long int64; #endif using std::string; using std::vector; using std::pair; // This assertion produces errors like "error: invalid use of // incomplete type 'struct ::AssertTypesEq'" // when it fails. template struct AssertTypesEq; template struct AssertTypesEq {}; #define COMPILE_ASSERT_TYPES_EQ(T, U) static_cast(AssertTypesEq()) // 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_; }; namespace google { namespace protobuf { namespace internal { template<> struct has_trivial_copy : true_type { }; } // namespace internal } // namespace protobuf } // namespace google // 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_; }; namespace google { namespace protobuf { namespace internal { template<> struct has_trivial_assign : true_type { }; } // namespace internal } // namespace protobuf } // namespace google // 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_; }; namespace google { namespace protobuf { namespace internal { template<> struct has_trivial_constructor : true_type { }; } // namespace internal } // namespace protobuf } // namespace google // 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_; }; namespace google { namespace protobuf { namespace internal { template<> struct has_trivial_destructor : true_type { }; } // namespace internal } // namespace protobuf } // namespace google enum G {}; union H {}; class I { public: operator int() const; }; class J { private: operator int() const; }; namespace google { namespace protobuf { namespace internal { namespace { // 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 { }; TEST(TypeTraitsTest, TestIsInteger) { // Verify that is_integral is true for all integer types. EXPECT_TRUE(is_integral::value); EXPECT_TRUE(is_integral::value); EXPECT_TRUE(is_integral::value); EXPECT_TRUE(is_integral::value); EXPECT_TRUE(is_integral::value); EXPECT_TRUE(is_integral::value); EXPECT_TRUE(is_integral::value); EXPECT_TRUE(is_integral::value); EXPECT_TRUE(is_integral::value); EXPECT_TRUE(is_integral::value); EXPECT_TRUE(is_integral::value); // Verify that is_integral is false for a few non-integer types. EXPECT_FALSE(is_integral::value); EXPECT_FALSE(is_integral::value); EXPECT_FALSE(is_integral::value); EXPECT_FALSE(is_integral::value); EXPECT_FALSE(is_integral::value); EXPECT_FALSE((is_integral >::value)); // Verify that cv-qualified integral types are still integral, and // cv-qualified non-integral types are still non-integral. EXPECT_TRUE(is_integral::value); EXPECT_TRUE(is_integral::value); EXPECT_TRUE(is_integral::value); EXPECT_FALSE(is_integral::value); EXPECT_FALSE(is_integral::value); EXPECT_FALSE(is_integral::value); } TEST(TypeTraitsTest, TestIsFloating) { // Verify that is_floating_point is true for all floating-point types. EXPECT_TRUE(is_floating_point::value); EXPECT_TRUE(is_floating_point::value); EXPECT_TRUE(is_floating_point::value); // Verify that is_floating_point is false for a few non-float types. EXPECT_FALSE(is_floating_point::value); EXPECT_FALSE(is_floating_point::value); EXPECT_FALSE(is_floating_point::value); EXPECT_FALSE(is_floating_point::value); EXPECT_FALSE(is_floating_point::value); EXPECT_FALSE((is_floating_point >::value)); // Verify that cv-qualified floating point types are still floating, and // cv-qualified non-floating types are still non-floating. EXPECT_TRUE(is_floating_point::value); EXPECT_TRUE(is_floating_point::value); EXPECT_TRUE(is_floating_point::value); EXPECT_FALSE(is_floating_point::value); EXPECT_FALSE(is_floating_point::value); EXPECT_FALSE(is_floating_point::value); } TEST(TypeTraitsTest, TestIsPointer) { // Verify that is_pointer is true for some pointer types. EXPECT_TRUE(is_pointer::value); EXPECT_TRUE(is_pointer::value); EXPECT_TRUE(is_pointer::value); EXPECT_TRUE(is_pointer::value); EXPECT_TRUE(is_pointer::value); // Verify that is_pointer is false for some non-pointer types. EXPECT_FALSE(is_pointer::value); EXPECT_FALSE(is_pointer::value); EXPECT_FALSE(is_pointer::value); EXPECT_FALSE(is_pointer >::value); EXPECT_FALSE(is_pointer::value); // A function pointer is a pointer, but a function type, or a function // reference type, is not. EXPECT_TRUE(is_pointer::value); EXPECT_FALSE(is_pointer::value); EXPECT_FALSE(is_pointer::value); // Verify that is_pointer is true for some cv-qualified pointer types, // and false for some cv-qualified non-pointer types. EXPECT_TRUE(is_pointer::value); EXPECT_TRUE(is_pointer::value); EXPECT_TRUE(is_pointer::value); EXPECT_FALSE(is_pointer::value); EXPECT_FALSE(is_pointer >::value); EXPECT_FALSE(is_pointer::value); } TEST(TypeTraitsTest, TestIsEnum) { // is_enum isn't supported on MSVC or gcc 3.x #if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) // Verify that is_enum is true for enum types. EXPECT_TRUE(is_enum::value); EXPECT_TRUE(is_enum::value); EXPECT_TRUE(is_enum::value); EXPECT_TRUE(is_enum::value); // Verify that is_enum is false for a few non-enum types. EXPECT_FALSE(is_enum::value); EXPECT_FALSE(is_enum::value); EXPECT_FALSE(is_enum::value); EXPECT_FALSE(is_enum::value); EXPECT_FALSE(is_enum::value); EXPECT_FALSE(is_enum::value); EXPECT_FALSE(is_enum::value); EXPECT_FALSE(is_enum::value); EXPECT_FALSE(is_enum::value); EXPECT_FALSE(is_enum::value); EXPECT_FALSE(is_enum::value); EXPECT_FALSE(is_enum::value); EXPECT_FALSE(is_enum::value); EXPECT_FALSE(is_enum::value); EXPECT_FALSE(is_enum::value); EXPECT_FALSE(is_enum::value); EXPECT_FALSE(is_enum::value); #endif } TEST(TypeTraitsTest, TestIsReference) { // Verifies that is_reference is true for all reference types. typedef float& RefFloat; EXPECT_TRUE(is_reference::value); EXPECT_TRUE(is_reference::value); EXPECT_TRUE(is_reference::value); EXPECT_TRUE(is_reference::value); EXPECT_TRUE(is_reference::value); EXPECT_TRUE(is_reference::value); EXPECT_TRUE(is_reference::value); EXPECT_TRUE(is_reference::value); // Verifies that is_reference is false for all non-reference types. EXPECT_FALSE(is_reference::value); EXPECT_FALSE(is_reference::value); EXPECT_FALSE(is_reference::value); EXPECT_FALSE(is_reference::value); EXPECT_FALSE(is_reference::value); EXPECT_FALSE(is_reference::value); EXPECT_FALSE(is_reference::value); } TEST(TypeTraitsTest, TestAddReference) { COMPILE_ASSERT_TYPES_EQ(int&, add_reference::type); COMPILE_ASSERT_TYPES_EQ(const int&, add_reference::type); COMPILE_ASSERT_TYPES_EQ(volatile int&, add_reference::type); COMPILE_ASSERT_TYPES_EQ(const volatile int&, add_reference::type); COMPILE_ASSERT_TYPES_EQ(int&, add_reference::type); COMPILE_ASSERT_TYPES_EQ(const int&, add_reference::type); COMPILE_ASSERT_TYPES_EQ(volatile int&, add_reference::type); COMPILE_ASSERT_TYPES_EQ(const volatile int&, add_reference::type); } TEST(TypeTraitsTest, TestIsPod) { // Verify that arithmetic types and pointers are marked as PODs. EXPECT_TRUE(is_pod::value); EXPECT_TRUE(is_pod::value); EXPECT_TRUE(is_pod::value); EXPECT_TRUE(is_pod::value); EXPECT_TRUE(is_pod::value); EXPECT_TRUE(is_pod::value); EXPECT_TRUE(is_pod::value); EXPECT_TRUE(is_pod::value); EXPECT_TRUE(is_pod::value); EXPECT_TRUE(is_pod::value); EXPECT_TRUE(is_pod::value); EXPECT_TRUE(is_pod::value); EXPECT_TRUE(is_pod::value); EXPECT_TRUE(is_pod::value); EXPECT_TRUE(is_pod::value); EXPECT_TRUE(is_pod::value); EXPECT_TRUE(is_pod::value); EXPECT_TRUE(is_pod::value); EXPECT_TRUE(is_pod::value); EXPECT_TRUE(is_pod::value); EXPECT_TRUE(is_pod::value); #if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) EXPECT_TRUE(is_pod::value); EXPECT_TRUE(is_pod::value); EXPECT_TRUE(is_pod::value); EXPECT_TRUE(is_pod::value); #endif // Verify that some non-POD types are not marked as PODs. EXPECT_FALSE(is_pod::value); EXPECT_FALSE(is_pod::value); EXPECT_FALSE((is_pod >::value)); EXPECT_FALSE(is_pod::value); EXPECT_FALSE(is_pod::value); EXPECT_FALSE(is_pod::value); EXPECT_FALSE(is_pod::value); EXPECT_FALSE(is_pod::value); EXPECT_FALSE(is_pod::value); } TEST(TypeTraitsTest, TestHasTrivialConstructor) { // Verify that arithmetic types and pointers have trivial constructors. EXPECT_TRUE(has_trivial_constructor::value); EXPECT_TRUE(has_trivial_constructor::value); EXPECT_TRUE(has_trivial_constructor::value); EXPECT_TRUE(has_trivial_constructor::value); EXPECT_TRUE(has_trivial_constructor::value); EXPECT_TRUE(has_trivial_constructor::value); EXPECT_TRUE(has_trivial_constructor::value); EXPECT_TRUE(has_trivial_constructor::value); EXPECT_TRUE(has_trivial_constructor::value); EXPECT_TRUE(has_trivial_constructor::value); EXPECT_TRUE(has_trivial_constructor::value); EXPECT_TRUE(has_trivial_constructor::value); EXPECT_TRUE(has_trivial_constructor::value); EXPECT_TRUE(has_trivial_constructor::value); EXPECT_TRUE(has_trivial_constructor::value); EXPECT_TRUE(has_trivial_constructor::value); EXPECT_TRUE(has_trivial_constructor::value); EXPECT_TRUE(has_trivial_constructor::value); // Verify that pairs and arrays of such types have trivial // constructors. typedef int int10[10]; EXPECT_TRUE((has_trivial_constructor >::value)); EXPECT_TRUE(has_trivial_constructor::value); // Verify that pairs of types without trivial constructors // are not marked as trivial. EXPECT_FALSE((has_trivial_constructor >::value)); EXPECT_FALSE((has_trivial_constructor >::value)); // Verify that types without trivial constructors are // correctly marked as such. EXPECT_FALSE(has_trivial_constructor::value); EXPECT_FALSE(has_trivial_constructor >::value); // Verify that E, which we have declared to have a trivial // constructor, is correctly marked as such. EXPECT_TRUE(has_trivial_constructor::value); } TEST(TypeTraitsTest, TestHasTrivialCopy) { // Verify that arithmetic types and pointers have trivial copy // constructors. EXPECT_TRUE(has_trivial_copy::value); EXPECT_TRUE(has_trivial_copy::value); EXPECT_TRUE(has_trivial_copy::value); EXPECT_TRUE(has_trivial_copy::value); EXPECT_TRUE(has_trivial_copy::value); EXPECT_TRUE(has_trivial_copy::value); EXPECT_TRUE(has_trivial_copy::value); EXPECT_TRUE(has_trivial_copy::value); EXPECT_TRUE(has_trivial_copy::value); EXPECT_TRUE(has_trivial_copy::value); EXPECT_TRUE(has_trivial_copy::value); EXPECT_TRUE(has_trivial_copy::value); EXPECT_TRUE(has_trivial_copy::value); EXPECT_TRUE(has_trivial_copy::value); EXPECT_TRUE(has_trivial_copy::value); EXPECT_TRUE(has_trivial_copy::value); EXPECT_TRUE(has_trivial_copy::value); EXPECT_TRUE(has_trivial_copy::value); // Verify that pairs and arrays of such types have trivial // copy constructors. typedef int int10[10]; EXPECT_TRUE((has_trivial_copy >::value)); EXPECT_TRUE(has_trivial_copy::value); // Verify that pairs of types without trivial copy constructors // are not marked as trivial. EXPECT_FALSE((has_trivial_copy >::value)); EXPECT_FALSE((has_trivial_copy >::value)); // Verify that types without trivial copy constructors are // correctly marked as such. EXPECT_FALSE(has_trivial_copy::value); EXPECT_FALSE(has_trivial_copy >::value); // Verify that C, which we have declared to have a trivial // copy constructor, is correctly marked as such. EXPECT_TRUE(has_trivial_copy::value); } TEST(TypeTraitsTest, TestHasTrivialAssign) { // Verify that arithmetic types and pointers have trivial assignment // operators. EXPECT_TRUE(has_trivial_assign::value); EXPECT_TRUE(has_trivial_assign::value); EXPECT_TRUE(has_trivial_assign::value); EXPECT_TRUE(has_trivial_assign::value); EXPECT_TRUE(has_trivial_assign::value); EXPECT_TRUE(has_trivial_assign::value); EXPECT_TRUE(has_trivial_assign::value); EXPECT_TRUE(has_trivial_assign::value); EXPECT_TRUE(has_trivial_assign::value); EXPECT_TRUE(has_trivial_assign::value); EXPECT_TRUE(has_trivial_assign::value); EXPECT_TRUE(has_trivial_assign::value); EXPECT_TRUE(has_trivial_assign::value); EXPECT_TRUE(has_trivial_assign::value); EXPECT_TRUE(has_trivial_assign::value); EXPECT_TRUE(has_trivial_assign::value); EXPECT_TRUE(has_trivial_assign::value); EXPECT_TRUE(has_trivial_assign::value); // Verify that pairs and arrays of such types have trivial // assignment operators. typedef int int10[10]; EXPECT_TRUE((has_trivial_assign >::value)); EXPECT_TRUE(has_trivial_assign::value); // Verify that pairs of types without trivial assignment operators // are not marked as trivial. EXPECT_FALSE((has_trivial_assign >::value)); EXPECT_FALSE((has_trivial_assign >::value)); // Verify that types without trivial assignment operators are // correctly marked as such. EXPECT_FALSE(has_trivial_assign::value); EXPECT_FALSE(has_trivial_assign >::value); // Verify that D, which we have declared to have a trivial // assignment operator, is correctly marked as such. EXPECT_TRUE(has_trivial_assign::value); } TEST(TypeTraitsTest, TestHasTrivialDestructor) { // Verify that arithmetic types and pointers have trivial destructors. EXPECT_TRUE(has_trivial_destructor::value); EXPECT_TRUE(has_trivial_destructor::value); EXPECT_TRUE(has_trivial_destructor::value); EXPECT_TRUE(has_trivial_destructor::value); EXPECT_TRUE(has_trivial_destructor::value); EXPECT_TRUE(has_trivial_destructor::value); EXPECT_TRUE(has_trivial_destructor::value); EXPECT_TRUE(has_trivial_destructor::value); EXPECT_TRUE(has_trivial_destructor::value); EXPECT_TRUE(has_trivial_destructor::value); EXPECT_TRUE(has_trivial_destructor::value); EXPECT_TRUE(has_trivial_destructor::value); EXPECT_TRUE(has_trivial_destructor::value); EXPECT_TRUE(has_trivial_destructor::value); EXPECT_TRUE(has_trivial_destructor::value); EXPECT_TRUE(has_trivial_destructor::value); EXPECT_TRUE(has_trivial_destructor::value); EXPECT_TRUE(has_trivial_destructor::value); // Verify that pairs and arrays of such types have trivial // destructors. typedef int int10[10]; EXPECT_TRUE((has_trivial_destructor >::value)); EXPECT_TRUE(has_trivial_destructor::value); // Verify that pairs of types without trivial destructors // are not marked as trivial. EXPECT_FALSE((has_trivial_destructor >::value)); EXPECT_FALSE((has_trivial_destructor >::value)); // Verify that types without trivial destructors are // correctly marked as such. EXPECT_FALSE(has_trivial_destructor::value); EXPECT_FALSE(has_trivial_destructor >::value); // Verify that F, which we have declared to have a trivial // destructor, is correctly marked as such. EXPECT_TRUE(has_trivial_destructor::value); } // Tests remove_pointer. TEST(TypeTraitsTest, TestRemovePointer) { COMPILE_ASSERT_TYPES_EQ(int, remove_pointer::type); COMPILE_ASSERT_TYPES_EQ(int, remove_pointer::type); COMPILE_ASSERT_TYPES_EQ(const int, remove_pointer::type); COMPILE_ASSERT_TYPES_EQ(int, remove_pointer::type); COMPILE_ASSERT_TYPES_EQ(int, remove_pointer::type); } TEST(TypeTraitsTest, TestRemoveConst) { COMPILE_ASSERT_TYPES_EQ(int, remove_const::type); COMPILE_ASSERT_TYPES_EQ(int, remove_const::type); COMPILE_ASSERT_TYPES_EQ(int *, remove_const::type); // TR1 examples. COMPILE_ASSERT_TYPES_EQ(const int *, remove_const::type); COMPILE_ASSERT_TYPES_EQ(volatile int, remove_const::type); } TEST(TypeTraitsTest, TestRemoveVolatile) { COMPILE_ASSERT_TYPES_EQ(int, remove_volatile::type); COMPILE_ASSERT_TYPES_EQ(int, remove_volatile::type); COMPILE_ASSERT_TYPES_EQ(int *, remove_volatile::type); // TR1 examples. COMPILE_ASSERT_TYPES_EQ(volatile int *, remove_volatile::type); COMPILE_ASSERT_TYPES_EQ(const int, remove_volatile::type); } TEST(TypeTraitsTest, TestRemoveCV) { COMPILE_ASSERT_TYPES_EQ(int, remove_cv::type); COMPILE_ASSERT_TYPES_EQ(int, remove_cv::type); COMPILE_ASSERT_TYPES_EQ(int, remove_cv::type); COMPILE_ASSERT_TYPES_EQ(int *, remove_cv::type); // TR1 examples. COMPILE_ASSERT_TYPES_EQ(const volatile int *, remove_cv::type); COMPILE_ASSERT_TYPES_EQ(int, remove_cv::type); } TEST(TypeTraitsTest, TestRemoveReference) { COMPILE_ASSERT_TYPES_EQ(int, remove_reference::type); COMPILE_ASSERT_TYPES_EQ(int, remove_reference::type); COMPILE_ASSERT_TYPES_EQ(const int, remove_reference::type); COMPILE_ASSERT_TYPES_EQ(int*, remove_reference::type); } TEST(TypeTraitsTest, TestIsSame) { EXPECT_TRUE((is_same::value)); EXPECT_FALSE((is_same::value)); EXPECT_FALSE((is_same::value)); EXPECT_FALSE((is_same::value)); EXPECT_TRUE((is_same::value)); EXPECT_FALSE((is_same::value)); EXPECT_FALSE((is_same::value)); EXPECT_TRUE((is_same::value)); EXPECT_TRUE((is_same::value)); EXPECT_FALSE((is_same::value)); EXPECT_FALSE((is_same::value)); EXPECT_FALSE((is_same::value)); EXPECT_FALSE((is_same::value)); EXPECT_TRUE((is_same::value)); EXPECT_TRUE((is_same::value)); EXPECT_FALSE((is_same::value)); EXPECT_FALSE((is_same::value)); } TEST(TypeTraitsTest, TestConvertible) { #if !(defined(__GNUC__) && __GNUC__ <= 3) EXPECT_TRUE((is_convertible::value)); EXPECT_TRUE((is_convertible::value)); EXPECT_TRUE((is_convertible::value)); EXPECT_TRUE((is_convertible::value)); EXPECT_FALSE((is_convertible::value)); EXPECT_TRUE((is_convertible::value)); EXPECT_FALSE((is_convertible::value)); EXPECT_TRUE((is_convertible::value)); EXPECT_FALSE((is_convertible::value)); #endif } } // anonymous namespace } // namespace internal } // namespace protobuf } // namespace google