From 3a86e88eb349cb483219376504690953d97095be Mon Sep 17 00:00:00 2001 From: Aleksey Gurtovoy Date: Fri, 7 Feb 2003 11:27:00 +0000 Subject: [PATCH] fix various QoI issues [SVN r17262] --- include/boost/mpl/aux_/back_impl.hpp | 10 +- include/boost/mpl/aux_/begin_end_impl.hpp | 11 ++- include/boost/mpl/aux_/debug_print.hpp | 3 +- include/boost/mpl/aux_/deref_wknd.hpp | 4 +- include/boost/mpl/aux_/has_xxx.hpp | 43 +++++++-- include/boost/mpl/inherit.hpp | 12 ++- include/boost/mpl/is_sequence.hpp | 52 +++++++++- include/boost/mpl/next.hpp | 2 +- include/boost/mpl/prior.hpp | 2 +- include/boost/mpl/sequence_tag.hpp | 112 ++++++++++++++-------- test/aux_/has_xxx.cpp | 12 ++- test/is_sequence.cpp | 38 ++++++++ 12 files changed, 231 insertions(+), 70 deletions(-) create mode 100644 test/is_sequence.cpp diff --git a/include/boost/mpl/aux_/back_impl.hpp b/include/boost/mpl/aux_/back_impl.hpp index eaba51f..d20bb9c 100644 --- a/include/boost/mpl/aux_/back_impl.hpp +++ b/include/boost/mpl/aux_/back_impl.hpp @@ -21,14 +21,14 @@ #include "boost/mpl/prior.hpp" #include "boost/mpl/aux_/deref_wknd.hpp" #include "boost/mpl/aux_/traits_lambda_spec.hpp" -#include "boost/config.hpp" +#include "boost/mpl/aux_/config/eti.hpp" namespace boost { namespace mpl { // default implementation, requires at least bi-directional iterators; // conrete sequences might override it by specializing either the -// |back_traits| or the primary |back| template +// 'back_traits' or the primary 'back' template template< typename Tag > struct back_traits @@ -36,10 +36,10 @@ struct back_traits template< typename Sequence > struct algorithm { typedef typename end::type iter_; -#if !defined(BOOST_MSVC) || BOOST_MSVC > 1200 - typedef typename iter_::prior last_; -#else +#if defined(BOOST_MPL_MSVC_70_ETI_BUG) typedef typename prior::type last_; +#else + typedef typename iter_::prior last_; #endif typedef typename BOOST_MPL_AUX_DEREF_WNKD(last_) type; }; diff --git a/include/boost/mpl/aux_/begin_end_impl.hpp b/include/boost/mpl/aux_/begin_end_impl.hpp index 96bfc7a..fb6241a 100644 --- a/include/boost/mpl/aux_/begin_end_impl.hpp +++ b/include/boost/mpl/aux_/begin_end_impl.hpp @@ -19,6 +19,7 @@ #include "boost/mpl/begin_end_fwd.hpp" #include "boost/mpl/sequence_tag_fwd.hpp" +#include "boost/mpl/void.hpp" #include "boost/mpl/aux_/traits_lambda_spec.hpp" #include "boost/mpl/aux_/config/eti.hpp" @@ -67,12 +68,12 @@ AUX_AGLORITM_TRAIT_SPEC(end, nested_begin_end_tag, typename Sequence::end) // if a type 'T' does not contain 'begin/end' or 'tag' members // and doesn't specialize either 'begin/end' or 'begin_traits/end_traits' // templates, then we end up here -AUX_AGLORITM_TRAIT_SPEC(begin, non_sequence_tag, non_sequence_tag) -AUX_AGLORITM_TRAIT_SPEC(end, non_sequence_tag, non_sequence_tag) +AUX_AGLORITM_TRAIT_SPEC(begin, non_sequence_tag, void_) +AUX_AGLORITM_TRAIT_SPEC(end, non_sequence_tag, void_) -#if defined(BOOST_MPL_MSVC_ETI_BUG) -AUX_AGLORITM_TRAIT_SPEC(begin, int, non_sequence_tag) -AUX_AGLORITM_TRAIT_SPEC(end, int, non_sequence_tag) +#if defined(BOOST_MPL_MSVC_70_ETI_BUG) +AUX_AGLORITM_TRAIT_SPEC(begin, int, int) +AUX_AGLORITM_TRAIT_SPEC(end, int, int) #endif # undef AUX_AGLORITM_TRAIT_SPEC diff --git a/include/boost/mpl/aux_/debug_print.hpp b/include/boost/mpl/aux_/debug_print.hpp index 787b083..17ceddb 100644 --- a/include/boost/mpl/aux_/debug_print.hpp +++ b/include/boost/mpl/aux_/debug_print.hpp @@ -32,8 +32,7 @@ struct print_ } // namespace boost #define BOOST_MPL_AUX_DEBUG_PRINT(type) \ -bool const mpl_debug_print_##type \ - = boost::mpl::aux::print_::value \ +enum { mpl_debug_print_##type = boost::mpl::aux::print_::value } ;\ /**/ #endif // BOOST_MPL_AUX_DEBUG_PRINT_HPP_INCLUDED diff --git a/include/boost/mpl/aux_/deref_wknd.hpp b/include/boost/mpl/aux_/deref_wknd.hpp index 5abce29..65d579b 100644 --- a/include/boost/mpl/aux_/deref_wknd.hpp +++ b/include/boost/mpl/aux_/deref_wknd.hpp @@ -19,7 +19,7 @@ #include "boost/mpl/aux_/config/eti.hpp" -#if defined(BOOST_MPL_MSVC_ETI_BUG) +#if defined(BOOST_MPL_MSVC_70_ETI_BUG) namespace boost { namespace mpl { namespace aux { @@ -31,7 +31,7 @@ struct deref_wknd template<> struct deref_wknd { - typedef deref_wknd type; + typedef int type; }; }}} // namespace boost::mpl::aux diff --git a/include/boost/mpl/aux_/has_xxx.hpp b/include/boost/mpl/aux_/has_xxx.hpp index 2ca7441..11c2191 100644 --- a/include/boost/mpl/aux_/has_xxx.hpp +++ b/include/boost/mpl/aux_/has_xxx.hpp @@ -34,7 +34,7 @@ template< typename T > \ boost::mpl::aux::yes_tag \ trait##_helper( \ - T const volatile* \ + boost::mpl::aux::type_wrapper const volatile* \ , boost::mpl::aux::type_wrapper* = 0 \ ); \ \ @@ -44,8 +44,9 @@ trait##_helper(...); \ template< typename T > \ struct trait \ { \ - BOOST_STATIC_CONSTANT(bool, value = \ - sizeof((trait##_helper)(static_cast(0))) \ + typedef boost::mpl::aux::type_wrapper t_; \ + BOOST_STATIC_CONSTANT(bool, value = \ + sizeof((trait##_helper)(static_cast(0))) \ == sizeof(boost::mpl::aux::yes_tag) \ ); \ }; \ @@ -53,6 +54,10 @@ struct trait \ # else +#include "boost/mpl/if.hpp" +#include "boost/mpl/bool_c.hpp" +#include "boost/preprocessor/cat.hpp" + // agurt, 11/sep/02: MSVC version, based on a USENET newsgroup's posting by // John Madsen (comp.lang.c++.moderated, 1999-11-12 19:17:06 GMT); // note that the code is _not_ standard-conforming, but it works, @@ -61,12 +66,29 @@ struct trait \ // Modified dwa 8/Oct/02 to handle reference types. namespace boost { namespace mpl { namespace aux { + struct has_xxx_tag; + +template< typename T > +struct msvc_is_incomplete +{ + struct incomplete_; + BOOST_STATIC_CONSTANT(bool, value = + sizeof(void (T::*)()) == sizeof(void (incomplete_::*)()) + ); +}; + +template<> +struct msvc_is_incomplete +{ + BOOST_STATIC_CONSTANT(bool, value = false); +}; + }}} # define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF_(trait, name, unused) \ template< typename T, typename name = ::boost::mpl::aux::has_xxx_tag > \ -struct trait : T \ +struct BOOST_PP_CAT(trait,_impl) : T \ { \ private: \ static boost::mpl::aux::no_tag test(void(*)(::boost::mpl::aux::has_xxx_tag)); \ @@ -79,6 +101,15 @@ struct trait : T \ ); \ }; \ \ +template< typename T > struct trait \ + : boost::mpl::if_c< \ + boost::mpl::aux::msvc_is_incomplete::value \ + , boost::mpl::bool_c \ + , BOOST_PP_CAT(trait,_impl) \ + >::type \ +{ \ +}; \ +\ BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, void) \ BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, bool) \ BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, char) \ @@ -96,9 +127,9 @@ BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, long double) \ /**/ # define BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, T) \ -template<> struct trait \ +template<> struct trait \ { \ - enum { value = false }; \ + BOOST_STATIC_CONSTANT(bool,value = false); \ }; \ /**/ diff --git a/include/boost/mpl/inherit.hpp b/include/boost/mpl/inherit.hpp index 285a19e..00c7082 100644 --- a/include/boost/mpl/inherit.hpp +++ b/include/boost/mpl/inherit.hpp @@ -72,18 +72,21 @@ struct inherit2 : T1, T2 { typedef inherit2 type; + BOOST_MPL_AUX_LAMBDA_SUPPORT(2, inherit2, (T1,T2)) }; template< typename T1 > struct inherit2 { typedef T1 type; + BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(2, inherit2, (T1,empty_base)) }; template< typename T2 > struct inherit2 { typedef T2 type; + BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(2, inherit2, (empty_base,T2)) }; // needed to disambiguate the previous two in case when both @@ -92,6 +95,7 @@ template<> struct inherit2 { typedef empty_base type; + BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(2, inherit2, (empty_base,empty_base)) }; #else @@ -150,7 +154,7 @@ struct inherit2 >::template result_< inherit2,T1,T2 > { typedef typename inherit2::type_ type; - BOOST_MPL_AUX_LAMBDA_SUPPORT(2,inherit2,(T1,T2)) + BOOST_MPL_AUX_LAMBDA_SUPPORT(2, inherit2, (T1,T2)) }; #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION @@ -183,7 +187,11 @@ struct BOOST_PP_CAT(inherit,n) , BOOST_PP_CAT(T,n) > { - BOOST_MPL_AUX_LAMBDA_SUPPORT(n,BOOST_PP_CAT(inherit,n),(BOOST_MPL_PP_PARAMS(n, T))) + BOOST_MPL_AUX_LAMBDA_SUPPORT( + n + , BOOST_PP_CAT(inherit,n) + , (BOOST_MPL_PP_PARAMS(n, T)) + ) }; BOOST_MPL_AUX_VOID_SPEC(n, BOOST_PP_CAT(inherit,n)) diff --git a/include/boost/mpl/is_sequence.hpp b/include/boost/mpl/is_sequence.hpp index 032ffc1..6eca6ad 100644 --- a/include/boost/mpl/is_sequence.hpp +++ b/include/boost/mpl/is_sequence.hpp @@ -18,25 +18,75 @@ #define BOOST_MPL_IS_SEQUENCE_HPP_INCLUDED #include "boost/mpl/logical/not.hpp" +#include "boost/mpl/logical/or.hpp" #include "boost/mpl/begin_end.hpp" +#include "boost/mpl/if.hpp" +#include "boost/mpl/bool_c.hpp" #include "boost/mpl/sequence_tag_fwd.hpp" +#include "boost/mpl/identity.hpp" +#include "boost/mpl/void.hpp" +#include "boost/mpl/aux_/has_tag.hpp" +#include "boost/mpl/aux_/has_begin.hpp" #include "boost/mpl/aux_/void_spec.hpp" #include "boost/mpl/aux_/lambda_support.hpp" #include "boost/mpl/aux_/config/eti.hpp" +#include "boost/mpl/aux_/config/workaround.hpp" #include "boost/type_traits/is_same.hpp" +#include "boost/type_traits/is_class.hpp" namespace boost { namespace mpl { +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + +namespace aux { + +template< typename T > struct is_sequence_impl + : logical_or< + identity< aux::has_tag > + , identity< aux::has_begin > + > +{ +}; + +} // namespace aux + +template< + typename BOOST_MPL_AUX_VOID_SPEC_PARAM(T) + > +struct is_sequence + : if_< + boost::is_class + , aux::is_sequence_impl + , bool_c + >::type +{ + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_sequence,(T)) +}; + +#elif defined(BOOST_NO_MPL_AUX_HAS_XXX) + template< typename BOOST_MPL_AUX_VOID_SPEC_PARAM(T) > struct is_sequence - : logical_not< is_same< typename begin::type, non_sequence_tag > > + : bool_c +{ +}; + +#else + +template< + typename BOOST_MPL_AUX_VOID_SPEC_PARAM(T) + > +struct is_sequence + : logical_not< is_same< typename begin::type, void_ > > { BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_sequence,(T)) }; +#endif // BOOST_MSVC + #if defined(BOOST_MPL_MSVC_ETI_BUG) template<> struct is_sequence : bool_c diff --git a/include/boost/mpl/next.hpp b/include/boost/mpl/next.hpp index 381ca44..da26328 100644 --- a/include/boost/mpl/next.hpp +++ b/include/boost/mpl/next.hpp @@ -33,7 +33,7 @@ struct next BOOST_MPL_AUX_LAMBDA_SUPPORT(1,next,(T)) }; -#if defined(BOOST_MPL_MSVC_ETI_BUG) +#if defined(BOOST_MPL_MSVC_70_ETI_BUG) template<> struct next { typedef next type; diff --git a/include/boost/mpl/prior.hpp b/include/boost/mpl/prior.hpp index 43d79b1..138075d 100644 --- a/include/boost/mpl/prior.hpp +++ b/include/boost/mpl/prior.hpp @@ -33,7 +33,7 @@ struct prior BOOST_MPL_AUX_LAMBDA_SUPPORT(1,prior,(T)) }; -#if defined(BOOST_MPL_MSVC_ETI_BUG) +#if defined(BOOST_MPL_MSVC_70_ETI_BUG) template<> struct prior { typedef prior type; diff --git a/include/boost/mpl/sequence_tag.hpp b/include/boost/mpl/sequence_tag.hpp index e3beb43..b191b55 100644 --- a/include/boost/mpl/sequence_tag.hpp +++ b/include/boost/mpl/sequence_tag.hpp @@ -22,19 +22,81 @@ #include "boost/mpl/aux_/has_begin.hpp" #include "boost/mpl/aux_/void_spec.hpp" #include "boost/mpl/aux_/config/eti.hpp" - -#include "boost/type_traits/is_class.hpp" +#include "boost/mpl/aux_/yes_no.hpp" +#include "boost/mpl/aux_/config/workaround.hpp" namespace boost { namespace mpl { // agurt, 27/nov/02: have to use a simplistic 'sequence_tag' implementation // on MSVC to avoid dreadful "internal structure overflow" error -#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + +template< + typename BOOST_MPL_AUX_VOID_SPEC_PARAM(Sequence) + > +struct sequence_tag +{ + typedef typename Sequence::tag type; +}; + +#elif BOOST_WORKAROUND(BOOST_MSVC, == 1300) + +// agurt, 07/feb/03: workaround for what seems to be MSVC 7.0-specific ETI issue + +namespace aux { + +template< bool > +struct sequence_tag_impl +{ + template< typename Sequence > struct result_ + { + typedef typename Sequence::tag type; + }; +}; + +template<> +struct sequence_tag_impl +{ + template< typename Sequence > struct result_ + { + typedef int type; + }; +}; + +struct int_convertible_ +{ + int_convertible_(int); +}; + +template< typename T > +struct is_msvc_70_ETI_arg +{ + static no_tag test(...); + static yes_tag test(int_convertible_); + static T get(); + + BOOST_STATIC_CONSTANT(bool, value = + sizeof(test(get())) == sizeof(yes_tag) + ); +}; + +} // namespace aux + +template< + typename BOOST_MPL_AUX_VOID_SPEC_PARAM(Sequence) + > +struct sequence_tag + : aux::sequence_tag_impl< !aux::is_msvc_70_ETI_arg::value > + ::template result_ +{ +}; + +#else namespace aux { template< bool has_tag_, bool has_begin_ > -struct class_sequence_tag_impl +struct sequence_tag_impl { // agurt 24/nov/02: MSVC 6.5 gets confused in 'sequence_tag_impl' // specialization below, if we name it 'result_' here @@ -42,7 +104,7 @@ struct class_sequence_tag_impl }; # define AUX_CLASS_SEQUENCE_TAG_SPEC(has_tag, has_begin, result_type) \ -template<> struct class_sequence_tag_impl \ +template<> struct sequence_tag_impl \ { \ template< typename Sequence > struct result2_ \ { \ @@ -58,28 +120,6 @@ AUX_CLASS_SEQUENCE_TAG_SPEC(false, false, non_sequence_tag) # undef AUX_CLASS_SEQUENCE_TAG_SPEC - -template< bool is_class_ > -struct sequence_tag_impl -{ - template< typename Sequence > struct result_ - { - typedef non_sequence_tag type; - }; -}; - -template<> -struct sequence_tag_impl -{ - template< typename Sequence > struct result_ - : class_sequence_tag_impl< - ::boost::mpl::aux::has_tag::value - , ::boost::mpl::aux::has_begin::value - >::template result2_ - { - }; -}; - } // namespace aux template< @@ -87,28 +127,18 @@ template< > struct sequence_tag : aux::sequence_tag_impl< - ::boost::is_class::value - >::template result_ + ::boost::mpl::aux::has_tag::value + , ::boost::mpl::aux::has_begin::value + >::template result2_ { }; -#else - -template< - typename BOOST_MPL_AUX_VOID_SPEC_PARAM(Sequence) - > -struct sequence_tag -{ - typedef typename Sequence::tag type; -}; - #endif // BOOST_MSVC - #if defined(BOOST_MPL_MSVC_ETI_BUG) template<> struct sequence_tag { - typedef non_sequence_tag type; + typedef int type; }; #endif diff --git a/test/aux_/has_xxx.cpp b/test/aux_/has_xxx.cpp index ecfe50e..c806f3b 100644 --- a/test/aux_/has_xxx.cpp +++ b/test/aux_/has_xxx.cpp @@ -15,6 +15,7 @@ // without express or implied warranty. #include "boost/mpl/aux_/has_xxx.hpp" +#include "boost/mpl/aux_/config/workaround.hpp" #include "boost/static_assert.hpp" BOOST_MPL_HAS_XXX_TRAIT_DEF(xxx_type) @@ -31,12 +32,15 @@ struct a9 { typedef void (xxx_type)(); }; int main() { +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + BOOST_STATIC_ASSERT(!has_xxx_type::value); + BOOST_STATIC_ASSERT(!has_xxx_type::value); + BOOST_STATIC_ASSERT(!has_xxx_type::value); + BOOST_STATIC_ASSERT(!has_xxx_type::value); +#endif + BOOST_STATIC_ASSERT(!has_xxx_type::value); - - #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 BOOST_STATIC_ASSERT(!has_xxx_type::value); - #endif - BOOST_STATIC_ASSERT(!has_xxx_type::value); BOOST_STATIC_ASSERT(has_xxx_type::value); BOOST_STATIC_ASSERT(has_xxx_type::value); diff --git a/test/is_sequence.cpp b/test/is_sequence.cpp new file mode 100644 index 0000000..f46d37c --- /dev/null +++ b/test/is_sequence.cpp @@ -0,0 +1,38 @@ +//----------------------------------------------------------------------------- +// boost mpl/test/is_sequence.cpp source file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2002-03 +// Aleksey Gurtovoy +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appears in all copies and +// that both the copyright notice and this permission notice appear in +// supporting documentation. No representations are made about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. + +#include "boost/mpl/list.hpp" +#include "boost/mpl/vector.hpp" +#include "boost/mpl/range_c.hpp" +#include "boost/mpl/is_sequence.hpp" +#include "boost/static_assert.hpp" + +using namespace boost::mpl; + +struct UDT {}; + +int main() +{ + BOOST_STATIC_ASSERT(!is_sequence< int >::value); + BOOST_STATIC_ASSERT(!is_sequence< int& >::value); + BOOST_STATIC_ASSERT(!is_sequence< UDT >::value); + BOOST_STATIC_ASSERT(!is_sequence< UDT* >::value); + BOOST_STATIC_ASSERT((is_sequence< range_c >::value)); + BOOST_STATIC_ASSERT(is_sequence< list<> >::value); + BOOST_STATIC_ASSERT(is_sequence< vector<> >::value); + + return 0; +}