diff --git a/include/boost/variant/variant.hpp b/include/boost/variant/variant.hpp index d4073ef..6bc3fbc 100644 --- a/include/boost/variant/variant.hpp +++ b/include/boost/variant/variant.hpp @@ -30,6 +30,7 @@ #include "boost/config.hpp" #include "boost/detail/workaround.hpp" #include "boost/mpl/aux_/config/eti.hpp" +#include "boost/mpl/aux_/deref_wknd.hpp" #include "boost/mpl/aux_/value_wknd.hpp" #include "boost/aligned_storage.hpp" @@ -54,7 +55,6 @@ #include "boost/mpl/contains.hpp" #include "boost/mpl/count_if.hpp" #include "boost/mpl/distance.hpp" -#include "boost/mpl/deref.hpp" #include "boost/mpl/empty.hpp" #include "boost/mpl/equal_to.hpp" #include "boost/mpl/identity.hpp" @@ -74,6 +74,21 @@ #include "boost/mpl/void.hpp" +////////////////////////////////////////////////////////////////////////// +// BOOST_VARIANT_MINIMIZE_SIZE +// +// When #defined, implementation employs all known means to minimize the +// size of variant objects. However, often unsuccessful due to alignment +// issues, and potentially harmful to runtime speed, so not enabled by +// default. (TODO: Investigate further.) +// +#if defined(BOOST_VARIANT_MINIMIZE_SIZE) +# include // for SCHAR_MAX +# include "boost/mpl/less.hpp" +# include "boost/mpl/long.hpp" +# include "boost/mpl/O1_size.hpp" +#endif + ////////////////////////////////////////////////////////////////////////// // BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT // @@ -103,7 +118,7 @@ private: // helpers, for metafunction result (below) public: // metafunction result - typedef typename mpl::deref::type + typedef typename BOOST_MPL_AUX_DEREF_WNKD(max_it) type; }; @@ -520,30 +535,7 @@ private: #endif // borland workaround -private: // static precondition assertions - -#if defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT) - - // Sequences are not supported for compilers that do not support - // using declarations in templates (see below). - -#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1200) - - BOOST_STATIC_ASSERT(( - BOOST_MPL_AUX_VALUE_WKND( - mpl::not_< mpl::is_sequence > - )::value - )); - -#else - - BOOST_STATIC_CONSTANT(bool, not_is_sequence_T0 = mpl::not_< mpl::is_sequence >::value); - - BOOST_STATIC_ASSERT(not_is_sequence_T0); - -#endif - -#endif // BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT +#if !defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT) public: // typedefs @@ -555,6 +547,34 @@ public: // typedefs > >::type types; +#else // defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT) + +public: // typedefs + + typedef typename detail::variant::make_variant_list< + BOOST_VARIANT_ENUM_PARAMS(T) + >::type types; + +private: // static precondition assertions + + // Sequences are not supported for compilers that do not support + // using declarations in templates (see below). + +# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1200) + + BOOST_STATIC_ASSERT(( + ::boost::mpl::not_< mpl::is_sequence >::value + )); + +# else // MSVC6 + + BOOST_STATIC_CONSTANT(bool, msvc_not_is_sequence_T0 = mpl::not_< mpl::is_sequence >::value); + BOOST_STATIC_ASSERT(msvc_not_is_sequence_T0); + +# endif // MSVC6 workaround + +#endif // BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT + private: // static precondition assertions, cont. // [Assert unique types: ommitted due to compile-time complexity.] @@ -607,7 +627,28 @@ private: // representation (int which_) // if which_ >= 0: // * then which() -> which_ // * else which() -> -(which_ + 1) - int which_; + +#if !defined(BOOST_VARIANT_MINIMIZE_SIZE) + + typedef int which_t; + +#else // defined(BOOST_VARIANT_MINIMIZE_SIZE) + + // [if O1_size available, then attempt which_t size optimization...] + // [select signed char if fewer than SCHAR_MAX types, else signed int:] + typedef typename mpl::apply_if< + mpl::equal_to< mpl::O1_size, mpl::long_<-1> > + , mpl::identity< int > + , mpl::if_< + mpl::less< mpl::O1_size, mpl::int_ > + , signed char + , int + > + >::type which_t; + +#endif // BOOST_VARIANT_MINIMIZE_SIZE switch + + which_t which_; static bool using_storage1_impl(mpl::true_) { @@ -631,12 +672,12 @@ private: // representation (int which_) void activate_storage1(int which) { - which_ = which; + which_ = static_cast( which ); } void activate_storage2(int which) { - which_ = -(which + 1); + which_ = static_cast( -(which + 1) ); } private: // representation (aligned double-storage) @@ -735,7 +776,7 @@ private: // helpers, for structors (below) { private: // helpers, for static functions (below) - typedef typename Iterator::type + typedef typename BOOST_MPL_AUX_DEREF_WNKD(Iterator) T; public: // static functions @@ -1297,7 +1338,7 @@ private: // helpers, for visitation support (below) // Otherwise, tail recurse, checking next iteration: typename mpl::next::type* next_which = 0; - typename NextIt::type* next_type = 0; + typename BOOST_MPL_AUX_DEREF_WNKD(NextIt)* next_type = 0; typedef typename mpl::next::type next_next_it_t; next_next_it_t* next_next_it = 0; typedef typename is_same::type next_next_is_last; @@ -1352,7 +1393,7 @@ public: { mpl::int_<0>* first_which = 0; typedef typename mpl::begin::type first_it; - typename first_it::type* first_type = 0; + typename BOOST_MPL_AUX_DEREF_WNKD(first_it)* first_type = 0; typename mpl::next::type* next_it = 0; typename mpl::end::type* last_it = 0; @@ -1370,7 +1411,7 @@ public: { mpl::int_<0>* first_which = 0; typedef typename mpl::begin::type first_it; - typename first_it::type* first_type = 0; + typename BOOST_MPL_AUX_DEREF_WNKD(first_it)* first_type = 0; typename mpl::next::type* next_it = 0; typename mpl::end::type* last_it = 0;