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