//--------------------------------------------------------------------------- #ifndef runtime_type_selected_invokerH #define runtime_type_selected_invokerH //--------------------------------------------------------------------------- #include "boost/preprocessor/arithmetic/inc.hpp" #include "boost/preprocessor/repetition/repeat.hpp" #include "boost/preprocessor/repetition/repeat_from_to.hpp" //--------------------------------------------------------------------------- #include "boost/assert.hpp" //#include "boost/config.hpp" #include "boost/static_assert.hpp" #include "boost/mpl/advance.hpp" #include "boost/mpl/and.hpp" #include "boost/mpl/at.hpp" #include "boost/mpl/begin_end.hpp" #include "boost/mpl/greater.hpp" #include "boost/mpl/integral_c.hpp" #include "boost/mpl/iterator_range.hpp" #include "boost/mpl/less_equal.hpp" #include "boost/mpl/minus.hpp" #include "boost/mpl/size.hpp" //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- namespace boost { namespace detail { namespace variant { /////////////////////////////////////////////////////////////////////////////// // (detail) function template cast_storage // // Casts the given storage to the specified type, but with qualification. // template inline T& cast_storage( void* storage BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(T) ) { return *static_cast(storage); } template inline const T& cast_storage( const void* storage BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(T) ) { return *static_cast(storage); } template class rtts_index_validator { public: BOOST_STATIC_CONSTANT(long, min_index = 0); BOOST_STATIC_CONSTANT(long, max_index = MaxIndex::value); inline static bool accepts_index(long candidate) { return (min_index <= candidate) && (candidate < max_index); } }; //This is an encapsulation of the requirements for the actual arguments to an instantiation //of n_ary_rtts_invoker. template class n_ary_rtts_invoker_template_arg_validator { //N must be in the range [1, size]: BOOST_STATIC_ASSERT (( mpl::and_ < mpl::less, N> , mpl::less_equal::type> > ::type::value )); }; //This is the class that is specialized on SelectionCount. It implements a selection //among the first 'N' types in Sequence. template class n_ary_rtts_invoker; //<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>> //Here is a single case statement: #define BOOST_DETAIL_VARIANT_RTTS_CASE_STATEMENT_RETURN(N) \ { \ typedef \ BOOST_DEDUCED_TYPENAME \ mpl::at >::type \ this_case_t; \ return op(cast_storage(storage)); \ } \ /**/ //Here is a single case statement: #define BOOST_DETAIL_VARIANT_RTTS_CASE_STATEMENT(N) \ case N: \ BOOST_DETAIL_VARIANT_RTTS_CASE_STATEMENT_RETURN(N) \ /**/ #define BOOST_DETAIL_VARIANT_RTTS_PP_READY_CASE_STATEMENT(z, N, _) \ BOOST_DETAIL_VARIANT_RTTS_CASE_STATEMENT(N) \ /**/ //Here is a series of case statements: #define BOOST_DETAIL_VARIANT_RTTS_CASE_STATEMENT_SERIES(z, N, _) \ BOOST_PP_REPEAT_ ## z(N, BOOST_DETAIL_VARIANT_RTTS_PP_READY_CASE_STATEMENT, _)\ /**/ //Here is the invoker class, partially specialized on mpl::integral_c : #define BOOST_DETAIL_VARIANT_RTTS_INVOKER(z, N, _) \ template \ class n_ary_rtts_invoker > \ : public rtts_index_validator > \ , public n_ary_rtts_invoker_template_arg_validator > \ { \ public: \ template \ static \ BOOST_DEDUCED_TYPENAME Operator::result_type \ invoke(Operator & op, StoragePtr storage, long index) \ { \ BOOST_ASSERT(accepts_index(index)); \ switch (index) \ { \ BOOST_DETAIL_VARIANT_RTTS_CASE_STATEMENT_SERIES(z, N, _) \ } \ } \ }; \ /**/ //Let's generate some classes: #if !defined(BOOST_VARIANT_RTTS_MAX_SELECTION_SPECIALIZATION_COUNT) #define BOOST_VARIANT_RTTS_MAX_SELECTION_SPECIALIZATION_COUNT 3 #endif //***********************The following: BOOST_PP_REPEAT_FROM_TO ( 1 , BOOST_PP_INC(BOOST_VARIANT_RTTS_MAX_SELECTION_SPECIALIZATION_COUNT) , BOOST_DETAIL_VARIANT_RTTS_INVOKER , _ ) //***********************expands to (assuming BOOST_VARIANT_RTTS_MAX_SELECTION_SPECIALIZATION_COUNT==3): /* template class n_ary_rtts_invoker > : public rtts_index_validator > , public n_ary_rtts_invoker_template_arg_validator > { public: template static BOOST_DEDUCED_TYPENAME Operator::result_type invoke(Operator & op, StoragePtr storage, long index) { BOOST_ASSERT(accepts_index(index)); switch (index) { case 0: { typedef BOOST_DEDUCED_TYPENAME mpl::at >::type this_case_t; return op(cast_storage(storage)); } } } }; template class n_ary_rtts_invoker > : public rtts_index_validator > , public n_ary_rtts_invoker_template_arg_validator > { public: template static BOOST_DEDUCED_TYPENAME Operator::result_type invoke(Operator & op, StoragePtr storage, long index) { BOOST_ASSERT(accepts_index(index)); switch (index) { case 0: { typedef BOOST_DEDUCED_TYPENAME mpl::at >::type this_case_t; return op(cast_storage(storage)); } case 1: { typedef BOOST_DEDUCED_TYPENAME mpl::at >::type this_case_t; return op(cast_storage(storage)); } } } }; template class n_ary_rtts_invoker > : public rtts_index_validator > , public n_ary_rtts_invoker_template_arg_validator > { public: template static BOOST_DEDUCED_TYPENAME Operator::result_type invoke(Operator & op, StoragePtr storage, long index) { BOOST_ASSERT(accepts_index(index)); switch (index) { case 0: { typedef BOOST_DEDUCED_TYPENAME mpl::at >::type this_case_t; return op(cast_storage(storage)); } case 1: { typedef BOOST_DEDUCED_TYPENAME mpl::at >::type this_case_t; return op(cast_storage(storage)); } case 2: { typedef BOOST_DEDUCED_TYPENAME mpl::at >::type this_case_t; return op(cast_storage(storage)); } } } }; */ //***********************end expansion /* //One is a special case. We assert that index == 0, then invoke on the first type. template class n_ary_rtts_invoker > , public rtts_index_validator > , public n_ary_rtts_invoker_template_arg_validator > { typedef mpl::integral_c SelectionCount; public: Operator::result_type invoke(long index) { BOOST_ASSERT((index == 0)); typedef mpl::at >::type * TypePtr_t; return op(storage, TypePtr_t()); } }; */ #undef BOOST_DETAIL_VARIANT_RTTS_CASE_STATEMENT_RETURN #undef BOOST_DETAIL_VARIANT_RTTS_CASE_STATEMENT #undef BOOST_DETAIL_VARIANT_RTTS_PP_READY_CASE_STATEMENT #undef BOOST_DETAIL_VARIANT_RTTS_CASE_STATEMENT_SERIES #undef BOOST_DETAIL_VARIANT_RTTS_INVOKER //<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>> ///general definition depending on BOOST_VARIANT_RTTS_MAX_SELECTION_SPECIALIZATION_COUNT typedef mpl::integral_c max_selection_specialization_count_t; //When this version of the template is invoked, it means that no specialization on //a fully-defined SelectionCount matched, so we can safely assume that: //mpl::greater::value == true. //Therefore, its invokation strategy is to instantiate two selections: one among //the first 'max_selection_specialization_count_t::value' types and another among //the remaining types. template class n_ary_rtts_invoker > : public rtts_index_validator > , public n_ary_rtts_invoker_template_arg_validator > { typedef mpl::integral_c SelectionCount; public: template static BOOST_DEDUCED_TYPENAME Operator::result_type invoke(Operator & op, StoragePtr storage, long index) { BOOST_ASSERT(accepts_index(index)); if (index < max_selection_specialization_count_t::value) { return n_ary_rtts_invoker < Sequence , max_selection_specialization_count_t > ::invoke(op, storage, index); } else { typedef BOOST_DEDUCED_TYPENAME mpl::iterator_range < BOOST_DEDUCED_TYPENAME mpl::advance < BOOST_DEDUCED_TYPENAME mpl::begin::type , max_selection_specialization_count_t > ::type , BOOST_DEDUCED_TYPENAME mpl::end::type > ::type remaining_types_t; typedef BOOST_DEDUCED_TYPENAME mpl::minus::type remaining_selection_count_t; return n_ary_rtts_invoker < remaining_types_t , remaining_selection_count_t > ::invoke(op, storage, index - max_selection_specialization_count_t::value); } } }; //It instantiates an n_ary_rtts_invoker with mpl::integral_c >, //because that's the type on which n_ary_rtts_invoker is specialized. //Implements a selection over all the types in the sequence. template class runtime_type_selected_invoker : public n_ary_rtts_invoker < Sequence , mpl::integral_c::type::value)> > { }; }//end namespace variant }//end namespace detail }//end namespace boost #endif