1ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Copyright (c) 2006, Google Inc.
2ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// All rights reserved.
3ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//
4ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Redistribution and use in source and binary forms, with or without
5ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// modification, are permitted provided that the following conditions are
6ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// met:
7ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//
8ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//     * Redistributions of source code must retain the above copyright
9ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// notice, this list of conditions and the following disclaimer.
10ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//     * Redistributions in binary form must reproduce the above
11ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// copyright notice, this list of conditions and the following disclaimer
12ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// in the documentation and/or other materials provided with the
13ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// distribution.
14ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//     * Neither the name of Google Inc. nor the names of its
15ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// contributors may be used to endorse or promote products derived from
16ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// this software without specific prior written permission.
17ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//
18ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
30ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// ----
31ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Author: Matt Austern
32ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//
33ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// This code is compiled directly on many platforms, including client
34ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// platforms like Windows, Mac, and embedded systems.  Before making
35ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// any changes here, make sure that you're not breaking any platforms.
36ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//
37ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Define a small subset of tr1 type traits. The traits we define are:
38ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//   is_integral
39ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//   is_floating_point
40ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//   is_pointer
41ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//   is_enum
42ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//   is_reference
43ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//   is_pod
44ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//   has_trivial_constructor
45ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//   has_trivial_copy
46ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//   has_trivial_assign
47ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//   has_trivial_destructor
48ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//   remove_const
49ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//   remove_volatile
50ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//   remove_cv
51ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//   remove_reference
52ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//   add_reference
53ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//   remove_pointer
54ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//   is_same
55ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//   is_convertible
56ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// We can add more type traits as required.
57ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
58ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#ifndef GOOGLE_PROTOBUF_TYPE_TRAITS_H_
59ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#define GOOGLE_PROTOBUF_TYPE_TRAITS_H_
60ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
61ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include <utility>                  // For pair
62ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
63ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include <google/protobuf/stubs/template_util.h>  // For true_type and false_type
64ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
65ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochnamespace google {
66ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochnamespace protobuf {
67ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochnamespace internal {
68ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
69ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct is_integral;
70ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct is_floating_point;
71ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct is_pointer;
72ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// MSVC can't compile this correctly, and neither can gcc 3.3.5 (at least)
73ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
74ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// is_enum uses is_convertible, which is not available on MSVC.
75ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct is_enum;
76ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#endif
77ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct is_reference;
78ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct is_pod;
79ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct has_trivial_constructor;
80ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct has_trivial_copy;
81ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct has_trivial_assign;
82ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct has_trivial_destructor;
83ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct remove_const;
84ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct remove_volatile;
85ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct remove_cv;
86ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct remove_reference;
87ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct add_reference;
88ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct remove_pointer;
89ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T, class U> struct is_same;
90ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
91ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class From, class To> struct is_convertible;
92ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#endif
93ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
94ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// is_integral is false except for the built-in integer types. A
95ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// cv-qualified type is integral if and only if the underlying type is.
96ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct is_integral : false_type { };
97ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<> struct is_integral<bool> : true_type { };
98ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<> struct is_integral<char> : true_type { };
99ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<> struct is_integral<unsigned char> : true_type { };
100ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<> struct is_integral<signed char> : true_type { };
101ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#if defined(_MSC_VER)
102ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// wchar_t is not by default a distinct type from unsigned short in
103ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Microsoft C.
104ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// See http://msdn2.microsoft.com/en-us/library/dh8che7s(VS.80).aspx
105ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<> struct is_integral<__wchar_t> : true_type { };
106ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#else
107ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<> struct is_integral<wchar_t> : true_type { };
108ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#endif
109ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<> struct is_integral<short> : true_type { };
110ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<> struct is_integral<unsigned short> : true_type { };
111ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<> struct is_integral<int> : true_type { };
112ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<> struct is_integral<unsigned int> : true_type { };
113ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<> struct is_integral<long> : true_type { };
114ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<> struct is_integral<unsigned long> : true_type { };
115ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#ifdef HAVE_LONG_LONG
116ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<> struct is_integral<long long> : true_type { };
117ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<> struct is_integral<unsigned long long> : true_type { };
118ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#endif
119ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct is_integral<const T> : is_integral<T> { };
120ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct is_integral<volatile T> : is_integral<T> { };
121ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct is_integral<const volatile T> : is_integral<T> { };
122ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
123ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// is_floating_point is false except for the built-in floating-point types.
124ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// A cv-qualified type is integral if and only if the underlying type is.
125ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct is_floating_point : false_type { };
126ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<> struct is_floating_point<float> : true_type { };
127ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<> struct is_floating_point<double> : true_type { };
128ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<> struct is_floating_point<long double> : true_type { };
129ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct is_floating_point<const T>
130ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    : is_floating_point<T> { };
131ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct is_floating_point<volatile T>
132ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    : is_floating_point<T> { };
133ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct is_floating_point<const volatile T>
134ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    : is_floating_point<T> { };
135ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
136ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// is_pointer is false except for pointer types. A cv-qualified type (e.g.
137ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// "int* const", as opposed to "int const*") is cv-qualified if and only if
138ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// the underlying type is.
139ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct is_pointer : false_type { };
140ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct is_pointer<T*> : true_type { };
141ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct is_pointer<const T> : is_pointer<T> { };
142ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct is_pointer<volatile T> : is_pointer<T> { };
143ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct is_pointer<const volatile T> : is_pointer<T> { };
144ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
145ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
146ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
147ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochnamespace internal {
148ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
149ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct is_class_or_union {
150ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  template <class U> static small_ tester(void (U::*)());
151ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  template <class U> static big_ tester(...);
152ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  static const bool value = sizeof(tester<T>(0)) == sizeof(small_);
153ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch};
154ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
155ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// is_convertible chokes if the first argument is an array. That's why
156ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// we use add_reference here.
157ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <bool NotUnum, class T> struct is_enum_impl
158ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    : is_convertible<typename add_reference<T>::type, int> { };
159ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
160ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct is_enum_impl<true, T> : false_type { };
161ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
162ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}  // namespace internal
163ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
164ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Specified by TR1 [4.5.1] primary type categories.
165ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
166ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Implementation note:
167ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//
168ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Each type is either void, integral, floating point, array, pointer,
169ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// reference, member object pointer, member function pointer, enum,
170ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// union or class. Out of these, only integral, floating point, reference,
171ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// class and enum types are potentially convertible to int. Therefore,
172ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// if a type is not a reference, integral, floating point or class and
173ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// is convertible to int, it's a enum. Adding cv-qualification to a type
174ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// does not change whether it's an enum.
175ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//
176ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Is-convertible-to-int check is done only if all other checks pass,
177ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// because it can't be used with some types (e.g. void or classes with
178ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// inaccessible conversion operators).
179ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct is_enum
180ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    : internal::is_enum_impl<
181ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          is_same<T, void>::value ||
182ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch              is_integral<T>::value ||
183ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch              is_floating_point<T>::value ||
184ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch              is_reference<T>::value ||
185ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch              internal::is_class_or_union<T>::value,
186ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          T> { };
187ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
188ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct is_enum<const T> : is_enum<T> { };
189ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct is_enum<volatile T> : is_enum<T> { };
190ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct is_enum<const volatile T> : is_enum<T> { };
191ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
192ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#endif
193ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
194ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// is_reference is false except for reference types.
195ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<typename T> struct is_reference : false_type {};
196ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<typename T> struct is_reference<T&> : true_type {};
197ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
198ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
199ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// We can't get is_pod right without compiler help, so fail conservatively.
200ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// We will assume it's false except for arithmetic types, enumerations,
201ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// pointers and cv-qualified versions thereof. Note that std::pair<T,U>
202ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// is not a POD even if T and U are PODs.
203ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct is_pod
204ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch : integral_constant<bool, (is_integral<T>::value ||
205ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                            is_floating_point<T>::value ||
206ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
207ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                            // is_enum is not available on MSVC.
208ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                            is_enum<T>::value ||
209ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#endif
210ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                            is_pointer<T>::value)> { };
211ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct is_pod<const T> : is_pod<T> { };
212ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct is_pod<volatile T> : is_pod<T> { };
213ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct is_pod<const volatile T> : is_pod<T> { };
214ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
215ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
216ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// We can't get has_trivial_constructor right without compiler help, so
217ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// fail conservatively. We will assume it's false except for: (1) types
218ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// for which is_pod is true. (2) std::pair of types with trivial
219ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// constructors. (3) array of a type with a trivial constructor.
220ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// (4) const versions thereof.
221ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct has_trivial_constructor : is_pod<T> { };
222ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T, class U> struct has_trivial_constructor<std::pair<T, U> >
223ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  : integral_constant<bool,
224ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                      (has_trivial_constructor<T>::value &&
225ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                       has_trivial_constructor<U>::value)> { };
226ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class A, int N> struct has_trivial_constructor<A[N]>
227ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  : has_trivial_constructor<A> { };
228ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct has_trivial_constructor<const T>
229ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  : has_trivial_constructor<T> { };
230ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
231ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// We can't get has_trivial_copy right without compiler help, so fail
232ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// conservatively. We will assume it's false except for: (1) types
233ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// for which is_pod is true. (2) std::pair of types with trivial copy
234ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// constructors. (3) array of a type with a trivial copy constructor.
235ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// (4) const versions thereof.
236ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct has_trivial_copy : is_pod<T> { };
237ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T, class U> struct has_trivial_copy<std::pair<T, U> >
238ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  : integral_constant<bool,
239ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                      (has_trivial_copy<T>::value &&
240ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                       has_trivial_copy<U>::value)> { };
241ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class A, int N> struct has_trivial_copy<A[N]>
242ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  : has_trivial_copy<A> { };
243ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct has_trivial_copy<const T> : has_trivial_copy<T> { };
244ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
245ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// We can't get has_trivial_assign right without compiler help, so fail
246ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// conservatively. We will assume it's false except for: (1) types
247ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// for which is_pod is true. (2) std::pair of types with trivial copy
248ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// constructors. (3) array of a type with a trivial assign constructor.
249ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct has_trivial_assign : is_pod<T> { };
250ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T, class U> struct has_trivial_assign<std::pair<T, U> >
251ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  : integral_constant<bool,
252ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                      (has_trivial_assign<T>::value &&
253ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                       has_trivial_assign<U>::value)> { };
254ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class A, int N> struct has_trivial_assign<A[N]>
255ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  : has_trivial_assign<A> { };
256ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
257ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// We can't get has_trivial_destructor right without compiler help, so
258ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// fail conservatively. We will assume it's false except for: (1) types
259ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// for which is_pod is true. (2) std::pair of types with trivial
260ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// destructors. (3) array of a type with a trivial destructor.
261ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// (4) const versions thereof.
262ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct has_trivial_destructor : is_pod<T> { };
263ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T, class U> struct has_trivial_destructor<std::pair<T, U> >
264ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  : integral_constant<bool,
265ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                      (has_trivial_destructor<T>::value &&
266ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                       has_trivial_destructor<U>::value)> { };
267ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class A, int N> struct has_trivial_destructor<A[N]>
268ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  : has_trivial_destructor<A> { };
269ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <class T> struct has_trivial_destructor<const T>
270ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  : has_trivial_destructor<T> { };
271ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
272ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Specified by TR1 [4.7.1]
273ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<typename T> struct remove_const { typedef T type; };
274ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<typename T> struct remove_const<T const> { typedef T type; };
275ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<typename T> struct remove_volatile { typedef T type; };
276ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<typename T> struct remove_volatile<T volatile> { typedef T type; };
277ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<typename T> struct remove_cv {
278ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  typedef typename remove_const<typename remove_volatile<T>::type>::type type;
279ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch};
280ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
281ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
282ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Specified by TR1 [4.7.2] Reference modifications.
283ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<typename T> struct remove_reference { typedef T type; };
284ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<typename T> struct remove_reference<T&> { typedef T type; };
285ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
286ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <typename T> struct add_reference { typedef T& type; };
287ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <typename T> struct add_reference<T&> { typedef T& type; };
288ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
289ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Specified by TR1 [4.7.4] Pointer modifications.
290ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<typename T> struct remove_pointer { typedef T type; };
291ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<typename T> struct remove_pointer<T*> { typedef T type; };
292ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<typename T> struct remove_pointer<T* const> { typedef T type; };
293ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<typename T> struct remove_pointer<T* volatile> { typedef T type; };
294ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<typename T> struct remove_pointer<T* const volatile> {
295ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  typedef T type; };
296ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
297ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Specified by TR1 [4.6] Relationships between types
298ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<typename T, typename U> struct is_same : public false_type { };
299ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate<typename T> struct is_same<T, T> : public true_type { };
300ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
301ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Specified by TR1 [4.6] Relationships between types
302ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
303ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochnamespace internal {
304ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
305ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// This class is an implementation detail for is_convertible, and you
306ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// don't need to know how it works to use is_convertible. For those
307ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// who care: we declare two different functions, one whose argument is
308ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// of type To and one with a variadic argument list. We give them
309ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// return types of different size, so we can use sizeof to trick the
310ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// compiler into telling us which function it would have chosen if we
311ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// had called it with an argument of type From.  See Alexandrescu's
312ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// _Modern C++ Design_ for more details on this sort of trick.
313ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
314ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <typename From, typename To>
315ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochstruct ConvertHelper {
316ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  static small_ Test(To);
317ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  static big_ Test(...);
318ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  static From Create();
319ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch};
320ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}  // namespace internal
321ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
322ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Inherits from true_type if From is convertible to To, false_type otherwise.
323ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <typename From, typename To>
324ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochstruct is_convertible
325ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    : integral_constant<bool,
326ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                        sizeof(internal::ConvertHelper<From, To>::Test(
327ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                  internal::ConvertHelper<From, To>::Create()))
328ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                        == sizeof(small_)> {
329ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch};
330ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#endif
331ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
332ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}  // namespace internal
333ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}  // namespace protobuf
334ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}  // namespace google
335ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
336ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#endif  // GOOGLE_PROTOBUF_TYPE_TRAITS_H_
337