Initial version of the code and tests

[SVN r33707]
This commit is contained in:
Alexander Nasonov
2006-04-16 00:22:36 +00:00
parent 117eddb5c9
commit 0c7e439b85
7 changed files with 641 additions and 0 deletions

View File

@ -0,0 +1,61 @@
// Copyright 2005 Alexander Nasonov.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef FILE_boost_type_traits_floating_point_promotion_hpp_INCLUDED
#define FILE_boost_type_traits_floating_point_promotion_hpp_INCLUDED
#include <boost/config.hpp>
// Should be the last #include
#include <boost/type_traits/detail/type_trait_def.hpp>
namespace boost {
namespace type_traits { namespace detail {
template<class T>
struct floating_point_promotion
{
typedef T type;
};
template<>
struct floating_point_promotion<float>
{
typedef double type;
};
template<>
struct floating_point_promotion<float const>
{
typedef double const type;
};
template<>
struct floating_point_promotion<float volatile>
{
typedef double volatile type;
};
template<>
struct floating_point_promotion<float const volatile>
{
typedef double const volatile type;
};
} }
BOOST_TT_AUX_TYPE_TRAIT_DEF1(
floating_point_promotion
, T
, BOOST_DEDUCED_TYPENAME
::boost::type_traits::detail::floating_point_promotion<T>::type
)
}
#include <boost/type_traits/detail/type_trait_undef.hpp>
#endif // #ifndef FILE_boost_type_traits_floating_point_promotion_hpp_INCLUDED

View File

