diff --git a/include/boost/type_traits/type_with_alignment.hpp b/include/boost/type_traits/type_with_alignment.hpp index 26a671a..03b753e 100644 --- a/include/boost/type_traits/type_with_alignment.hpp +++ b/include/boost/type_traits/type_with_alignment.hpp @@ -189,8 +189,10 @@ struct is_pod< ::boost::detail::lower_alignment > // This alignment method originally due to Brian Parker, implemented by David // Abrahams, and then ported here by Doug Gregor. +namespace detail{ + template -class type_with_alignment +class type_with_alignment_imp { typedef ::boost::detail::lower_alignment t1; typedef typename mpl::if_c< @@ -208,6 +210,13 @@ class type_with_alignment typedef align_t type; }; +} + +template +class type_with_alignment : public detail::type_with_alignment_imp +{ +}; + #if defined(__GNUC__) namespace align { struct __attribute__((__aligned__(2))) a2 {}; @@ -233,19 +242,89 @@ BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a32,true) } #endif #if defined(BOOST_MSVC) || (defined(BOOST_INTEL) && defined(_MSC_VER)) +// +// MSVC supports types which have alignments greater than the normal +// maximum: these are used for example in the types __m64 and __m128 +// to provide types with alignment requirements which match the SSE +// registers. Therefore we extend type_with_alignment<> to support +// such types, however, we have to be careful to use a builtin type +// whenever possible otherwise we break previously working code: +// see http://article.gmane.org/gmane.comp.lib.boost.devel/173011 +// for an example and test case. Thus types like a8 below will +// be used *only* if the existing implementation can't provide a type +// with suitable alignment. This does mean however, that type_with_alignment<> +// may return a type which cannot be passed through a function call +// by value (and neither can any type containing such a type like +// Boost.Optional). However, this only happens when we have no choice +// in the matter because no other "ordinary" type is available. +// namespace align { -struct __declspec(align(8)) a8 { char m[8]; }; -struct __declspec(align(16)) a16 { char m[16]; }; -struct __declspec(align(32)) a32 { char m[32]; }; -struct __declspec(align(64)) a64 { char m[64]; }; -struct __declspec(align(128)) a128 { char m[128]; }; +struct __declspec(align(8)) a8 { + char m[8]; + typedef a8 type; +}; +struct __declspec(align(16)) a16 { + char m[16]; + typedef a16 type; +}; +struct __declspec(align(32)) a32 { + char m[32]; + typedef a32 type; +}; +struct __declspec(align(64)) a64 +{ + char m[64]; + typedef a64 type; +}; +struct __declspec(align(128)) a128 { + char m[128]; + typedef a128 type; +}; } -template<> class type_with_alignment<8> { public: typedef align::a8 type; }; -template<> class type_with_alignment<16> { public: typedef align::a16 type; }; -template<> class type_with_alignment<32> { public: typedef align::a32 type; }; -template<> class type_with_alignment<64> { public: typedef align::a64 type; }; -template<> class type_with_alignment<128> { public: typedef align::a128 type; }; +template<> class type_with_alignment<8> +{ + typedef mpl::if_c< + ::boost::alignment_of::value < 8, + align::a8, + detail::type_with_alignment_imp<8> >::type t1; +public: + typedef t1::type type; +}; +template<> class type_with_alignment<16> +{ + typedef mpl::if_c< + ::boost::alignment_of::value < 16, + align::a16, + detail::type_with_alignment_imp<16> >::type t1; +public: + typedef t1::type type; +}; +template<> class type_with_alignment<32> +{ + typedef mpl::if_c< + ::boost::alignment_of::value < 32, + align::a32, + detail::type_with_alignment_imp<32> >::type t1; +public: + typedef t1::type type; +}; +template<> class type_with_alignment<64> { + typedef mpl::if_c< + ::boost::alignment_of::value < 64, + align::a64, + detail::type_with_alignment_imp<64> >::type t1; +public: + typedef t1::type type; +}; +template<> class type_with_alignment<128> { + typedef mpl::if_c< + ::boost::alignment_of::value < 128, + align::a128, + detail::type_with_alignment_imp<128> >::type t1; +public: + typedef t1::type type; +}; namespace detail { BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC1(is_pod,::boost::align::a8,true) diff --git a/test/type_with_alignment_test.cpp b/test/type_with_alignment_test.cpp index 77f399c..534803c 100644 --- a/test/type_with_alignment_test.cpp +++ b/test/type_with_alignment_test.cpp @@ -25,227 +25,76 @@ struct __declspec(align(64)) a64 { char m[64]; }; struct __declspec(align(128)) a128 { char m[128]; }; #endif +void check_call2(...){} + +template +void check_call(const T& v) +{ + check_call2(v); +} + +#define TYPE_WITH_ALIGNMENT_TEST(T)\ +{\ +BOOST_CHECK(::tt::alignment_of<\ + ::tt::type_with_alignment<\ + ::tt::alignment_of< T >::value\ + >::type\ + >::value == ::boost::alignment_of< T >::value);\ +BOOST_CHECK(::tt::is_pod<\ + ::tt::type_with_alignment<\ + ::tt::alignment_of< T >::value>::type\ + >::value);\ +} +#define TYPE_WITH_ALIGNMENT_TEST_EX(T)\ + TYPE_WITH_ALIGNMENT_TEST(T)\ +{\ + ::tt::type_with_alignment<\ + ::tt::alignment_of< T >::value\ + >::type val;\ + check_call(val);\ +} + + TT_TEST_BEGIN(type_with_alignment) BOOST_MESSAGE(typeid(::tt::type_with_alignment< ::tt::alignment_of::value >::type).name()); -BOOST_CHECK(::tt::alignment_of< - ::tt::type_with_alignment< - ::tt::alignment_of::value - >::type - >::value == ::boost::alignment_of::value); -BOOST_CHECK(::tt::alignment_of< - ::tt::type_with_alignment< - ::tt::alignment_of::value - >::type - >::value == ::boost::alignment_of::value); -BOOST_CHECK(::tt::alignment_of< - ::tt::type_with_alignment< - ::tt::alignment_of::value - >::type - >::value == ::boost::alignment_of::value); -BOOST_CHECK(::tt::alignment_of< - ::tt::type_with_alignment< - ::tt::alignment_of::value - >::type - >::value == ::boost::alignment_of::value); -BOOST_CHECK(::tt::alignment_of< - ::tt::type_with_alignment< - ::tt::alignment_of::value - >::type - >::value == ::boost::alignment_of::value); -BOOST_CHECK(::tt::alignment_of< - ::tt::type_with_alignment< - ::tt::alignment_of::value - >::type - >::value == ::boost::alignment_of::value); -BOOST_CHECK(::tt::alignment_of< - ::tt::type_with_alignment< - ::tt::alignment_of::value - >::type - >::value == ::boost::alignment_of::value); +TYPE_WITH_ALIGNMENT_TEST_EX(char) +TYPE_WITH_ALIGNMENT_TEST_EX(short) +TYPE_WITH_ALIGNMENT_TEST_EX(int) +TYPE_WITH_ALIGNMENT_TEST_EX(long) +TYPE_WITH_ALIGNMENT_TEST_EX(float) +TYPE_WITH_ALIGNMENT_TEST_EX(double) +TYPE_WITH_ALIGNMENT_TEST_EX(long double) + #ifdef BOOST_HAS_LONG_LONG -BOOST_CHECK(::tt::alignment_of< - ::tt::type_with_alignment< - ::tt::alignment_of< ::boost::long_long_type>::value - >::type - >::value == ::boost::alignment_of< ::boost::long_long_type>::value); +TYPE_WITH_ALIGNMENT_TEST_EX(::boost::long_long_type) #endif #ifdef BOOST_HAS_MS_INT64 -BOOST_CHECK(::tt::alignment_of< - ::tt::type_with_alignment< - ::tt::alignment_of<__int64>::value - >::type - >::value == ::boost::alignment_of<__int64>::value); +TYPE_WITH_ALIGNMENT_TEST_EX(__int64) #endif +TYPE_WITH_ALIGNMENT_TEST_EX(int[4]) +TYPE_WITH_ALIGNMENT_TEST_EX(int(*)(int)) +TYPE_WITH_ALIGNMENT_TEST_EX(int*) +TYPE_WITH_ALIGNMENT_TEST_EX(VB) +TYPE_WITH_ALIGNMENT_TEST_EX(VD) +TYPE_WITH_ALIGNMENT_TEST_EX(enum_UDT) +TYPE_WITH_ALIGNMENT_TEST_EX(mf2) +TYPE_WITH_ALIGNMENT_TEST_EX(POD_UDT) +TYPE_WITH_ALIGNMENT_TEST_EX(empty_UDT) +TYPE_WITH_ALIGNMENT_TEST_EX(union_UDT) + #if defined(BOOST_MSVC) || (defined(BOOST_INTEL) && defined(_MSC_VER)) #if _MSC_VER >= 1400 -BOOST_CHECK(::tt::alignment_of< - ::tt::type_with_alignment< - ::tt::alignment_of<__m128>::value - >::type - >::value == ::boost::alignment_of<__m128>::value); -BOOST_CHECK(::tt::alignment_of< - ::tt::type_with_alignment< - ::tt::alignment_of<__m64>::value - >::type - >::value == ::boost::alignment_of<__m64>::value); +TYPE_WITH_ALIGNMENT_TEST(__m128) +TYPE_WITH_ALIGNMENT_TEST(__m64) #endif -BOOST_CHECK(::tt::alignment_of< - ::tt::type_with_alignment< - ::tt::alignment_of::value - >::type - >::value == ::boost::alignment_of::value); -BOOST_CHECK(::tt::alignment_of< - ::tt::type_with_alignment< - ::tt::alignment_of::value - >::type - >::value == ::boost::alignment_of::value); -BOOST_CHECK(::tt::alignment_of< - ::tt::type_with_alignment< - ::tt::alignment_of::value - >::type - >::value == ::boost::alignment_of::value); -BOOST_CHECK(::tt::alignment_of< - ::tt::type_with_alignment< - ::tt::alignment_of::value - >::type - >::value == ::boost::alignment_of::value); +TYPE_WITH_ALIGNMENT_TEST(a8) +TYPE_WITH_ALIGNMENT_TEST(a16) +TYPE_WITH_ALIGNMENT_TEST(a32) #endif -BOOST_CHECK(::tt::alignment_of< - ::tt::type_with_alignment< - ::tt::alignment_of::value - >::type - >::value == ::boost::alignment_of::value); -BOOST_CHECK(::tt::alignment_of< - ::tt::type_with_alignment< - ::tt::alignment_of::value - >::type - >::value == ::boost::alignment_of::value); -BOOST_CHECK(::tt::alignment_of< - ::tt::type_with_alignment< - ::tt::alignment_of::value - >::type - >::value == ::boost::alignment_of::value); -BOOST_CHECK(::tt::alignment_of< - ::tt::type_with_alignment< - ::tt::alignment_of::value - >::type - >::value == ::boost::alignment_of::value); -BOOST_CHECK(::tt::alignment_of< - ::tt::type_with_alignment< - ::tt::alignment_of::value - >::type - >::value == ::boost::alignment_of::value); -BOOST_CHECK(::tt::alignment_of< - ::tt::type_with_alignment< - ::tt::alignment_of::value - >::type - >::value == ::boost::alignment_of::value); -BOOST_CHECK(::tt::alignment_of< - ::tt::type_with_alignment< - ::tt::alignment_of::value - >::type - >::value == ::boost::alignment_of::value); -BOOST_CHECK(::tt::alignment_of< - ::tt::type_with_alignment< - ::tt::alignment_of::value - >::type - >::value == ::boost::alignment_of::value); -BOOST_CHECK(::tt::alignment_of< - ::tt::type_with_alignment< - ::tt::alignment_of::value - >::type - >::value == ::boost::alignment_of::value); -BOOST_CHECK(::tt::alignment_of< - ::tt::type_with_alignment< - ::tt::alignment_of::value - >::type - >::value == ::boost::alignment_of::value); - -// check that the type produced are POD's: -BOOST_CHECK(::tt::is_pod< - ::tt::type_with_alignment< - ::tt::alignment_of::value>::type - >::value); -BOOST_CHECK(::tt::is_pod< - ::tt::type_with_alignment< - ::tt::alignment_of::value>::type - >::value); -BOOST_CHECK(::tt::is_pod< - ::tt::type_with_alignment< - ::tt::alignment_of::value>::type - >::value); -BOOST_CHECK(::tt::is_pod< - ::tt::type_with_alignment< - ::tt::alignment_of::value>::type - >::value); -BOOST_CHECK(::tt::is_pod< - ::tt::type_with_alignment< - ::tt::alignment_of::value>::type - >::value); -BOOST_CHECK(::tt::is_pod< - ::tt::type_with_alignment< - ::tt::alignment_of::value>::type - >::value); -BOOST_CHECK(::tt::is_pod< - ::tt::type_with_alignment< - ::tt::alignment_of::value>::type - >::value); -#ifdef BOOST_HAS_LONG_LONG -BOOST_CHECK(::tt::is_pod< - ::tt::type_with_alignment< - ::tt::alignment_of< ::boost::long_long_type>::value>::type - >::value); -#endif -#ifdef BOOST_HAS_MS_INT64 -BOOST_CHECK(::tt::is_pod< - ::tt::type_with_alignment< - ::tt::alignment_of<__int64>::value>::type - >::value); -#endif -BOOST_CHECK(::tt::is_pod< - ::tt::type_with_alignment< - ::tt::alignment_of::value>::type - >::value); -BOOST_CHECK(::tt::is_pod< - ::tt::type_with_alignment< - ::tt::alignment_of::value>::type - >::value); -BOOST_CHECK(::tt::is_pod< - ::tt::type_with_alignment< - ::tt::alignment_of::value>::type - >::value); -BOOST_CHECK(::tt::is_pod< - ::tt::type_with_alignment< - ::tt::alignment_of::value>::type - >::value); -BOOST_CHECK(::tt::is_pod< - ::tt::type_with_alignment< - ::tt::alignment_of::value>::type - >::value); -BOOST_CHECK(::tt::is_pod< - ::tt::type_with_alignment< - ::tt::alignment_of::value>::type - >::value); -BOOST_CHECK(::tt::is_pod< - ::tt::type_with_alignment< - ::tt::alignment_of::value>::type - >::value); -BOOST_CHECK(::tt::is_pod< - ::tt::type_with_alignment< - ::tt::alignment_of::value>::type - >::value); -BOOST_CHECK(::tt::is_pod< - ::tt::type_with_alignment< - ::tt::alignment_of::value>::type - >::value); -BOOST_CHECK(::tt::is_pod< - ::tt::type_with_alignment< - ::tt::alignment_of::value>::type - >::value); TT_TEST_END