//----------------------------------------------------------------------------- // boost variant/detail/visitation_impl.hpp header file // See http://www.boost.org for updates, documentation, and revision history. //----------------------------------------------------------------------------- // // Copyright (c) 2003 // Eric Friedman // // 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 BOOST_VARIANT_DETAIL_VISITATION_IMPL_HPP #define BOOST_VARIANT_DETAIL_VISITATION_IMPL_HPP #include "boost/config.hpp" #include "boost/variant/detail/backup_holder.hpp" #include "boost/variant/detail/cast_storage.hpp" #include "boost/variant/detail/forced_return.hpp" #include "boost/variant/detail/generic_result_type.hpp" #include "boost/assert.hpp" #include "boost/mpl/eval_if.hpp" #include "boost/mpl/bool.hpp" #include "boost/mpl/identity.hpp" #include "boost/mpl/int.hpp" #include "boost/mpl/next.hpp" #include "boost/mpl/deref.hpp" #include "boost/mpl/or.hpp" #include "boost/preprocessor/cat.hpp" #include "boost/preprocessor/inc.hpp" #include "boost/preprocessor/repeat.hpp" #include "boost/type_traits/is_same.hpp" #include "boost/type_traits/has_nothrow_copy.hpp" #include "boost/variant/detail/has_nothrow_move.hpp" #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) # pragma warning (push) # pragma warning (disable : 4702) //unreachable code #endif /////////////////////////////////////////////////////////////////////////////// // BOOST_VARIANT_VISITATION_UNROLLING_LIMIT // // Unrolls variant's visitation mechanism to reduce template instantiation // and potentially increase runtime performance. (TODO: Investigate further.) // #if !defined(BOOST_VARIANT_VISITATION_UNROLLING_LIMIT) # define BOOST_VARIANT_VISITATION_UNROLLING_LIMIT \ BOOST_VARIANT_LIMIT_TYPES #endif namespace boost { namespace detail { namespace variant { /////////////////////////////////////////////////////////////////////////////// // (detail) class apply_visitor_unrolled // // Tag type indicates when visitation_impl is unrolled. // struct apply_visitor_unrolled {}; /////////////////////////////////////////////////////////////////////////////// // (detail) class template visitation_impl_step // // "Never ending" iterator range facilitates visitation_impl unrolling. // #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) template struct visitation_impl_step { typedef typename mpl::deref::type type; typedef typename mpl::next::type next_iter; typedef visitation_impl_step< next_iter, LastIter > next; }; template struct visitation_impl_step< LastIter,LastIter > { typedef apply_visitor_unrolled type; typedef visitation_impl_step next; }; #else // defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) template struct visitation_impl_step { typedef typename mpl::eval_if< is_same , mpl::identity , Iter >::type type; typedef typename mpl::eval_if< is_same //is_same , mpl::identity , mpl::next >::type next_iter; typedef visitation_impl_step< next_iter, LastIter > next; }; #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION workaround /////////////////////////////////////////////////////////////////////////////// // (detail) function template visitation_impl_invoke // // Invokes the given visitor on the specified type in the given storage. // template inline BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type) visitation_impl_invoke_impl( int, Visitor& visitor, VoidPtrCV storage, T* , mpl::true_// never_uses_backup ) { return visitor.internal_visit( cast_storage(storage), 1L ); } template inline BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type) visitation_impl_invoke_impl( int internal_which, Visitor& visitor, VoidPtrCV storage, T* , mpl::false_// never_uses_backup ) { if (internal_which >= 0) { return visitor.internal_visit( cast_storage(storage), 1L ); } else { return visitor.internal_visit( cast_storage< backup_holder >(storage), 1L ); } } template inline BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type) visitation_impl_invoke( int internal_which, Visitor& visitor, VoidPtrCV storage, T* t , NoBackupFlag , int ) { typedef typename mpl::or_< NoBackupFlag , has_nothrow_move_constructor , has_nothrow_copy >::type never_uses_backup; return visitation_impl_invoke_impl( internal_which, visitor, storage, t , never_uses_backup() ); } template inline BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type) visitation_impl_invoke(int, Visitor&, VoidPtrCV, apply_visitor_unrolled*, NBF, long) { // should never be here at runtime: BOOST_ASSERT(false); typedef typename Visitor::result_type result_type; return ::boost::detail::variant::forced_return< result_type >(); } /////////////////////////////////////////////////////////////////////////////// // (detail) function template visitation_impl // // Invokes the given visitor on the type in the given variant storage. // template < typename W, typename S , typename Visitor, typename VPCV , typename NBF > inline BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type) visitation_impl( int, int, Visitor&, VPCV , mpl::true_ // is_apply_visitor_unrolled , NBF, W* = 0, S* = 0 ) { // should never be here at runtime: BOOST_ASSERT(false); typedef typename Visitor::result_type result_type; return ::boost::detail::variant::forced_return< result_type >(); } template < typename Which, typename step0 , typename Visitor, typename VoidPtrCV , typename NoBackupFlag > inline BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type) visitation_impl( const int internal_which, const int logical_which , Visitor& visitor, VoidPtrCV storage , mpl::false_ // is_apply_visitor_unrolled , NoBackupFlag no_backup_flag , Which* = 0, step0* = 0 ) { // Typedef apply_visitor_unrolled steps and associated types... # define BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_TYPEDEF(z, N, _) \ typedef typename BOOST_PP_CAT(step,N)::type BOOST_PP_CAT(T,N); \ typedef typename BOOST_PP_CAT(step,N)::next \ BOOST_PP_CAT(step, BOOST_PP_INC(N)); \ /**/ BOOST_PP_REPEAT( BOOST_VARIANT_VISITATION_UNROLLING_LIMIT , BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_TYPEDEF , _ ) # undef BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_TYPEDEF // ...switch on the target which-index value... switch (logical_which) { // ...applying the appropriate case: # define BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_CASE(z, N, _) \ case (Which::value + (N)): \ return visitation_impl_invoke( \ internal_which, visitor, storage \ , static_cast(0) \ , no_backup_flag, 1L \ ); \ /**/ BOOST_PP_REPEAT( BOOST_VARIANT_VISITATION_UNROLLING_LIMIT , BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_CASE , _ ) # undef BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_CASE } // If not handled in this iteration, continue unrolling: typedef mpl::int_< Which::value + (BOOST_VARIANT_VISITATION_UNROLLING_LIMIT) > next_which; typedef BOOST_PP_CAT(step, BOOST_VARIANT_VISITATION_UNROLLING_LIMIT) next_step; typedef typename next_step::type next_type; typedef typename is_same< next_type,apply_visitor_unrolled >::type is_apply_visitor_unrolled; return visitation_impl( internal_which, logical_which , visitor, storage , is_apply_visitor_unrolled() , no_backup_flag , static_cast(0), static_cast(0) ); } }} // namespace detail::variant } // namespace boost #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) # pragma warning(pop) #endif #endif // BOOST_VARIANT_DETAIL_VISITATION_IMPL_HPP