@ -0,0 +1,194 @@
// Copyright 2005 Alexander Nasonov.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef FILE_boost_type_traits_integral_promotion_hpp_INCLUDED
#define FILE_boost_type_traits_integral_promotion_hpp_INCLUDED
#include <boost/config.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/is_enum.hpp>
#include <boost/type_traits/is_volatile.hpp>
// Should be the last #include
#include <boost/type_traits/detail/type_trait_def.hpp>
#include <boost/type_traits/detail/bool_trait_def.hpp>
namespace boost {
namespace type_traits { namespace detail {
// 4.5/2
BOOST_TT_AUX_BOOL_TRAIT_DEF1(need_promotion, T, boost::is_enum<T>::value)
// 4.5/1
BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(need_promotion, char , true)
BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(need_promotion, signed char , true)
BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(need_promotion, unsigned char , true)
BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(need_promotion, signed short int , true)
BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(need_promotion, unsigned short int, true)
// Specializations for non-standard types.
// Type is promoted if it's smaller then int.
#define BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(T) \
BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(need_promotion, T, (sizeof(T) < sizeof(int)))
// Same set of integral types as in boost/type_traits/is_integral.hpp.
// Please, keep in sync.
#if (defined(BOOST_MSVC) && (BOOST_MSVC < 1300)) \
|| (defined(BOOST_INTEL_CXX_VERSION) && defined(_MSC_VER) && (BOOST_INTEL_CXX_VERSION <= 600)) \
|| (defined(__BORLANDC__) && (__BORLANDC__ == 0x600) && (_MSC_VER < 1300))
// TODO: common macro for this #if. Or better yet, PP SEQ of non-standard types.
BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(__int8 )
BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(unsigned __int8 )
BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(__int16 )
BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(unsigned __int16)
BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(__int32 )
BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(unsigned __int32)
#ifdef __BORLANDC__
BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(unsigned __int64)
BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE( __int64)
#endif
#endif
#if defined(BOOST_HAS_LONG_LONG)
BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(boost::ulong_long_type)
BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(boost::long_long_type )
#elif defined(BOOST_HAS_MS_INT64)
BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(unsigned __int64)
BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE( __int64)
#endif
#undef BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE
#ifndef BOOST_NO_INTRINSIC_WCHAR_T
// 4.5/2
BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(need_promotion, wchar_t, true)
#endif
// 4.5/3 (integral bit-field) is not supported.
// 4.5/4
BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(need_promotion, bool, true)
// Get promoted type by index and cv qualifiers.
template<int Index, int IsConst, int IsVolatile> struct promote_from_index;
#define BOOST_TT_AUX_PROMOTE_FROM_INDEX(N,T) \
template<> struct promote_from_index<N,0,0> { typedef T type; }; \
template<> struct promote_from_index<N,0,1> { typedef T volatile type; }; \
template<> struct promote_from_index<N,1,0> { typedef T const type; }; \
template<> struct promote_from_index<N,1,1> { typedef T const volatile type; };
BOOST_TT_AUX_PROMOTE_FROM_INDEX(1, int )
BOOST_TT_AUX_PROMOTE_FROM_INDEX(2, unsigned int )
BOOST_TT_AUX_PROMOTE_FROM_INDEX(3, long )
BOOST_TT_AUX_PROMOTE_FROM_INDEX(4, unsigned long)
// WARNING: integral promotions to non-standard types
// long long and __int64 are not defined by the standard.
// Additional specialisations and overloads shouldn't
// introduce ambiguity, though.
#if defined(BOOST_HAS_LONG_LONG)
BOOST_TT_AUX_PROMOTE_FROM_INDEX(5, boost::long_long_type )
BOOST_TT_AUX_PROMOTE_FROM_INDEX(6, boost::ulong_long_type)
#elif defined(BOOST_HAS_MS_INT64)
BOOST_TT_AUX_PROMOTE_FROM_INDEX(7, __int64 )
BOOST_TT_AUX_PROMOTE_FROM_INDEX(8, unsigned __int64)
#endif
#undef BOOST_TT_AUX_PROMOTE_FROM_INDEX
// Define BOOST_TT_AUX_PROMOTED_INDEX_TESTER:
#if !defined(BOOST_MSVC)
template<int N>
struct sized_type_for_promotion
{
typedef char (&type)[N];
};
#define BOOST_TT_AUX_PROMOTED_INDEX_TESTER(I,T) \
sized_type_for_promotion<I>::type promoted_index_tester(T);
#else
#define BOOST_TT_AUX_PROMOTED_INDEX_TESTER(I,T) \
char (&promoted_index_tester(T))[I];
#endif
BOOST_TT_AUX_PROMOTED_INDEX_TESTER(1, int )
BOOST_TT_AUX_PROMOTED_INDEX_TESTER(2, unsigned int )
BOOST_TT_AUX_PROMOTED_INDEX_TESTER(3, long )
BOOST_TT_AUX_PROMOTED_INDEX_TESTER(4, unsigned long)
#if defined(BOOST_HAS_LONG_LONG)
BOOST_TT_AUX_PROMOTED_INDEX_TESTER(5, boost::long_long_type )
BOOST_TT_AUX_PROMOTED_INDEX_TESTER(6, boost::ulong_long_type)
#elif defined(BOOST_HAS_MS_INT64)
BOOST_TT_AUX_PROMOTED_INDEX_TESTER(7, __int64 )
BOOST_TT_AUX_PROMOTED_INDEX_TESTER(8, unsigned __int64)
#endif
#undef BOOST_TT_AUX_PROMOTED_INDEX_TESTER
// Get an index of promoted type for type T.
// Precondition: need_promotion<T>
template<class T>
struct promoted_index
{
static T testee; // undefined
BOOST_STATIC_CONSTANT(int, value = sizeof(promoted_index_tester(+testee)) );
// Unary plus promotes testee LOOK HERE ---> ^
};
template<class T>
struct integral_promotion_impl
{
typedef BOOST_DEDUCED_TYPENAME promote_from_index<
(boost::type_traits::detail::promoted_index<T>::value)
, (boost::is_const<T>::value)
, (boost::is_volatile<T>::value)
>::type type;
};
template<class T>
struct integral_promotion
: boost::mpl::eval_if<
need_promotion<T>
, integral_promotion_impl<T>
, boost::mpl::identity<T>
>
{
};
} }
BOOST_TT_AUX_TYPE_TRAIT_DEF1(
integral_promotion
, T
, BOOST_DEDUCED_TYPENAME
boost::type_traits::detail::integral_promotion<T>::type
)
}
#include <boost/type_traits/detail/bool_trait_undef.hpp>
#include <boost/type_traits/detail/type_trait_undef.hpp>
#endif // #ifndef FILE_boost_type_traits_integral_promotion_hpp_INCLUDED

