From c02516b25b2b51c5e835c07427ae3dbe1364af12 Mon Sep 17 00:00:00 2001 From: John Maddock Date: Wed, 12 Jan 2011 13:29:37 +0000 Subject: [PATCH] Fix comon_type to actually work when typeof isn't in use. Applies fixes from Vicente Botet. [SVN r68040] --- .../type_traits/detail/common_type_imp.hpp | 67 ++++-- test/check_type.hpp | 26 +++ test/common_type_2_test.cpp | 212 ++++++++++++++++++ test/common_type_test.cpp | 103 +++++++++ 4 files changed, 390 insertions(+), 18 deletions(-) create mode 100644 test/common_type_2_test.cpp diff --git a/include/boost/type_traits/detail/common_type_imp.hpp b/include/boost/type_traits/detail/common_type_imp.hpp index 9e06282..59c7743 100644 --- a/include/boost/type_traits/detail/common_type_imp.hpp +++ b/include/boost/type_traits/detail/common_type_imp.hpp @@ -72,21 +72,45 @@ struct propagate_cv< const volatile From, To > { typedef To const volatile type; }; /******************************************************************************* - * struct is_signable_integral + * struct is_integral_or_enum * * This metafunction determines if T is an integral type which can be made * signed or unsigned. ******************************************************************************/ template< class T > -struct is_signable_integral +struct is_integral_or_enum : mpl::or_< is_integral, is_enum > { }; template<> -struct is_signable_integral< bool > +struct is_integral_or_enum< bool > : false_type { }; +/******************************************************************************* + * struct make_unsigned_soft + * struct make_signed_soft + * + * These metafunction are identical to make_unsigned and make_signed, + * respetively, except for special-casing bool. + ******************************************************************************/ + +template< class T > +struct make_unsigned_soft + : make_unsigned +{ }; +template<> +struct make_unsigned_soft< bool > +{ typedef bool type; }; + +template< class T > +struct make_signed_soft + : make_signed +{ }; +template<> +struct make_signed_soft< bool > +{ typedef bool type; }; + /******************************************************************************* * struct sizeof_t * typedef ... yes_type @@ -185,12 +209,21 @@ struct select< Sequence, N, N > * { V*, W*, V'*, W'* } * where V' is V with whatever cv-qualifiers are on W, and W' is W * with whatever cv-qualifiers are on V - * else T' and U' are both "signable integral types" (integral and enum - * types excepting bool), then: + * else if T' and U' are both integral or enum types, then: * define the set of NominalCandidates to be - * { unsigned(T'), unsigned(U'), signed(T'), signed(U') } - * where unsigned(X) is make_unsigned::type and signed(X) is - * make_signed::type + * { + * unsigned_soft(T'), + * unsigned_soft(U'), + * signed_soft(T'), + * signed_soft(U'), + * T', + * U', + * unsigned int, + * int + * } + * where unsigned_soft(X) is make_unsigned_soft::type and + * signed_soft(X) is make_signed_soft::type (these are all + * generally necessary to cover the various integral promotion cases) * else * define the set of NominalCandidates to be * { T', U' } @@ -231,22 +264,20 @@ template< class T, class U, class V = typename remove_cv< typename remove_reference::type >::type, class W = typename remove_cv< typename remove_reference::type >::type, - bool = is_signable_integral::value && is_signable_integral::value + bool = is_integral_or_enum::value && is_integral_or_enum::value > -struct nominal_candidates; - -template< class T, class U, class V, class W > -struct nominal_candidates< T, U, V, W, false > +struct nominal_candidates { typedef mpl::vector2 type; }; template< class T, class U, class V, class W > struct nominal_candidates< T, U, V, W, true > { - typedef mpl::vector4< - typename make_unsigned::type, - typename make_unsigned::type, - typename make_signed::type, - typename make_signed::type + typedef boost::mpl::vector8< + typename make_unsigned_soft::type, + typename make_unsigned_soft::type, + typename make_signed_soft::type, + typename make_signed_soft::type, + V, W, unsigned int, int > type; }; diff --git a/test/check_type.hpp b/test/check_type.hpp index 700551a..33ed399 100644 --- a/test/check_type.hpp +++ b/test/check_type.hpp @@ -40,6 +40,32 @@ do{\ << BOOST_STRINGIZE(expression) << "\"");\ }while(0) +#define BOOST_CHECK_TYPE3(type_expression, type_expression_suffix, expected_type)\ +do{\ + if(!::boost::is_same< type_expression, type_expression_suffix, expected_type >::value){\ + BOOST_CHECK_MESSAGE(false, "The expression: \"" << BOOST_STRINGIZE(expression)\ + << "\" did not have the expected type:\n\tevaluating: boost::is_same<"\ + << BOOST_STRINGIZE((type_expression, type_expression_suffix)) << ", " << BOOST_STRINGIZE(expected_type)\ + << ">" << "\n\tfound: "\ + << typeid(::boost::is_same< type_expression, type_expression_suffix, expected_type >).name());\ + }else\ + BOOST_CHECK_MESSAGE(true, "Validating Type Expression: \""\ + << BOOST_STRINGIZE(expression) << "\"");\ +}while(0) + +#define BOOST_CHECK_TYPE4(type_expression, suffix1, suffix2, expected_type)\ +do{\ + if(!::boost::is_same< type_expression, suffix1, suffix2, expected_type >::value){\ + BOOST_CHECK_MESSAGE(false, "The expression: \"" << BOOST_STRINGIZE(expression)\ + << "\" did not have the expected type:\n\tevaluating: boost::is_same<"\ + << BOOST_STRINGIZE((type_expression, suffix1, suffix2)) << ", " << BOOST_STRINGIZE(expected_type)\ + << ">" << "\n\tfound: "\ + << typeid(::boost::is_same< type_expression, suffix1, suffix2, expected_type >).name());\ + }else\ + BOOST_CHECK_MESSAGE(true, "Validating Type Expression: \""\ + << BOOST_STRINGIZE(expression) << "\"");\ +}while(0) + #endif diff --git a/test/common_type_2_test.cpp b/test/common_type_2_test.cpp new file mode 100644 index 0000000..f878133 --- /dev/null +++ b/test/common_type_2_test.cpp @@ -0,0 +1,212 @@ +// common_type_test.cpp ----------------------------------------------------// + +// Copyright 2010 Beman Dawes + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +#define BOOST_COMMON_TYPE_DONT_USE_TYPEOF 1 + +#include "test.hpp" +#include "check_type.hpp" +#ifdef TEST_STD +# include +#else +# include +#endif +#include + +#ifdef BOOST_INTEL +#pragma warning(disable: 304 383) +#endif + +struct C1 {}; + +struct C2 {}; + + +struct C3 : C2 {}; +struct C1C2 { + C1C2() {} + C1C2(C1 const&) {} + C1C2(C2 const&) {} + C1C2& operator=(C1C2 const&) { + return *this; + } +}; + +template +void proc2(typename boost::common_type::type const& ) {} + +template +void proc3(typename boost::common_type::type const& ) {} + +template +void assignation_2() { +typedef typename boost::common_type::type AC; + A a; + C c; + AC ac; + ac=a; + ac=c; + + proc2(a); + proc2(c); + +} + +template +void assignation_3() { +typedef typename boost::common_type::type ABC; + A a; + B b; + C c; + ABC abc; + + abc=a; + abc=b; + abc=c; + + proc3(a); + proc3(b); + proc3(c); +} + +C1C2 c1c2; +C1 c1; + +int f(C1C2 ) { return 1;} +int f(C1 ) { return 2;} +template +OSTREAM& operator<<(OSTREAM& os, C1 const&) {return os;} + +C1C2& declval_C1C2() {return c1c2;} +C1& declval_C1(){return c1;} +bool declval_bool(){return true;} + + +TT_TEST_BEGIN(common_type) +{ + assignation_2(); + typedef tt::common_type::type T1; + typedef tt::common_type::type T2; + typedef tt::common_type::type T3; +#if defined(BOOST_NO_DECLTYPE) && !defined(BOOST_COMMON_TYPE_DONT_USE_TYPEOF) + // fails if BOOST_COMMON_TYPE_DONT_USE_TYPEOF: + typedef tt::common_type::type T4; +#endif + typedef tt::common_type::type T5; + + assignation_2(); + assignation_2(); + assignation_2(); + assignation_3(); + assignation_3(); + assignation_3(); + assignation_3(); + //assignation_3(); // fails because the common type is the third + + BOOST_CHECK_TYPE(tt::common_type::type, int); + BOOST_CHECK_TYPE(tt::common_type::type, char); + + BOOST_CHECK_TYPE3(tt::common_type::type, char); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, unsigned int); +#ifndef BOOST_NO_LONG_LONG + BOOST_CHECK_TYPE3(tt::common_type::type, boost::long_long_type); + BOOST_CHECK_TYPE3(tt::common_type::type, boost::ulong_long_type); +#endif + BOOST_CHECK_TYPE3(tt::common_type::type, double); + + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, unsigned char); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, unsigned int); +#ifndef BOOST_NO_LONG_LONG + BOOST_CHECK_TYPE3(tt::common_type::type, boost::long_long_type); + BOOST_CHECK_TYPE3(tt::common_type::type, boost::ulong_long_type); +#endif + BOOST_CHECK_TYPE3(tt::common_type::type, double); + + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, short); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, unsigned int); +#ifndef BOOST_NO_LONG_LONG + BOOST_CHECK_TYPE3(tt::common_type::type, boost::long_long_type); + BOOST_CHECK_TYPE3(tt::common_type::type, boost::ulong_long_type); +#endif + BOOST_CHECK_TYPE3(tt::common_type::type, double); + + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, unsigned short); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, unsigned int); +#ifndef BOOST_NO_LONG_LONG + BOOST_CHECK_TYPE3(tt::common_type::type, boost::long_long_type); + BOOST_CHECK_TYPE3(tt::common_type::type, boost::ulong_long_type); +#endif + BOOST_CHECK_TYPE3(tt::common_type::type, double); + + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, unsigned int); +#ifndef BOOST_NO_LONG_LONG + BOOST_CHECK_TYPE3(tt::common_type::type, boost::long_long_type); + BOOST_CHECK_TYPE3(tt::common_type::type, boost::ulong_long_type); +#endif + BOOST_CHECK_TYPE3(tt::common_type::type, double); + + BOOST_CHECK_TYPE3(tt::common_type::type, unsigned int); + BOOST_CHECK_TYPE3(tt::common_type::type, unsigned int); + BOOST_CHECK_TYPE3(tt::common_type::type, unsigned int); + BOOST_CHECK_TYPE3(tt::common_type::type, unsigned int); + BOOST_CHECK_TYPE3(tt::common_type::type, unsigned int); + BOOST_CHECK_TYPE3(tt::common_type::type, unsigned int); +#ifndef BOOST_NO_LONG_LONG + BOOST_CHECK_TYPE3(tt::common_type::type, boost::long_long_type); + BOOST_CHECK_TYPE3(tt::common_type::type, boost::ulong_long_type); +#endif + BOOST_CHECK_TYPE3(tt::common_type::type, double); + +#ifndef BOOST_NO_LONG_LONG + BOOST_CHECK_TYPE3(tt::common_type::type, boost::long_long_type); + BOOST_CHECK_TYPE3(tt::common_type::type, boost::long_long_type); + BOOST_CHECK_TYPE3(tt::common_type::type, boost::long_long_type); + BOOST_CHECK_TYPE3(tt::common_type::type, boost::long_long_type); + BOOST_CHECK_TYPE3(tt::common_type::type, boost::long_long_type); + BOOST_CHECK_TYPE3(tt::common_type::type, boost::long_long_type); + BOOST_CHECK_TYPE3(tt::common_type::type, boost::long_long_type); + BOOST_CHECK_TYPE3(tt::common_type::type, boost::ulong_long_type); + BOOST_CHECK_TYPE3(tt::common_type::type, double); +#endif + BOOST_CHECK_TYPE3(tt::common_type::type, double); + BOOST_CHECK_TYPE3(tt::common_type::type, double); + BOOST_CHECK_TYPE3(tt::common_type::type, double); + BOOST_CHECK_TYPE3(tt::common_type::type, double); + BOOST_CHECK_TYPE3(tt::common_type::type, double); + BOOST_CHECK_TYPE3(tt::common_type::type, double); +#ifndef BOOST_NO_LONG_LONG + BOOST_CHECK_TYPE3(tt::common_type::type, double); + BOOST_CHECK_TYPE3(tt::common_type::type, double); +#endif + BOOST_CHECK_TYPE3(tt::common_type::type, double); + + BOOST_CHECK_TYPE4(tt::common_type::type, double); +#ifndef BOOST_NO_LONG_LONG + BOOST_CHECK_TYPE4(tt::common_type::type, boost::long_long_type); +#endif +} +TT_TEST_END diff --git a/test/common_type_test.cpp b/test/common_type_test.cpp index 22a0fd0..bd1a54a 100644 --- a/test/common_type_test.cpp +++ b/test/common_type_test.cpp @@ -103,5 +103,108 @@ TT_TEST_BEGIN(common_type) assignation_3(); assignation_3(); //assignation_3(); // fails because the common type is the third + + BOOST_CHECK_TYPE(tt::common_type::type, int); + BOOST_CHECK_TYPE(tt::common_type::type, char); + + BOOST_CHECK_TYPE3(tt::common_type::type, char); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, unsigned int); +#ifndef BOOST_NO_LONG_LONG + BOOST_CHECK_TYPE3(tt::common_type::type, boost::long_long_type); + BOOST_CHECK_TYPE3(tt::common_type::type, boost::ulong_long_type); +#endif + BOOST_CHECK_TYPE3(tt::common_type::type, double); + + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, unsigned char); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, unsigned int); +#ifndef BOOST_NO_LONG_LONG + BOOST_CHECK_TYPE3(tt::common_type::type, boost::long_long_type); + BOOST_CHECK_TYPE3(tt::common_type::type, boost::ulong_long_type); +#endif + BOOST_CHECK_TYPE3(tt::common_type::type, double); + + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, short); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, unsigned int); +#ifndef BOOST_NO_LONG_LONG + BOOST_CHECK_TYPE3(tt::common_type::type, boost::long_long_type); + BOOST_CHECK_TYPE3(tt::common_type::type, boost::ulong_long_type); +#endif + BOOST_CHECK_TYPE3(tt::common_type::type, double); + + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, unsigned short); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, unsigned int); +#ifndef BOOST_NO_LONG_LONG + BOOST_CHECK_TYPE3(tt::common_type::type, boost::long_long_type); + BOOST_CHECK_TYPE3(tt::common_type::type, boost::ulong_long_type); +#endif + BOOST_CHECK_TYPE3(tt::common_type::type, double); + + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, int); + BOOST_CHECK_TYPE3(tt::common_type::type, unsigned int); +#ifndef BOOST_NO_LONG_LONG + BOOST_CHECK_TYPE3(tt::common_type::type, boost::long_long_type); + BOOST_CHECK_TYPE3(tt::common_type::type, boost::ulong_long_type); +#endif + BOOST_CHECK_TYPE3(tt::common_type::type, double); + + BOOST_CHECK_TYPE3(tt::common_type::type, unsigned int); + BOOST_CHECK_TYPE3(tt::common_type::type, unsigned int); + BOOST_CHECK_TYPE3(tt::common_type::type, unsigned int); + BOOST_CHECK_TYPE3(tt::common_type::type, unsigned int); + BOOST_CHECK_TYPE3(tt::common_type::type, unsigned int); + BOOST_CHECK_TYPE3(tt::common_type::type, unsigned int); +#ifndef BOOST_NO_LONG_LONG + BOOST_CHECK_TYPE3(tt::common_type::type, boost::long_long_type); + BOOST_CHECK_TYPE3(tt::common_type::type, boost::ulong_long_type); +#endif + BOOST_CHECK_TYPE3(tt::common_type::type, double); + +#ifndef BOOST_NO_LONG_LONG + BOOST_CHECK_TYPE3(tt::common_type::type, boost::long_long_type); + BOOST_CHECK_TYPE3(tt::common_type::type, boost::long_long_type); + BOOST_CHECK_TYPE3(tt::common_type::type, boost::long_long_type); + BOOST_CHECK_TYPE3(tt::common_type::type, boost::long_long_type); + BOOST_CHECK_TYPE3(tt::common_type::type, boost::long_long_type); + BOOST_CHECK_TYPE3(tt::common_type::type, boost::long_long_type); + BOOST_CHECK_TYPE3(tt::common_type::type, boost::long_long_type); + BOOST_CHECK_TYPE3(tt::common_type::type, boost::ulong_long_type); + BOOST_CHECK_TYPE3(tt::common_type::type, double); +#endif + BOOST_CHECK_TYPE3(tt::common_type::type, double); + BOOST_CHECK_TYPE3(tt::common_type::type, double); + BOOST_CHECK_TYPE3(tt::common_type::type, double); + BOOST_CHECK_TYPE3(tt::common_type::type, double); + BOOST_CHECK_TYPE3(tt::common_type::type, double); + BOOST_CHECK_TYPE3(tt::common_type::type, double); +#ifndef BOOST_NO_LONG_LONG + BOOST_CHECK_TYPE3(tt::common_type::type, double); + BOOST_CHECK_TYPE3(tt::common_type::type, double); +#endif + BOOST_CHECK_TYPE3(tt::common_type::type, double); + + BOOST_CHECK_TYPE4(tt::common_type::type, double); +#ifndef BOOST_NO_LONG_LONG + BOOST_CHECK_TYPE4(tt::common_type::type, boost::long_long_type); +#endif } TT_TEST_END