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