Jeff Thompson | f7d4994 | 2013-08-01 16:47:40 -0700 | [diff] [blame] | 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 | |
Jeff Thompson | 2277ce5 | 2013-08-01 17:34:11 -0700 | [diff] [blame] | 11 | #include <ndnboost/mpl/if.hpp> |
| 12 | #include <ndnboost/preprocessor/list/for_each_i.hpp> |
| 13 | #include <ndnboost/preprocessor/tuple/to_list.hpp> |
| 14 | #include <ndnboost/preprocessor/cat.hpp> |
| 15 | #include <ndnboost/preprocessor/list/transform.hpp> |
| 16 | #include <ndnboost/preprocessor/list/append.hpp> |
| 17 | #include <ndnboost/type_traits/alignment_of.hpp> |
| 18 | #include <ndnboost/type_traits/is_pod.hpp> |
| 19 | #include <ndnboost/static_assert.hpp> |
| 20 | #include <ndnboost/config.hpp> |
Jeff Thompson | f7d4994 | 2013-08-01 16:47:40 -0700 | [diff] [blame] | 21 | |
| 22 | // should be the last #include |
Jeff Thompson | 2277ce5 | 2013-08-01 17:34:11 -0700 | [diff] [blame] | 23 | #include <ndnboost/type_traits/detail/bool_trait_def.hpp> |
Jeff Thompson | f7d4994 | 2013-08-01 16:47:40 -0700 | [diff] [blame] | 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 ndnboost { |
| 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, ::ndnboost::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) ndnboost::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,::ndnboost::detail::max_align,true) |
| 171 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::ndnboost::detail::lower_alignment<1> ,true) |
| 172 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::ndnboost::detail::lower_alignment<2> ,true) |
| 173 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::ndnboost::detail::lower_alignment<4> ,true) |
| 174 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::ndnboost::detail::lower_alignment<8> ,true) |
| 175 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::ndnboost::detail::lower_alignment<10> ,true) |
| 176 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::ndnboost::detail::lower_alignment<16> ,true) |
| 177 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::ndnboost::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< ::ndnboost::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 ::ndnboost::detail::lower_alignment<Align> t1; |
| 198 | typedef typename mpl::if_c< |
| 199 | ::ndnboost::detail::is_aligned< ::ndnboost::alignment_of<t1>::value,Align >::value |
| 200 | , t1 |
| 201 | , ::ndnboost::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 ::ndnboost::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,::ndnboost::align::a2,true) |
| 243 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::ndnboost::align::a4,true) |
| 244 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::ndnboost::align::a8,true) |
| 245 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::ndnboost::align::a16,true) |
| 246 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::ndnboost::align::a32,true) |
| 247 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::ndnboost::align::a64,true) |
| 248 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::ndnboost::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 | ::ndnboost::alignment_of<ndnboost::detail::max_align>::value < 8, |
| 296 | align::a8, |
| 297 | ndnboost::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 | ::ndnboost::alignment_of<ndnboost::detail::max_align>::value < 16, |
| 305 | align::a16, |
| 306 | ndnboost::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 | ::ndnboost::alignment_of<ndnboost::detail::max_align>::value < 32, |
| 314 | align::a32, |
| 315 | ndnboost::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 | ::ndnboost::alignment_of<ndnboost::detail::max_align>::value < 64, |
| 322 | align::a64, |
| 323 | ndnboost::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 | ::ndnboost::alignment_of<ndnboost::detail::max_align>::value < 128, |
| 330 | align::a128, |
| 331 | ndnboost::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,::ndnboost::align::a8,true) |
| 338 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::ndnboost::align::a16,true) |
| 339 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::ndnboost::align::a32,true) |
| 340 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::ndnboost::align::a64,true) |
| 341 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::ndnboost::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 ::ndnboost::align::a16 max_align; |
| 365 | |
| 366 | //#if ! BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x610)) |
| 367 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::ndnboost::align::a2,true) |
| 368 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::ndnboost::align::a4,true) |
| 369 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::ndnboost::align::a8,true) |
| 370 | BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::ndnboost::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 ndnboost |
| 390 | |
| 391 | #ifdef BOOST_MSVC |
| 392 | # pragma warning(pop) |
| 393 | #endif |
| 394 | |
Jeff Thompson | 2277ce5 | 2013-08-01 17:34:11 -0700 | [diff] [blame] | 395 | #include <ndnboost/type_traits/detail/bool_trait_undef.hpp> |
Jeff Thompson | f7d4994 | 2013-08-01 16:47:40 -0700 | [diff] [blame] | 396 | |
| 397 | #endif // BOOST_TT_TYPE_WITH_ALIGNMENT_INCLUDED |
| 398 | |
| 399 | |