// switch.hpp // // Copyright (c) 2006-2007 // Steven Watanabe // // Distriuted 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_SWITCH_HPP_INCLUDED #define BOOST_SWITCH_HPP_INCLUDED #include #include #include #include #include #include #include #include #include #include #include #ifndef BOOST_SWITCH_LIMIT #define BOOST_SWITCH_LIMIT 50 #endif #if BOOST_SWITCH_LIMIT > BOOST_PP_LIMIT_REPEAT #error BOOST_SWITCH_LIMIT exceeds Boost.Preprocessor limit #endif #if BOOST_SWITCH_LIMIT > BOOST_PP_LIMIT_ITERATION #error BOOST_SWITCH_LIMIT exceeds Boost.Preprocessor limit #endif namespace boost { class bad_switch : public std::runtime_error { public: template explicit bad_switch(Int v) : std::runtime_error( "boost::switch_ default case called -- none provided. value is: " + boost::lexical_cast(v)) {} }; namespace switch_detail { // Avoid the need to create all the specializations of switch_impl // twice. Just pass this to switch_impl::apply(...) when no // default is supplied. template inline R forced_return(typename boost::remove_reference::type* r = 0) { return(*r); } // Thanks to Stjepan Rajko for catching this. template<> inline void forced_return(void*) {} template<> inline const void forced_return(const void*) {} template<> inline volatile void forced_return(volatile void*) {} template<> inline const volatile void forced_return(const volatile void*) {} template struct throw_exception { template R operator()(Int i) const { boost::throw_exception(bad_switch(i)); return(switch_detail::forced_return()); } }; // N is the number of cases not including the default template struct switch_impl; // specialize for 0 separately to avoid warnings template<> struct switch_impl<0> { template static typename F::result_type apply(Int i, F, Default d BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(V)) { return(d(i)); } }; #define BOOST_SWITCH_CASE(z, n, data) \ case boost::mpl::at_c::type::value: { \ typename boost::mpl::at_c::type arg; \ return(f(arg)); \ } #define BOOST_SWITCH_IMPL(z, n, data) \ template<> \ struct switch_impl { \ template \ static typename F::result_type \ apply(I i, F f, D d BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(V)) { \ switch(i) { \ BOOST_PP_REPEAT_##z(n, BOOST_SWITCH_CASE, V) \ default: return(d(i)); \ } \ } \ }; #define BOOST_PP_LOCAL_LIMITS (1, BOOST_SWITCH_LIMIT) #define BOOST_PP_LOCAL_MACRO(n) BOOST_SWITCH_IMPL(1, n, ~) #include BOOST_PP_LOCAL_ITERATE() #undef BOOST_SWITCH_IMPL #undef BOOST_SWITCH_CASE } template inline typename F::result_type switch_(N n, F f BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(V)) { typedef switch_detail::switch_impl::value> impl; switch_detail::throw_exception default_; return(impl::template apply(n, f, default_)); } template inline typename F::result_type switch_(N n, F f, D d BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(V)) { typedef switch_detail::switch_impl::value> impl; return(impl::template apply(n, f, d)); } } #endif