View File

@ -0,0 +1,40 @@
// Copyright 2005 Alexander Nasonov.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef FILE_boost_type_traits_promote_hpp_INCLUDED
#define FILE_boost_type_traits_promote_hpp_INCLUDED
#include <boost/config.hpp>
#include <boost/type_traits/integral_promotion.hpp>
#include <boost/type_traits/floating_point_promotion.hpp>
// Should be the last #include
#include <boost/type_traits/detail/type_trait_def.hpp>
namespace boost {
namespace detail {
template<class T>
struct promote_impl
: integral_promotion<
BOOST_DEDUCED_TYPENAME floating_point_promotion<T>::type
>
{
};
}
BOOST_TT_AUX_TYPE_TRAIT_DEF1(
promote
, T
, BOOST_DEDUCED_TYPENAME ::boost::detail::promote_impl<T>::type
)
}
#include <boost/type_traits/detail/type_trait_undef.hpp>
#endif // #ifndef FILE_boost_type_traits_promote_hpp_INCLUDED

111
test/promote_basic_test.cpp Executable file
View File

@ -0,0 +1,111 @@
// Copyright 2005 Alexander Nasonov.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <climits>
#if !defined(BOOST_NO_CWCHAR)
#include <cwchar>
#endif
#include "promote_util.hpp"
struct Struct {};
int main()
{
// char types
#if CHAR_MAX <= INT_MAX
test_cv< char, int >();
#else
// TODO: dead branch?
test_cv< char, unsigned int >();
#endif
test_cv< signed char, int >();
#if UCHAR_MAX <= INT_MAX
test_cv< unsigned char, int >();
#else
test_cv< unsigned char, unsigned int >();
#endif
// short types
test_cv< short int, int >();
#if USHRT_MAX <= INT_MAX
test_cv< unsigned short, int >();
#else
test_cv< unsigned short, unsigned int >();
#endif
// int and long
test_cv< int, int >();
test_cv< unsigned int, unsigned int >();
test_cv< long, long >();
test_cv< unsigned long, unsigned long >();
#if defined(BOOST_NO_CWCHAR) || !defined(WCHAR_MAX) || !defined(WCHAR_MIN)
// Skip wchar_t promotion
#elif WCHAR_MAX <= INT_MAX
test_cv< wchar_t, int >();
#elif WCHAR_MIN == 0 && WCHAR_MAX <= UINT_MAX
test_cv< wchar_t, unsigned int >();
#elif WCHAR_MAX <= LONG_MAX
test_cv< wchar_t, long >();
#else
test_cv< wchar_t, unsigned long >();
#endif
// floating point promotion
test_cv< float , double >();
test_cv< double, double >();
// Other types
test_cv< Struct, Struct >();
test_cv< void , void >();
test_cv< void* , void* >();
// Array types
typedef int arr[3];
typedef int (&arr_ref)[3];
typedef int (*arr_ptr)[3];
test_cv< arr , arr >();
test_cv< arr_ptr, arr_ptr >();
test_no_cv<arr_ref,arr_ref>();
// Function types
typedef int (fun)();
typedef int (&fun_ref)();
typedef int (*fun_ptr)();
test_no_cv< fun , fun >();
test_no_cv< fun_ref, fun_ref >();
test_no_cv< fun_ptr, fun_ptr >();
// Member pointer types
typedef int (Struct::*mem_fun_ptr)();
typedef int Struct::*mem_ptr;
test_no_cv< mem_ptr, mem_ptr >();
test_no_cv< mem_fun_ptr, mem_fun_ptr >();
return 0;
}

