1 | // Copyright 2005 Alexander Nasonov. |
2 | // Distributed under the Boost Software License, Version 1.0. (See |
3 | // accompanying file LICENSE_1_0.txt or copy at |
4 | // http://www.boost.org/LICENSE_1_0.txt) |
5 | |
6 | #ifndef FILE_boost_type_traits_integral_promotion_hpp_INCLUDED |
7 | #define FILE_boost_type_traits_integral_promotion_hpp_INCLUDED |
8 | |
9 | #include <boost/config.hpp> |
10 | |
11 | #include <boost/mpl/eval_if.hpp> |
12 | #include <boost/mpl/identity.hpp> |
13 | #include <boost/type_traits/integral_constant.hpp> |
14 | #include <boost/type_traits/is_const.hpp> |
15 | #include <boost/type_traits/is_enum.hpp> |
16 | #include <boost/type_traits/is_volatile.hpp> |
17 | #include <boost/type_traits/remove_cv.hpp> |
18 | |
19 | // Should be the last #include |
20 | #include <boost/type_traits/detail/type_trait_def.hpp> |
21 | |
22 | namespace boost { |
23 | |
24 | namespace type_traits { namespace detail { |
25 | |
26 | // 4.5/2 |
27 | template <class T> struct need_promotion : public boost::is_enum<T> {}; |
28 | |
29 | // 4.5/1 |
30 | template<> struct need_promotion<char > : public true_type {}; |
31 | template<> struct need_promotion<signed char > : public true_type {}; |
32 | template<> struct need_promotion<unsigned char > : public true_type {}; |
33 | template<> struct need_promotion<signed short int > : public true_type {}; |
34 | template<> struct need_promotion<unsigned short int> : public true_type {}; |
35 | |
36 | |
37 | // Specializations for non-standard types. |
38 | // Type is promoted if it's smaller then int. |
39 | |
40 | #define BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(T) \ |
41 | template<> struct need_promotion<T> \ |
42 | : public integral_constant<bool, (sizeof(T) < sizeof(int))> {}; |
43 | |
44 | // Same set of integral types as in boost/type_traits/is_integral.hpp. |
45 | // Please, keep in sync. |
46 | #if (defined(BOOST_INTEL_CXX_VERSION) && defined(_MSC_VER) && (BOOST_INTEL_CXX_VERSION <= 600)) \ |
47 | || (defined(__BORLANDC__) && (__BORLANDC__ == 0x600) && (_MSC_VER < 1300)) |
48 | // TODO: common macro for this #if. Or better yet, PP SEQ of non-standard types. |
49 | BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(__int8 ) |
50 | BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(unsigned __int8 ) |
51 | BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(__int16 ) |
52 | BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(unsigned __int16) |
53 | BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(__int32 ) |
54 | BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(unsigned __int32) |
55 | #ifdef __BORLANDC__ |
56 | BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(unsigned __int64) |
57 | BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE( __int64) |
58 | #endif |
59 | #endif |
60 | |
61 | #if defined(BOOST_HAS_LONG_LONG) |
62 | BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(boost::ulong_long_type) |
63 | BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(boost::long_long_type ) |
64 | #elif defined(BOOST_HAS_MS_INT64) |
65 | BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(unsigned __int64) |
66 | BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE( __int64) |
67 | #endif |
68 | |
69 | #undef BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE |
70 | |
71 | |
72 | #ifndef BOOST_NO_INTRINSIC_WCHAR_T |
73 | // 4.5/2 |
74 | template<> struct need_promotion<wchar_t> : public true_type {}; |
75 | #endif |
76 | |
77 | // 4.5/3 (integral bit-field) is not supported. |
78 | |
79 | // 4.5/4 |
80 | template<> struct need_promotion<bool> : public true_type {}; |
81 | |
82 | |
83 | // Get promoted type by index and cv qualifiers. |
84 | |
85 | template<int Index, int IsConst, int IsVolatile> struct promote_from_index; |
86 | |
87 | #define BOOST_TT_AUX_PROMOTE_FROM_INDEX(N,T) \ |
88 | template<> struct promote_from_index<N,0,0> { typedef T type; }; \ |
89 | template<> struct promote_from_index<N,0,1> { typedef T volatile type; }; \ |
90 | template<> struct promote_from_index<N,1,0> { typedef T const type; }; \ |
91 | template<> struct promote_from_index<N,1,1> { typedef T const volatile type; }; |
92 | |
93 | |
94 | BOOST_TT_AUX_PROMOTE_FROM_INDEX(1, int ) |
95 | BOOST_TT_AUX_PROMOTE_FROM_INDEX(2, unsigned int ) |
96 | BOOST_TT_AUX_PROMOTE_FROM_INDEX(3, long ) |
97 | BOOST_TT_AUX_PROMOTE_FROM_INDEX(4, unsigned long) |
98 | |
99 | |
100 | // WARNING: integral promotions to non-standard types |
101 | // long long and __int64 are not defined by the standard. |
102 | // Additional specialisations and overloads shouldn't |
103 | // introduce ambiguity, though. |
104 | |
105 | #if defined(BOOST_HAS_LONG_LONG) |
106 | BOOST_TT_AUX_PROMOTE_FROM_INDEX(5, boost::long_long_type ) |
107 | BOOST_TT_AUX_PROMOTE_FROM_INDEX(6, boost::ulong_long_type) |
108 | #elif defined(BOOST_HAS_MS_INT64) |
109 | BOOST_TT_AUX_PROMOTE_FROM_INDEX(7, __int64 ) |
110 | BOOST_TT_AUX_PROMOTE_FROM_INDEX(8, unsigned __int64) |
111 | #endif |
112 | |
113 | #undef BOOST_TT_AUX_PROMOTE_FROM_INDEX |
114 | |
115 | |
116 | // Define BOOST_TT_AUX_PROMOTED_INDEX_TESTER: |
117 | #if !defined(BOOST_MSVC) |
118 | |
119 | template<int N> |
120 | struct sized_type_for_promotion |
121 | { |
122 | typedef char (&type)[N]; |
123 | }; |
124 | |
125 | #define BOOST_TT_AUX_PROMOTED_INDEX_TESTER(I,T) \ |
126 | sized_type_for_promotion<I>::type promoted_index_tester(T); |
127 | |
128 | #else |
129 | |
130 | #define BOOST_TT_AUX_PROMOTED_INDEX_TESTER(I,T) \ |
131 | char (&promoted_index_tester(T))[I]; |
132 | |
133 | #endif |
134 | |
135 | BOOST_TT_AUX_PROMOTED_INDEX_TESTER(1, int ) |
136 | BOOST_TT_AUX_PROMOTED_INDEX_TESTER(2, unsigned int ) |
137 | BOOST_TT_AUX_PROMOTED_INDEX_TESTER(3, long ) |
138 | BOOST_TT_AUX_PROMOTED_INDEX_TESTER(4, unsigned long) |
139 | |
140 | #if defined(BOOST_HAS_LONG_LONG) |
141 | BOOST_TT_AUX_PROMOTED_INDEX_TESTER(5, boost::long_long_type ) |
142 | BOOST_TT_AUX_PROMOTED_INDEX_TESTER(6, boost::ulong_long_type) |
143 | #elif defined(BOOST_HAS_MS_INT64) |
144 | BOOST_TT_AUX_PROMOTED_INDEX_TESTER(7, __int64 ) |
145 | BOOST_TT_AUX_PROMOTED_INDEX_TESTER(8, unsigned __int64) |
146 | #endif |
147 | |
148 | #undef BOOST_TT_AUX_PROMOTED_INDEX_TESTER |
149 | |
150 | |
151 | // Get an index of promoted type for type T. |
152 | // Precondition: need_promotion<T> |
153 | template<class T> |
154 | struct promoted_index |
155 | { |
156 | static T testee; // undefined |
157 | BOOST_STATIC_CONSTANT(int, value = sizeof(promoted_index_tester(+testee)) ); |
158 | // Unary plus promotes testee LOOK HERE ---> ^ |
159 | }; |
160 | |
161 | template<class T> |
162 | struct integral_promotion_impl |
163 | { |
164 | typedef BOOST_DEDUCED_TYPENAME promote_from_index< |
165 | (boost::type_traits::detail::promoted_index<T>::value) |
166 | , (boost::is_const<T>::value) |
167 | , (boost::is_volatile<T>::value) |
168 | >::type type; |
169 | }; |
170 | |
171 | template<class T> |
172 | struct integral_promotion |
173 | : public boost::mpl::eval_if< |
174 | need_promotion<BOOST_DEDUCED_TYPENAME remove_cv<T>::type> |
175 | , integral_promotion_impl<T> |
176 | , boost::mpl::identity<T> |
177 | > |
178 | { |
179 | }; |
180 | |
181 | } } |
182 | |
183 | BOOST_TT_AUX_TYPE_TRAIT_DEF1( |
184 | integral_promotion |
185 | , T |
186 | , BOOST_DEDUCED_TYPENAME |
187 | boost::type_traits::detail::integral_promotion<T>::type |
188 | ) |
189 | } |
190 | |
191 | #include <boost/type_traits/detail/type_trait_undef.hpp> |
192 | |
193 | #endif // #ifndef FILE_boost_type_traits_integral_promotion_hpp_INCLUDED |
194 | |
195 | |