[1022] | 1 | // (C) Copyright John Maddock 2000. |
---|
| 2 | // Use, modification and distribution are subject to the Boost Software License, |
---|
| 3 | // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
---|
| 4 | // http://www.boost.org/LICENSE_1_0.txt). |
---|
| 5 | // |
---|
| 6 | // See http://www.boost.org/libs/type_traits for most recent version including documentation. |
---|
| 7 | |
---|
| 8 | #ifndef BOOST_TT_TYPE_WITH_ALIGNMENT_INCLUDED |
---|
| 9 | #define BOOST_TT_TYPE_WITH_ALIGNMENT_INCLUDED |
---|
| 10 | |
---|
| 11 | #include <boost/mpl/if.hpp> |
---|
| 12 | #include <boost/preprocessor/list/for_each_i.hpp> |
---|
| 13 | #include <boost/preprocessor/tuple/to_list.hpp> |
---|
| 14 | #include <boost/preprocessor/cat.hpp> |
---|
| 15 | #include <boost/preprocessor/list/transform.hpp> |
---|
| 16 | #include <boost/preprocessor/list/append.hpp> |
---|
| 17 | #include <boost/type_traits/alignment_of.hpp> |
---|
| 18 | #include <boost/type_traits/is_pod.hpp> |
---|
| 19 | #include <boost/static_assert.hpp> |
---|
| 20 | #include <boost/config.hpp> |
---|
| 21 | |
---|
| 22 | // should be the last #include |
---|
| 23 | #include <boost/type_traits/detail/bool_trait_def.hpp> |
---|
| 24 | |
---|
| 25 | #include <cstddef> |
---|
| 26 | |
---|
| 27 | #ifdef BOOST_MSVC |
---|
| 28 | # pragma warning(push) |
---|
| 29 | # pragma warning(disable: 4121) // alignment is sensitive to packing |
---|
| 30 | #endif |
---|
| 31 | |
---|
| 32 | namespace boost { |
---|
| 33 | |
---|
| 34 | #ifndef __BORLANDC__ |
---|
| 35 | |
---|
| 36 | namespace detail { |
---|
| 37 | |
---|
| 38 | class alignment_dummy; |
---|
| 39 | typedef void (*function_ptr)(); |
---|
| 40 | typedef int (alignment_dummy::*member_ptr); |
---|
| 41 | typedef int (alignment_dummy::*member_function_ptr)(); |
---|
| 42 | |
---|
| 43 | #ifdef BOOST_HAS_LONG_LONG |
---|
| 44 | #define BOOST_TT_ALIGNMENT_BASE_TYPES BOOST_PP_TUPLE_TO_LIST( \ |
---|
| 45 | 12, ( \ |
---|
| 46 | char, short, int, long, ::boost::long_long_type, float, double, long double \ |
---|
| 47 | , void*, function_ptr, member_ptr, member_function_ptr)) |
---|
| 48 | #else |
---|
| 49 | #define BOOST_TT_ALIGNMENT_BASE_TYPES BOOST_PP_TUPLE_TO_LIST( \ |
---|
| 50 | 11, ( \ |
---|
| 51 | char, short, int, long, float, double, long double \ |
---|
| 52 | , void*, function_ptr, member_ptr, member_function_ptr)) |
---|
| 53 | #endif |
---|
| 54 | |
---|
| 55 | #define BOOST_TT_HAS_ONE_T(D,Data,T) boost::detail::has_one_T< T > |
---|
| 56 | |
---|
| 57 | #define BOOST_TT_ALIGNMENT_STRUCT_TYPES \ |
---|
| 58 | BOOST_PP_LIST_TRANSFORM(BOOST_TT_HAS_ONE_T, \ |
---|
| 59 | X, \ |
---|
| 60 | BOOST_TT_ALIGNMENT_BASE_TYPES) |
---|
| 61 | |
---|
| 62 | #define BOOST_TT_ALIGNMENT_TYPES \ |
---|
| 63 | BOOST_PP_LIST_APPEND(BOOST_TT_ALIGNMENT_BASE_TYPES, \ |
---|
| 64 | BOOST_TT_ALIGNMENT_STRUCT_TYPES) |
---|
| 65 | |
---|
| 66 | // |
---|
| 67 | // lower_alignment_helper -- |
---|
| 68 | // |
---|
| 69 | // This template gets instantiated a lot, so use partial |
---|
| 70 | // specialization when available to reduce the compiler burden. |
---|
| 71 | // |
---|
| 72 | #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
---|
| 73 | template <bool found = true> |
---|
| 74 | struct lower_alignment_helper_impl |
---|
| 75 | { |
---|
| 76 | template <std::size_t, class> |
---|
| 77 | struct apply |
---|
| 78 | { |
---|
| 79 | typedef char type; |
---|
| 80 | enum { value = true }; |
---|
| 81 | }; |
---|
| 82 | }; |
---|
| 83 | |
---|
| 84 | template <> |
---|
| 85 | struct lower_alignment_helper_impl<false> |
---|
| 86 | { |
---|
| 87 | template <std::size_t target, class TestType> |
---|
| 88 | struct apply |
---|
| 89 | : mpl::if_c<(alignment_of<TestType>::value == target), TestType, char> |
---|
| 90 | { |
---|
| 91 | enum { value = (alignment_of<TestType>::value == target) }; |
---|
| 92 | }; |
---|
| 93 | }; |
---|
| 94 | |
---|
| 95 | template <bool found, std::size_t target, class TestType> |
---|
| 96 | struct lower_alignment_helper |
---|
| 97 | : lower_alignment_helper_impl<found>::template apply<target,TestType> |
---|
| 98 | { |
---|
| 99 | }; |
---|
| 100 | #else |
---|
| 101 | template <bool found, std::size_t target, class TestType> |
---|
| 102 | struct lower_alignment_helper |
---|
| 103 | { |
---|
| 104 | typedef char type; |
---|
| 105 | enum { value = true }; |
---|
| 106 | }; |
---|
| 107 | |
---|
| 108 | template <std::size_t target, class TestType> |
---|
| 109 | struct lower_alignment_helper<false,target,TestType> |
---|
| 110 | { |
---|
| 111 | enum { value = (alignment_of<TestType>::value == target) }; |
---|
| 112 | typedef typename mpl::if_c<value, TestType, char>::type type; |
---|
| 113 | }; |
---|
| 114 | #endif |
---|
| 115 | |
---|
| 116 | #define BOOST_TT_CHOOSE_MIN_ALIGNMENT(R,P,I,T) \ |
---|
| 117 | typename lower_alignment_helper< \ |
---|
| 118 | BOOST_PP_CAT(found,I),target,T \ |
---|
| 119 | >::type BOOST_PP_CAT(t,I); \ |
---|
| 120 | enum { \ |
---|
| 121 | BOOST_PP_CAT(found,BOOST_PP_INC(I)) \ |
---|
| 122 | = lower_alignment_helper<BOOST_PP_CAT(found,I),target,T >::value \ |
---|
| 123 | }; |
---|
| 124 | |
---|
| 125 | #define BOOST_TT_CHOOSE_T(R,P,I,T) T BOOST_PP_CAT(t,I); |
---|
| 126 | |
---|
| 127 | template <typename T> |
---|
| 128 | struct has_one_T |
---|
| 129 | { |
---|
| 130 | T data; |
---|
| 131 | }; |
---|
| 132 | |
---|
| 133 | template <std::size_t target> |
---|
| 134 | union lower_alignment |
---|
| 135 | { |
---|
| 136 | enum { found0 = false }; |
---|
| 137 | |
---|
| 138 | BOOST_PP_LIST_FOR_EACH_I( |
---|
| 139 | BOOST_TT_CHOOSE_MIN_ALIGNMENT |
---|
| 140 | , ignored |
---|
| 141 | , BOOST_TT_ALIGNMENT_TYPES |
---|
| 142 | ) |
---|
| 143 | }; |
---|
| 144 | |
---|
| 145 | union max_align |
---|
| 146 | { |
---|
| 147 | BOOST_PP_LIST_FOR_EACH_I( |
---|
| 148 | BOOST_TT_CHOOSE_T |
---|
| 149 | , ignored |
---|
| 150 | , BOOST_TT_ALIGNMENT_TYPES |
---|
| 151 | ) |
---|
| 152 | }; |
---|
| 153 | |
---|
| 154 | #undef BOOST_TT_ALIGNMENT_BASE_TYPES |
---|
| 155 | #undef BOOST_TT_HAS_ONE_T |
---|
| 156 | #undef BOOST_TT_ALIGNMENT_STRUCT_TYPES |
---|
| 157 | #undef BOOST_TT_ALIGNMENT_TYPES |
---|
| 158 | #undef BOOST_TT_CHOOSE_MIN_ALIGNMENT |
---|
| 159 | #undef BOOST_TT_CHOOSE_T |
---|
| 160 | |
---|
| 161 | template<std::size_t TAlign, std::size_t Align> |
---|
| 162 | struct is_aligned |
---|
| 163 | { |
---|
| 164 | BOOST_STATIC_CONSTANT(bool, |
---|
| 165 | value = (TAlign >= Align) & (TAlign % Align == 0) |
---|
| 166 | ); |
---|
| 167 | }; |
---|
| 168 | |
---|
| 169 | #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
---|
| 170 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::detail::max_align,true) |
---|
| 171 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::detail::lower_alignment<1> ,true) |
---|
| 172 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::detail::lower_alignment<2> ,true) |
---|
| 173 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::detail::lower_alignment<4> ,true) |
---|
| 174 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::detail::lower_alignment<8> ,true) |
---|
| 175 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::detail::lower_alignment<10> ,true) |
---|
| 176 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::detail::lower_alignment<16> ,true) |
---|
| 177 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::detail::lower_alignment<32> ,true) |
---|
| 178 | #endif |
---|
| 179 | |
---|
| 180 | } // namespace detail |
---|
| 181 | |
---|
| 182 | #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
---|
| 183 | template<std::size_t Align> |
---|
| 184 | struct is_pod< ::boost::detail::lower_alignment<Align> > |
---|
| 185 | { |
---|
| 186 | BOOST_STATIC_CONSTANT(std::size_t, value = true); |
---|
| 187 | }; |
---|
| 188 | #endif |
---|
| 189 | |
---|
| 190 | // This alignment method originally due to Brian Parker, implemented by David |
---|
| 191 | // Abrahams, and then ported here by Doug Gregor. |
---|
| 192 | namespace detail{ |
---|
| 193 | |
---|
| 194 | template <std::size_t Align> |
---|
| 195 | class type_with_alignment_imp |
---|
| 196 | { |
---|
| 197 | typedef ::boost::detail::lower_alignment<Align> t1; |
---|
| 198 | typedef typename mpl::if_c< |
---|
| 199 | ::boost::detail::is_aligned< ::boost::alignment_of<t1>::value,Align >::value |
---|
| 200 | , t1 |
---|
| 201 | , ::boost::detail::max_align |
---|
| 202 | >::type align_t; |
---|
| 203 | |
---|
| 204 | BOOST_STATIC_CONSTANT(std::size_t, found = alignment_of<align_t>::value); |
---|
| 205 | |
---|
| 206 | BOOST_STATIC_ASSERT(found >= Align); |
---|
| 207 | BOOST_STATIC_ASSERT(found % Align == 0); |
---|
| 208 | |
---|
| 209 | public: |
---|
| 210 | typedef align_t type; |
---|
| 211 | }; |
---|
| 212 | |
---|
| 213 | } |
---|
| 214 | |
---|
| 215 | template <std::size_t Align> |
---|
| 216 | class type_with_alignment |
---|
| 217 | : public ::boost::detail::type_with_alignment_imp<Align> |
---|
| 218 | { |
---|
| 219 | }; |
---|
| 220 | |
---|
| 221 | #if defined(__GNUC__) |
---|
| 222 | namespace align { |
---|
| 223 | struct __attribute__((__aligned__(2))) a2 {}; |
---|
| 224 | struct __attribute__((__aligned__(4))) a4 {}; |
---|
| 225 | struct __attribute__((__aligned__(8))) a8 {}; |
---|
| 226 | struct __attribute__((__aligned__(16))) a16 {}; |
---|
| 227 | struct __attribute__((__aligned__(32))) a32 {}; |
---|
| 228 | } |
---|
| 229 | |
---|
| 230 | template<> class type_with_alignment<1> { public: typedef char type; }; |
---|
| 231 | template<> class type_with_alignment<2> { public: typedef align::a2 type; }; |
---|
| 232 | template<> class type_with_alignment<4> { public: typedef align::a4 type; }; |
---|
| 233 | template<> class type_with_alignment<8> { public: typedef align::a8 type; }; |
---|
| 234 | template<> class type_with_alignment<16> { public: typedef align::a16 type; }; |
---|
| 235 | template<> class type_with_alignment<32> { public: typedef align::a32 type; }; |
---|
| 236 | |
---|
| 237 | namespace detail { |
---|
| 238 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a2,true) |
---|
| 239 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a4,true) |
---|
| 240 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a8,true) |
---|
| 241 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a16,true) |
---|
| 242 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a32,true) |
---|
| 243 | } |
---|
| 244 | #endif |
---|
| 245 | #if (defined(BOOST_MSVC) || (defined(BOOST_INTEL) && defined(_MSC_VER))) && _MSC_VER >= 1300 |
---|
| 246 | // |
---|
| 247 | // MSVC supports types which have alignments greater than the normal |
---|
| 248 | // maximum: these are used for example in the types __m64 and __m128 |
---|
| 249 | // to provide types with alignment requirements which match the SSE |
---|
| 250 | // registers. Therefore we extend type_with_alignment<> to support |
---|
| 251 | // such types, however, we have to be careful to use a builtin type |
---|
| 252 | // whenever possible otherwise we break previously working code: |
---|
| 253 | // see http://article.gmane.org/gmane.comp.lib.boost.devel/173011 |
---|
| 254 | // for an example and test case. Thus types like a8 below will |
---|
| 255 | // be used *only* if the existing implementation can't provide a type |
---|
| 256 | // with suitable alignment. This does mean however, that type_with_alignment<> |
---|
| 257 | // may return a type which cannot be passed through a function call |
---|
| 258 | // by value (and neither can any type containing such a type like |
---|
| 259 | // Boost.Optional). However, this only happens when we have no choice |
---|
| 260 | // in the matter because no other "ordinary" type is available. |
---|
| 261 | // |
---|
| 262 | namespace align { |
---|
| 263 | struct __declspec(align(8)) a8 { |
---|
| 264 | char m[8]; |
---|
| 265 | typedef a8 type; |
---|
| 266 | }; |
---|
| 267 | struct __declspec(align(16)) a16 { |
---|
| 268 | char m[16]; |
---|
| 269 | typedef a16 type; |
---|
| 270 | }; |
---|
| 271 | struct __declspec(align(32)) a32 { |
---|
| 272 | char m[32]; |
---|
| 273 | typedef a32 type; |
---|
| 274 | }; |
---|
| 275 | struct __declspec(align(64)) a64 |
---|
| 276 | { |
---|
| 277 | char m[64]; |
---|
| 278 | typedef a64 type; |
---|
| 279 | }; |
---|
| 280 | struct __declspec(align(128)) a128 { |
---|
| 281 | char m[128]; |
---|
| 282 | typedef a128 type; |
---|
| 283 | }; |
---|
| 284 | } |
---|
| 285 | |
---|
| 286 | template<> class type_with_alignment<8> |
---|
| 287 | { |
---|
| 288 | typedef mpl::if_c< |
---|
| 289 | ::boost::alignment_of<boost::detail::max_align>::value < 8, |
---|
| 290 | align::a8, |
---|
| 291 | boost::detail::type_with_alignment_imp<8> >::type t1; |
---|
| 292 | public: |
---|
| 293 | typedef t1::type type; |
---|
| 294 | }; |
---|
| 295 | template<> class type_with_alignment<16> |
---|
| 296 | { |
---|
| 297 | typedef mpl::if_c< |
---|
| 298 | ::boost::alignment_of<boost::detail::max_align>::value < 16, |
---|
| 299 | align::a16, |
---|
| 300 | boost::detail::type_with_alignment_imp<16> >::type t1; |
---|
| 301 | public: |
---|
| 302 | typedef t1::type type; |
---|
| 303 | }; |
---|
| 304 | template<> class type_with_alignment<32> |
---|
| 305 | { |
---|
| 306 | typedef mpl::if_c< |
---|
| 307 | ::boost::alignment_of<boost::detail::max_align>::value < 32, |
---|
| 308 | align::a32, |
---|
| 309 | boost::detail::type_with_alignment_imp<32> >::type t1; |
---|
| 310 | public: |
---|
| 311 | typedef t1::type type; |
---|
| 312 | }; |
---|
| 313 | template<> class type_with_alignment<64> { |
---|
| 314 | typedef mpl::if_c< |
---|
| 315 | ::boost::alignment_of<boost::detail::max_align>::value < 64, |
---|
| 316 | align::a64, |
---|
| 317 | boost::detail::type_with_alignment_imp<64> >::type t1; |
---|
| 318 | public: |
---|
| 319 | typedef t1::type type; |
---|
| 320 | }; |
---|
| 321 | template<> class type_with_alignment<128> { |
---|
| 322 | typedef mpl::if_c< |
---|
| 323 | ::boost::alignment_of<boost::detail::max_align>::value < 128, |
---|
| 324 | align::a128, |
---|
| 325 | boost::detail::type_with_alignment_imp<128> >::type t1; |
---|
| 326 | public: |
---|
| 327 | typedef t1::type type; |
---|
| 328 | }; |
---|
| 329 | |
---|
| 330 | namespace detail { |
---|
| 331 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a8,true) |
---|
| 332 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a16,true) |
---|
| 333 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a32,true) |
---|
| 334 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a64,true) |
---|
| 335 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a128,true) |
---|
| 336 | } |
---|
| 337 | #endif |
---|
| 338 | |
---|
| 339 | #else |
---|
| 340 | |
---|
| 341 | // |
---|
| 342 | // Borland specific version, we have this for two reasons: |
---|
| 343 | // 1) The version above doesn't always compile (with the new test cases for example) |
---|
| 344 | // 2) Because of Borlands #pragma option we can create types with alignments that are |
---|
| 345 | // greater that the largest aligned builtin type. |
---|
| 346 | |
---|
| 347 | namespace align{ |
---|
| 348 | #pragma option push -a16 |
---|
| 349 | struct a2{ short s; }; |
---|
| 350 | struct a4{ int s; }; |
---|
| 351 | struct a8{ double s; }; |
---|
| 352 | struct a16{ long double s; }; |
---|
| 353 | #pragma option pop |
---|
| 354 | } |
---|
| 355 | |
---|
| 356 | namespace detail { |
---|
| 357 | |
---|
| 358 | typedef ::boost::align::a16 max_align; |
---|
| 359 | |
---|
| 360 | //#if ! BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x610)) |
---|
| 361 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a2,true) |
---|
| 362 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a4,true) |
---|
| 363 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a8,true) |
---|
| 364 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a16,true) |
---|
| 365 | //#endif |
---|
| 366 | } |
---|
| 367 | |
---|
| 368 | template <std::size_t N> struct type_with_alignment |
---|
| 369 | { |
---|
| 370 | // We should never get to here, but if we do use the maximally |
---|
| 371 | // aligned type: |
---|
| 372 | // BOOST_STATIC_ASSERT(0); |
---|
| 373 | typedef align::a16 type; |
---|
| 374 | }; |
---|
| 375 | template <> struct type_with_alignment<1>{ typedef char type; }; |
---|
| 376 | template <> struct type_with_alignment<2>{ typedef align::a2 type; }; |
---|
| 377 | template <> struct type_with_alignment<4>{ typedef align::a4 type; }; |
---|
| 378 | template <> struct type_with_alignment<8>{ typedef align::a8 type; }; |
---|
| 379 | template <> struct type_with_alignment<16>{ typedef align::a16 type; }; |
---|
| 380 | |
---|
| 381 | #endif |
---|
| 382 | |
---|
| 383 | } // namespace boost |
---|
| 384 | |
---|
| 385 | #ifdef BOOST_MSVC |
---|
| 386 | # pragma warning(pop) |
---|
| 387 | #endif |
---|
| 388 | |
---|
| 389 | #include <boost/type_traits/detail/bool_trait_undef.hpp> |
---|
| 390 | |
---|
| 391 | #endif // BOOST_TT_TYPE_WITH_ALIGNMENT_INCLUDED |
---|
| 392 | |
---|
| 393 | |
---|