151
test/promote_enum_test.cpp Executable file
View File

@ -0,0 +1,151 @@
// Copyright 2005-2006 Alexander Nasonov.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Status of some compilers:
//
// Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86
// /Za (disable extentions) is totally broken.
// /Ze (enable extentions) promotes UIntEnum incorrectly to int.
// See http://lab.msdn.microsoft.com/ProductFeedback/viewfeedback.aspx?feedbackid=22b0a6b7-120f-4ca0-9136-fa1b25b26efe
//
// Intel 9.0.028 for Windows has a similar problem:
// https://premier.intel.com/IssueDetail.aspx?IssueID=365073
//
// gcc 3.4.4 with -fshort-enums option on x86
// Dummy value is required, otherwise gcc promotes Enum1
// to unsigned int although USHRT_MAX <= INT_MAX.
// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=24063
//
// CC: Sun WorkShop 6 update 2 C++ 5.3 Patch 111685-20 2004/03/19
// on SPARC V9 64-bit processor (-xarch=v9 flag)
// Dummy values are required for LongEnum3 and LongEnum4.
//
// CC: Sun C++ 5.7 Patch 117830-03 2005/07/21
// ICE in boost/type_traits/is_enum.hpp at line 67.
#include <climits>
#include "promote_util.hpp"
enum IntEnum1 { IntEnum1_min = -5 , IntEnum1_max = 5 };
enum IntEnum2 { IntEnum2_min = SHRT_MIN, IntEnum2_max = SHRT_MAX };
enum IntEnum3 { IntEnum3_min = INT_MIN , IntEnum3_max = INT_MAX };
enum IntEnum4 { IntEnum4_value = INT_MAX };
enum IntEnum5 { IntEnum5_value = INT_MIN };
void test_promote_to_int()
{
test_cv<IntEnum1,int>();
test_cv<IntEnum2,int>();
test_cv<IntEnum3,int>();
test_cv<IntEnum4,int>();
test_cv<IntEnum5,int>();
}
#if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ == 4 && USHRT_MAX <= INT_MAX)
enum Enum1 { Enum1_value = USHRT_MAX };
#else
// workaround for bug #24063 in gcc 3.4
// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=24063
namespace gcc_short_enums_workaround {
enum short_enum { value = 1 };
template<bool ShortEnumsIsOn>
struct select
{
// Adding negative dummy value doesn't change
// promoted type because USHRT_MAX <= INT_MAX.
enum type { dummy = -1, value = USHRT_MAX };
};
template<>
struct select<false>
{
// No dummy value
enum type { value = USHRT_MAX };
};
} // namespace gcc_short_enums_workaround
typedef gcc_short_enums_workaround::select<
sizeof(gcc_short_enums_workaround::short_enum) != sizeof(int)
>::type Enum1;
#endif
void test_promote_to_int_or_uint()
{
#if USHRT_MAX <= INT_MAX
test_cv<Enum1, int>();
#else
test_cv<Enum1, unsigned int>();
#endif
}
#if (defined(BOOST_MSVC) && BOOST_MSVC <= 1400 ) || \
(defined(BOOST_INTEL_WIN) && BOOST_INTEL_WIN <= 900)
// Don't test UIntEnum on VC++ 8.0 and Intel for Windows 9.0,
// they are broken. More info is on top of this file.
#else
enum UIntEnum { UIntEnum_max = UINT_MAX };
void test_promote_to_uint()
{
test_cv< UIntEnum, unsigned int >();
}
#endif
// Enums can't be promoted to [unsigned] long if sizeof(int) == sizeof(long).
#if INT_MAX < LONG_MAX
enum LongEnum1 { LongEnum1_min = -1 , LongEnum1_max = UINT_MAX };
enum LongEnum2 { LongEnum2_min = LONG_MIN, LongEnum2_max = LONG_MAX };
enum LongEnum3
{
LongEnum3_value = LONG_MAX
#if defined(__SUNPRO_CC) && __SUNPRO_CC <= 0x530
, LongEnum3_dummy = -1
#endif
};
enum LongEnum4
{
LongEnum4_value = LONG_MIN
#if defined(__SUNPRO_CC) && __SUNPRO_CC <= 0x530
, LongEnum4_dummy = 1
#endif
};
void test_promote_to_long()
{
test_cv< LongEnum1, long >();
test_cv< LongEnum2, long >();
test_cv< LongEnum3, long >();
test_cv< LongEnum4, long >();
}
enum ULongEnum { ULongEnum_value = ULONG_MAX };
void test_promote_to_ulong()
{
test_cv< ULongEnum, unsigned long >();
}
#endif // #if INT_MAX < LONG_MAX
int main()
{
return 0;
}

