sl@0: //----------------------------------------------------------------------------- sl@0: // boost variant/detail/initializer.hpp header file sl@0: // See http://www.boost.org for updates, documentation, and revision history. sl@0: //----------------------------------------------------------------------------- sl@0: // sl@0: // Copyright (c) 2002-2003 sl@0: // Eric Friedman, Itay Maman sl@0: // sl@0: // Distributed under the Boost Software License, Version 1.0. (See sl@0: // accompanying file LICENSE_1_0.txt or copy at sl@0: // http://www.boost.org/LICENSE_1_0.txt) sl@0: sl@0: #ifndef BOOST_VARIANT_DETAIL_INITIALIZER_HPP sl@0: #define BOOST_VARIANT_DETAIL_INITIALIZER_HPP sl@0: sl@0: #include // for placement new sl@0: sl@0: #include "boost/config.hpp" sl@0: sl@0: #include "boost/call_traits.hpp" sl@0: #include "boost/detail/reference_content.hpp" sl@0: #include "boost/variant/recursive_wrapper_fwd.hpp" sl@0: sl@0: #if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) sl@0: # include "boost/mpl/aux_/value_wknd.hpp" sl@0: # include "boost/mpl/int.hpp" sl@0: # include "boost/mpl/iter_fold.hpp" sl@0: # include "boost/mpl/next.hpp" sl@0: # include "boost/mpl/deref.hpp" sl@0: # include "boost/mpl/pair.hpp" sl@0: # include "boost/mpl/protect.hpp" sl@0: #else sl@0: # include "boost/variant/variant_fwd.hpp" sl@0: # include "boost/preprocessor/cat.hpp" sl@0: # include "boost/preprocessor/enum.hpp" sl@0: # include "boost/preprocessor/repeat.hpp" sl@0: #endif sl@0: sl@0: namespace boost { sl@0: namespace detail { namespace variant { sl@0: sl@0: /////////////////////////////////////////////////////////////////////////////// sl@0: // (detail) support to simulate standard overload resolution rules sl@0: // sl@0: // The below initializers allows variant to follow standard overload sl@0: // resolution rules over the specified set of bounded types. sl@0: // sl@0: // On compilers where using declarations in class templates can correctly sl@0: // avoid name hiding, use an optimal solution based on the variant's typelist. sl@0: // sl@0: // Otherwise, use a preprocessor workaround based on knowledge of the fixed sl@0: // size of the variant's psuedo-variadic template parameter list. sl@0: // sl@0: sl@0: #if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) sl@0: sl@0: // (detail) quoted metafunction make_initializer_node sl@0: // sl@0: // Exposes a pair whose first type is a node in the initializer hierarchy. sl@0: // sl@0: struct make_initializer_node sl@0: { sl@0: template sl@0: struct apply sl@0: { sl@0: private: // helpers, for metafunction result (below) sl@0: sl@0: typedef typename BaseIndexPair::first sl@0: base; sl@0: typedef typename BaseIndexPair::second sl@0: index; sl@0: sl@0: class initializer_node sl@0: : public base sl@0: { sl@0: private: // helpers, for static functions (below) sl@0: sl@0: typedef typename mpl::deref::type sl@0: recursive_enabled_T; sl@0: typedef typename unwrap_recursive::type sl@0: public_T; sl@0: typedef typename call_traits::param_type sl@0: param_T; sl@0: sl@0: public: // static functions sl@0: sl@0: using base::initialize; sl@0: sl@0: static int initialize(void* dest, param_T operand) sl@0: { sl@0: typedef typename boost::detail::make_reference_content< sl@0: recursive_enabled_T sl@0: >::type internal_T; sl@0: sl@0: new(dest) internal_T(operand); sl@0: return BOOST_MPL_AUX_VALUE_WKND(index)::value; // which sl@0: } sl@0: sl@0: }; sl@0: sl@0: friend class initializer_node; sl@0: sl@0: public: // metafunction result sl@0: sl@0: typedef mpl::pair< sl@0: initializer_node sl@0: , typename mpl::next< index >::type sl@0: > type; sl@0: sl@0: }; sl@0: }; sl@0: sl@0: // (detail) class initializer_root sl@0: // sl@0: // Every level of the initializer hierarchy must expose the name sl@0: // "initialize," so initializer_root provides a dummy function: sl@0: // sl@0: class initializer_root sl@0: { sl@0: public: // static functions sl@0: sl@0: static void initialize(); sl@0: sl@0: }; sl@0: sl@0: #else // defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) sl@0: sl@0: # if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) sl@0: sl@0: #define BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_PARAMS \ sl@0: BOOST_VARIANT_ENUM_PARAMS(typename recursive_enabled_T) \ sl@0: /**/ sl@0: sl@0: #define BOOST_VARIANT_AUX_PP_INITIALIZER_DEFINE_PARAM_T(N) \ sl@0: typedef typename unwrap_recursive< \ sl@0: BOOST_PP_CAT(recursive_enabled_T,N) \ sl@0: >::type BOOST_PP_CAT(public_T,N); \ sl@0: typedef typename call_traits< \ sl@0: BOOST_PP_CAT(public_T,N) \ sl@0: >::param_type BOOST_PP_CAT(param_T,N); \ sl@0: /**/ sl@0: sl@0: # else // MSVC7 and below sl@0: sl@0: #define BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_PARAMS \ sl@0: BOOST_VARIANT_ENUM_PARAMS(typename recursive_enabled_T) \ sl@0: , BOOST_VARIANT_ENUM_PARAMS(typename param_T) \ sl@0: /**/ sl@0: sl@0: #define BOOST_VARIANT_AUX_PP_INITIALIZER_DEFINE_PARAM_T(N) \ sl@0: /**/ sl@0: sl@0: # endif // MSVC7 and below workaround sl@0: sl@0: template < BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_PARAMS > sl@0: struct preprocessor_list_initializer sl@0: { sl@0: public: // static functions sl@0: sl@0: #define BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION(z,N,_) \ sl@0: BOOST_VARIANT_AUX_PP_INITIALIZER_DEFINE_PARAM_T(N) \ sl@0: static int initialize( \ sl@0: void* dest \ sl@0: , BOOST_PP_CAT(param_T,N) operand \ sl@0: ) \ sl@0: { \ sl@0: typedef typename boost::detail::make_reference_content< \ sl@0: BOOST_PP_CAT(recursive_enabled_T,N) \ sl@0: >::type internal_T; \ sl@0: \ sl@0: new(dest) internal_T(operand); \ sl@0: return (N); /*which*/ \ sl@0: } \ sl@0: /**/ sl@0: sl@0: BOOST_PP_REPEAT( sl@0: BOOST_VARIANT_LIMIT_TYPES sl@0: , BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION sl@0: , _ sl@0: ) sl@0: sl@0: #undef BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION sl@0: sl@0: }; sl@0: sl@0: # if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG) sl@0: sl@0: #if !defined(BOOST_VARIANT_AUX_ECHO) sl@0: # define BOOST_VARIANT_AUX_ECHO(z,N,token) token sl@0: #endif sl@0: sl@0: template <> sl@0: struct preprocessor_list_initializer< sl@0: BOOST_PP_ENUM(BOOST_VARIANT_LIMIT_TYPES, BOOST_VARIANT_AUX_ECHO, int) sl@0: , BOOST_PP_ENUM(BOOST_VARIANT_LIMIT_TYPES, BOOST_VARIANT_AUX_ECHO, const int) sl@0: > sl@0: { sl@0: }; sl@0: sl@0: # endif // BOOST_MPL_CFG_MSVC_60_ETI_BUG workaround sl@0: sl@0: #endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround sl@0: sl@0: }} // namespace detail::variant sl@0: } // namespace boost sl@0: sl@0: /////////////////////////////////////////////////////////////////////////////// sl@0: // macro BOOST_VARIANT_AUX_INITIALIZER_T sl@0: // sl@0: // Given both the variant's typelist and a basename for forming the list of sl@0: // bounded types (i.e., T becomes T1, T2, etc.), exposes the initializer sl@0: // most appropriate to the current compiler. sl@0: // sl@0: sl@0: #if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) sl@0: sl@0: #define BOOST_VARIANT_AUX_INITIALIZER_T( mpl_seq, typename_base ) \ sl@0: ::boost::mpl::iter_fold< \ sl@0: mpl_seq \ sl@0: , ::boost::mpl::pair< \ sl@0: ::boost::detail::variant::initializer_root \ sl@0: , ::boost::mpl::int_<0> \ sl@0: > \ sl@0: , ::boost::mpl::protect< \ sl@0: ::boost::detail::variant::make_initializer_node \ sl@0: > \ sl@0: >::type::first \ sl@0: /**/ sl@0: sl@0: #else // defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) sl@0: sl@0: # if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) sl@0: sl@0: #define BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_ARGS(typename_base) \ sl@0: BOOST_VARIANT_ENUM_PARAMS(typename_base) \ sl@0: /**/ sl@0: sl@0: # else // MSVC7 and below sl@0: sl@0: #define BOOST_VARIANT_AUX_PP_INITIALIZER_ENUM_PARAM_TYPE(z,N,T) \ sl@0: ::boost::call_traits< \ sl@0: ::boost::unwrap_recursive::type \ sl@0: >::param_type \ sl@0: /**/ sl@0: sl@0: #define BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_ARGS(typename_base) \ sl@0: BOOST_VARIANT_ENUM_PARAMS(typename_base) \ sl@0: , BOOST_PP_ENUM( \ sl@0: BOOST_VARIANT_LIMIT_TYPES \ sl@0: , BOOST_VARIANT_AUX_PP_INITIALIZER_ENUM_PARAM_TYPE \ sl@0: , typename_base \ sl@0: ) \ sl@0: /**/ sl@0: sl@0: # endif // MSVC7 workaround sl@0: sl@0: #define BOOST_VARIANT_AUX_INITIALIZER_T( mpl_seq, typename_base ) \ sl@0: ::boost::detail::variant::preprocessor_list_initializer< \ sl@0: BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_ARGS(typename_base) \ sl@0: > \ sl@0: /**/ sl@0: sl@0: #endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround sl@0: sl@0: #endif // BOOST_VARIANT_DETAIL_INITIALIZER_HPP