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 : public 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 : public 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 struct __attribute__((__aligned__(64))) a64 {}; 229 struct __attribute__((__aligned__(128))) a128 {}; 230 } 231 232 template<> class type_with_alignment<1> { public: typedef char type; }; 233 template<> class type_with_alignment<2> { public: typedef align::a2 type; }; 234 template<> class type_with_alignment<4> { public: typedef align::a4 type; }; 235 template<> class type_with_alignment<8> { public: typedef align::a8 type; }; 236 template<> class type_with_alignment<16> { public: typedef align::a16 type; }; 237 template<> class type_with_alignment<32> { public: typedef align::a32 type; }; 238 template<> class type_with_alignment<64> { public: typedef align::a64 type; }; 239 template<> class type_with_alignment<128> { public: typedef align::a128 type; }; 240 241 namespace detail { 242 BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a2,true) 243 BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a4,true) 244 BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a8,true) 245 BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a16,true) 246 BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a32,true) 247 BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a64,true) 248 BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a128,true) 249 } 250 #endif 251 #if (defined(BOOST_MSVC) || (defined(BOOST_INTEL) && defined(_MSC_VER))) && _MSC_VER >= 1300 252 // 253 // MSVC supports types which have alignments greater than the normal 254 // maximum: these are used for example in the types __m64 and __m128 255 // to provide types with alignment requirements which match the SSE 256 // registers. Therefore we extend type_with_alignment<> to support 257 // such types, however, we have to be careful to use a builtin type 258 // whenever possible otherwise we break previously working code: 259 // see http://article.gmane.org/gmane.comp.lib.boost.devel/173011 260 // for an example and test case. Thus types like a8 below will 261 // be used *only* if the existing implementation can't provide a type 262 // with suitable alignment. This does mean however, that type_with_alignment<> 263 // may return a type which cannot be passed through a function call 264 // by value (and neither can any type containing such a type like 265 // Boost.Optional). However, this only happens when we have no choice 266 // in the matter because no other "ordinary" type is available. 267 // 268 namespace align { 269 struct __declspec(align(8)) a8 { 270 char m[8]; 271 typedef a8 type; 272 }; 273 struct __declspec(align(16)) a16 { 274 char m[16]; 275 typedef a16 type; 276 }; 277 struct __declspec(align(32)) a32 { 278 char m[32]; 279 typedef a32 type; 280 }; 281 struct __declspec(align(64)) a64 282 { 283 char m[64]; 284 typedef a64 type; 285 }; 286 struct __declspec(align(128)) a128 { 287 char m[128]; 288 typedef a128 type; 289 }; 290 } 291 292 template<> class type_with_alignment<8> 293 { 294 typedef mpl::if_c< 295 ::boost::alignment_of<boost::detail::max_align>::value < 8, 296 align::a8, 297 boost::detail::type_with_alignment_imp<8> >::type t1; 298 public: 299 typedef t1::type type; 300 }; 301 template<> class type_with_alignment<16> 302 { 303 typedef mpl::if_c< 304 ::boost::alignment_of<boost::detail::max_align>::value < 16, 305 align::a16, 306 boost::detail::type_with_alignment_imp<16> >::type t1; 307 public: 308 typedef t1::type type; 309 }; 310 template<> class type_with_alignment<32> 311 { 312 typedef mpl::if_c< 313 ::boost::alignment_of<boost::detail::max_align>::value < 32, 314 align::a32, 315 boost::detail::type_with_alignment_imp<32> >::type t1; 316 public: 317 typedef t1::type type; 318 }; 319 template<> class type_with_alignment<64> { 320 typedef mpl::if_c< 321 ::boost::alignment_of<boost::detail::max_align>::value < 64, 322 align::a64, 323 boost::detail::type_with_alignment_imp<64> >::type t1; 324 public: 325 typedef t1::type type; 326 }; 327 template<> class type_with_alignment<128> { 328 typedef mpl::if_c< 329 ::boost::alignment_of<boost::detail::max_align>::value < 128, 330 align::a128, 331 boost::detail::type_with_alignment_imp<128> >::type t1; 332 public: 333 typedef t1::type type; 334 }; 335 336 namespace detail { 337 BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a8,true) 338 BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a16,true) 339 BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a32,true) 340 BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a64,true) 341 BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a128,true) 342 } 343 #endif 344 345 #else 346 347 // 348 // Borland specific version, we have this for two reasons: 349 // 1) The version above doesn't always compile (with the new test cases for example) 350 // 2) Because of Borlands #pragma option we can create types with alignments that are 351 // greater that the largest aligned builtin type. 352 353 namespace align{ 354 #pragma option push -a16 355 struct a2{ short s; }; 356 struct a4{ int s; }; 357 struct a8{ double s; }; 358 struct a16{ long double s; }; 359 #pragma option pop 360 } 361 362 namespace detail { 363 364 typedef ::boost::align::a16 max_align; 365 366 //#if ! BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x610)) 367 BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a2,true) 368 BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a4,true) 369 BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a8,true) 370 BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a16,true) 371 //#endif 372 } 373 374 template <std::size_t N> struct type_with_alignment 375 { 376 // We should never get to here, but if we do use the maximally 377 // aligned type: 378 // BOOST_STATIC_ASSERT(0); 379 typedef align::a16 type; 380 }; 381 template <> struct type_with_alignment<1>{ typedef char type; }; 382 template <> struct type_with_alignment<2>{ typedef align::a2 type; }; 383 template <> struct type_with_alignment<4>{ typedef align::a4 type; }; 384 template <> struct type_with_alignment<8>{ typedef align::a8 type; }; 385 template <> struct type_with_alignment<16>{ typedef align::a16 type; }; 386 387 #endif 388 389 } // namespace boost 390 391 #ifdef BOOST_MSVC 392 # pragma warning(pop) 393 #endif 394 395 #include <boost/type_traits/detail/bool_trait_undef.hpp> 396 397 #endif // BOOST_TT_TYPE_WITH_ALIGNMENT_INCLUDED 398 399 400