47
test/promote_mpl_test.cpp Executable file
View File

@ -0,0 +1,47 @@
// Copyright 2005 Alexander Nasonov.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/mpl/at.hpp>
#include <boost/mpl/lambda.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/promote.hpp>
namespace mpl = boost::mpl;
int main()
{
using namespace mpl::placeholders;
typedef mpl::vector< char
, signed char // 1
, unsigned char
, short int const // 3
, unsigned short int
, int volatile // 5
, unsigned int // 6
, long // 7
, unsigned long // 8
, float const // 9
> types;
typedef mpl::transform< types
, mpl::lambda< boost::promote<_> >::type
>::type promoted;
BOOST_STATIC_ASSERT(( ::boost::is_same< mpl::at_c<promoted,1>::type, int >::value ));
BOOST_STATIC_ASSERT(( ::boost::is_same< mpl::at_c<promoted,3>::type, int const >::value ));
BOOST_STATIC_ASSERT(( ::boost::is_same< mpl::at_c<promoted,5>::type, int volatile >::value ));
BOOST_STATIC_ASSERT(( ::boost::is_same< mpl::at_c<promoted,6>::type, unsigned int >::value ));
BOOST_STATIC_ASSERT(( ::boost::is_same< mpl::at_c<promoted,7>::type, long >::value ));
BOOST_STATIC_ASSERT(( ::boost::is_same< mpl::at_c<promoted,8>::type, unsigned long >::value ));
BOOST_STATIC_ASSERT(( ::boost::is_same< mpl::at_c<promoted,9>::type, double const >::value ));
return 0;
}

37
test/promote_util.hpp Executable file
View File

@ -0,0 +1,37 @@
// Copyright 2005 Alexander Nasonov.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef FILE_boost_libs_type_traits_test_promote_util_hpp_INCLUDED
#define FILE_boost_libs_type_traits_test_promote_util_hpp_INCLUDED
#include <boost/type_traits/promote.hpp>
#include <boost/config.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
template<class T, class Promoted>
inline void test_no_cv()
{
typedef BOOST_DEDUCED_TYPENAME boost::promote<T>::type promoted;
BOOST_STATIC_ASSERT(( boost::is_same<promoted,Promoted>::value ));
}
template<class T, class Promoted>
inline void test_cv()
{
typedef BOOST_DEDUCED_TYPENAME ::boost::promote<T >::type promoted;
typedef BOOST_DEDUCED_TYPENAME ::boost::promote<T const >::type promoted_c;
typedef BOOST_DEDUCED_TYPENAME ::boost::promote<T volatile>::type promoted_v;
typedef BOOST_DEDUCED_TYPENAME ::boost::promote<T const volatile>::type promoted_cv;
BOOST_STATIC_ASSERT(( ::boost::is_same< promoted , Promoted >::value ));
BOOST_STATIC_ASSERT(( ::boost::is_same< promoted_c , Promoted const >::value ));
BOOST_STATIC_ASSERT(( ::boost::is_same< promoted_v , Promoted volatile >::value ));
BOOST_STATIC_ASSERT(( ::boost::is_same< promoted_cv, Promoted const volatile >::value ));
}
#endif // #ifndef FILE_boost_libs_type_traits_test_promote_util_hpp_INCLUDED