added iOS source code
[wl-app.git] / iOS / Pods / Realm / include / core / realm / util / type_traits.hpp
1 /*************************************************************************
2  *
3  * Copyright 2016 Realm Inc.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  **************************************************************************/
18
19 #ifndef REALM_UTIL_TYPE_TRAITS_HPP
20 #define REALM_UTIL_TYPE_TRAITS_HPP
21
22 #include <cstdint>
23 #include <climits>
24 #include <cwchar>
25 #include <limits>
26 #include <type_traits>
27
28 #include <realm/util/features.h>
29 #include <realm/util/assert.hpp>
30 #include <realm/util/type_list.hpp>
31
32 namespace realm {
33 namespace util {
34
35 template <class From, class To>
36 struct CopyConst {
37 private:
38     typedef typename std::remove_const<To>::type type_1;
39
40 public:
41     typedef typename std::conditional<std::is_const<From>::value, const type_1, type_1>::type type;
42 };
43
44
45 /// Member `type` is the type resulting from integral or
46 /// floating-point promotion of a value of type `T`.
47 ///
48 /// \note Enum types are supported only when the compiler supports the
49 /// C++11 'decltype' feature.
50 template <class T>
51 struct Promote;
52
53
54 /// Member `type` is the type of the result of a binary arithmetic (or
55 /// bitwise) operation (+, -, *, /, %, |, &, ^) when applied to
56 /// operands of type `A` and `B` respectively. The type of the result
57 /// of a shift operation (<<, >>) can instead be found as the type
58 /// resulting from integral promotion of the left operand. The type of
59 /// the result of a unary arithmetic (or bitwise) operation can be
60 /// found as the type resulting from integral promotion of the
61 /// operand.
62 ///
63 /// \note Enum types are supported only when the compiler supports the
64 /// C++11 'decltype' feature.
65 template <class A, class B>
66 struct ArithBinOpType;
67
68
69 /// Member `type` is `B` if `B` has more value bits than `A`,
70 /// otherwise is is `A`.
71 template <class A, class B>
72 struct ChooseWidestInt;
73
74
75 /// Member `type` is the first of `unsigned char`, `unsigned short`,
76 /// `unsigned int`, `unsigned long`, and `unsigned long long` that has
77 /// at least `bits` value bits.
78 template <int bits>
79 struct LeastUnsigned;
80
81
82 /// Member `type` is `unsigned` if `unsigned` has at least `bits`
83 /// value bits, otherwise it is the same as
84 /// `LeastUnsigned<bits>::%type`.
85 template <int bits>
86 struct FastestUnsigned;
87
88
89 // Implementation
90
91
92 template <class T>
93 struct Promote {
94     typedef decltype(+T()) type; // FIXME: This is not performing floating-point promotion.
95 };
96
97
98 template <class A, class B>
99 struct ArithBinOpType {
100     typedef decltype(A() + B()) type;
101 };
102
103
104 template <class A, class B>
105 struct ChooseWidestInt {
106 private:
107     typedef std::numeric_limits<A> lim_a;
108     typedef std::numeric_limits<B> lim_b;
109     static_assert(lim_a::is_specialized && lim_b::is_specialized,
110                   "std::numeric_limits<> must be specialized for both types");
111     static_assert(lim_a::is_integer && lim_b::is_integer, "Both types must be integers");
112
113 public:
114     typedef typename std::conditional<(lim_a::digits >= lim_b::digits), A, B>::type type;
115 };
116
117
118 template <int bits>
119 struct LeastUnsigned {
120 private:
121     typedef void types_0;
122     typedef TypeAppend<types_0, unsigned char>::type types_1;
123     typedef TypeAppend<types_1, unsigned short>::type types_2;
124     typedef TypeAppend<types_2, unsigned int>::type types_3;
125     typedef TypeAppend<types_3, unsigned long>::type types_4;
126     typedef TypeAppend<types_4, unsigned long long>::type types_5;
127     typedef types_5 types;
128     // The `dummy<>` template is there to work around a bug in
129     // VisualStudio (seen in versions 2010 and 2012). Without the
130     // `dummy<>` template, The C++ compiler in Visual Studio would
131     // attempt to instantiate `FindType<type, pred>` before the
132     // instantiation of `LeastUnsigned<>` which obviously fails
133     // because `pred` depends on `bits`.
134     template <int>
135     struct dummy {
136         template <class T>
137         struct pred {
138             static const bool value = std::numeric_limits<T>::digits >= bits;
139         };
140     };
141
142 public:
143     typedef typename FindType<types, dummy<bits>::template pred>::type type;
144     static_assert(!(std::is_same<type, void>::value), "No unsigned type is that wide");
145 };
146
147
148 template <int bits>
149 struct FastestUnsigned {
150 private:
151     typedef typename util::LeastUnsigned<bits>::type least_unsigned;
152
153 public:
154     typedef typename util::ChooseWidestInt<unsigned, least_unsigned>::type type;
155 };
156
157
158 } // namespace util
159 } // namespace realm
160
161 #endif // REALM_UTIL_TYPE_TRAITS_HPP