Line data Source code
1 : //----------------------------------------------------------------------------- 2 : // boost variant/detail/initializer.hpp header file 3 : // See http://www.boost.org for updates, documentation, and revision history. 4 : //----------------------------------------------------------------------------- 5 : // 6 : // Copyright (c) 2002-2003 7 : // Eric Friedman, Itay Maman 8 : // 9 : // Distributed under the Boost Software License, Version 1.0. (See 10 : // accompanying file LICENSE_1_0.txt or copy at 11 : // http://www.boost.org/LICENSE_1_0.txt) 12 : 13 : #ifndef BOOST_VARIANT_DETAIL_INITIALIZER_HPP 14 : #define BOOST_VARIANT_DETAIL_INITIALIZER_HPP 15 : 16 : #include <new> // for placement new 17 : 18 : #include <boost/config.hpp> 19 : 20 : #include <boost/call_traits.hpp> 21 : #include <boost/detail/reference_content.hpp> 22 : #include <boost/variant/recursive_wrapper_fwd.hpp> 23 : #include <boost/variant/detail/move.hpp> 24 : 25 : # include <boost/mpl/aux_/value_wknd.hpp> 26 : # include <boost/mpl/int.hpp> 27 : # include <boost/mpl/iter_fold.hpp> 28 : # include <boost/mpl/next.hpp> 29 : # include <boost/mpl/deref.hpp> 30 : # include <boost/mpl/pair.hpp> 31 : # include <boost/mpl/protect.hpp> 32 : 33 : 34 : namespace boost { 35 : namespace detail { namespace variant { 36 : 37 : /////////////////////////////////////////////////////////////////////////////// 38 : // (detail) support to simulate standard overload resolution rules 39 : // 40 : // The below initializers allows variant to follow standard overload 41 : // resolution rules over the specified set of bounded types. 42 : // 43 : // On compilers where using declarations in class templates can correctly 44 : // avoid name hiding, use an optimal solution based on the variant's typelist. 45 : // 46 : // Otherwise, use a preprocessor workaround based on knowledge of the fixed 47 : // size of the variant's psuedo-variadic template parameter list. 48 : // 49 : 50 : // (detail) quoted metafunction make_initializer_node 51 : // 52 : // Exposes a pair whose first type is a node in the initializer hierarchy. 53 : // 54 : struct make_initializer_node 55 : { 56 : template <typename BaseIndexPair, typename Iterator> 57 : struct apply 58 : { 59 : private: // helpers, for metafunction result (below) 60 : 61 : typedef typename BaseIndexPair::first 62 : base; 63 : typedef typename BaseIndexPair::second 64 : index; 65 : 66 : class initializer_node 67 : : public base 68 : { 69 : private: // helpers, for static functions (below) 70 : 71 : typedef typename mpl::deref<Iterator>::type 72 : recursive_enabled_T; 73 : typedef typename unwrap_recursive<recursive_enabled_T>::type 74 : public_T; 75 : 76 : typedef boost::is_reference<public_T> 77 : is_reference_content_t; 78 : 79 : typedef typename boost::mpl::if_<is_reference_content_t, public_T, const public_T& >::type 80 : param_T; 81 : 82 : template <class T> struct disable_overload{}; 83 : 84 : typedef typename boost::mpl::if_<is_reference_content_t, disable_overload<public_T>, public_T&& >::type 85 : param2_T; 86 : 87 : public: // static functions 88 : 89 : using base::initialize; 90 : 91 : static int initialize(void* dest, param_T operand) 92 : { 93 : typedef typename boost::detail::make_reference_content< 94 : recursive_enabled_T 95 : >::type internal_T; 96 : 97 : new(dest) internal_T(operand); 98 : return BOOST_MPL_AUX_VALUE_WKND(index)::value; // which 99 : } 100 : 101 111230 : static int initialize(void* dest, param2_T operand) 102 : { 103 : // This assert must newer trigger, because all the reference contents are 104 : // handled by the initilize(void* dest, param_T operand) function above 105 : BOOST_ASSERT(!is_reference_content_t::value); 106 : 107 : typedef typename boost::mpl::if_<is_reference_content_t, param2_T, recursive_enabled_T>::type value_T; 108 111230 : new(dest) value_T( boost::detail::variant::move(operand) ); 109 111230 : return BOOST_MPL_AUX_VALUE_WKND(index)::value; // which 110 : } 111 : }; 112 : 113 : friend class initializer_node; 114 : 115 : public: // metafunction result 116 : 117 : typedef mpl::pair< 118 : initializer_node 119 : , typename mpl::next< index >::type 120 : > type; 121 : 122 : }; 123 : }; 124 : 125 : // (detail) class initializer_root 126 : // 127 : // Every level of the initializer hierarchy must expose the name 128 : // "initialize," so initializer_root provides a dummy function: 129 : // 130 : class initializer_root 131 : { 132 : public: // static functions 133 : 134 : static void initialize(); 135 : 136 : }; 137 : 138 : }} // namespace detail::variant 139 : } // namespace boost 140 : 141 : /////////////////////////////////////////////////////////////////////////////// 142 : // macro BOOST_VARIANT_AUX_INITIALIZER_T 143 : // 144 : // Given both the variant's typelist and a basename for forming the list of 145 : // bounded types (i.e., T becomes T1, T2, etc.), exposes the initializer 146 : // most appropriate to the current compiler. 147 : // 148 : 149 : #define BOOST_VARIANT_AUX_INITIALIZER_T( mpl_seq, typename_base ) \ 150 : ::boost::mpl::iter_fold< \ 151 : mpl_seq \ 152 : , ::boost::mpl::pair< \ 153 : ::boost::detail::variant::initializer_root \ 154 : , ::boost::mpl::int_<0> \ 155 : > \ 156 : , ::boost::mpl::protect< \ 157 : ::boost::detail::variant::make_initializer_node \ 158 : > \ 159 : >::type::first \ 160 : /**/ 161 : 162 : #endif // BOOST_VARIANT_DETAIL_INITIALIZER_HPP