1 //----------------------------------------------------------------------------- 2 // boost variant/recursive_variant.hpp header file 3 // See http://www.boost.org for updates, documentation, and revision history. 4 //----------------------------------------------------------------------------- 5 // 6 // Copyright (c) 2003 Eric Friedman 7 // Copyright (c) 2013-2021 Antony Polukhin 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_RECURSIVE_VARIANT_HPP 14 #define BOOST_VARIANT_RECURSIVE_VARIANT_HPP 15 16 #include <boost/variant/variant_fwd.hpp> 17 #include <boost/variant/detail/enable_recursive.hpp> 18 #include <boost/variant/detail/substitute_fwd.hpp> 19 #include <boost/variant/detail/make_variant_list.hpp> 20 #include <boost/variant/detail/over_sequence.hpp> 21 22 #include <boost/mpl/aux_/lambda_arity_param.hpp> 23 24 #include <boost/mpl/equal.hpp> 25 #include <boost/mpl/eval_if.hpp> 26 #include <boost/mpl/identity.hpp> 27 #include <boost/mpl/if.hpp> 28 #include <boost/mpl/protect.hpp> 29 #include <boost/mpl/transform.hpp> 30 #include <boost/type_traits/is_same.hpp> 31 #include <boost/preprocessor/cat.hpp> 32 #include <boost/preprocessor/repeat.hpp> 33 34 #include <boost/mpl/bool.hpp> 35 #include <boost/mpl/is_sequence.hpp> 36 #include <boost/variant/variant.hpp> 37 38 namespace boost { 39 40 namespace detail { namespace variant { 41 42 /////////////////////////////////////////////////////////////////////////////// 43 // (detail) metafunction specialization substitute 44 // 45 // Handles embedded variant types when substituting for recursive_variant_. 46 // 47 48 #if !defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE) 49 50 template < 51 BOOST_VARIANT_ENUM_PARAMS(typename T) 52 , typename RecursiveVariant 53 BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(typename Arity) 54 > 55 struct substitute< 56 ::boost::variant< 57 recursive_flag< T0 > 58 , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T) 59 > 60 , RecursiveVariant 61 , ::boost::recursive_variant_ 62 BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(Arity) 63 > 64 { 65 typedef ::boost::variant< 66 recursive_flag< T0 > 67 , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T) 68 > type; 69 }; 70 71 template < 72 BOOST_VARIANT_ENUM_PARAMS(typename T) 73 , typename RecursiveVariant 74 BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(typename Arity) 75 > 76 struct substitute< 77 ::boost::variant< 78 ::boost::detail::variant::over_sequence< T0 > 79 , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T) 80 > 81 , RecursiveVariant 82 , ::boost::recursive_variant_ 83 BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(Arity) 84 > 85 { 86 private: 87 88 typedef T0 initial_types; 89 90 typedef typename mpl::transform< 91 initial_types 92 , mpl::protect< quoted_enable_recursive<RecursiveVariant,mpl::true_> > 93 >::type types; 94 95 public: 96 97 typedef typename mpl::if_< 98 mpl::equal<initial_types, types, ::boost::is_same<mpl::_1, mpl::_2> > 99 , ::boost::variant< 100 ::boost::detail::variant::over_sequence< T0 > 101 , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T) 102 > 103 , ::boost::variant< over_sequence<types> > 104 >::type type; 105 }; 106 107 template < 108 BOOST_VARIANT_ENUM_PARAMS(typename T) 109 , typename RecursiveVariant 110 BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(typename Arity) 111 > 112 struct substitute< 113 ::boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) > 114 , RecursiveVariant 115 , ::boost::recursive_variant_ 116 BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(Arity) 117 > 118 { 119 #if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) 120 121 typedef ::boost::variant< 122 typename enable_recursive< 123 T0 124 , RecursiveVariant 125 , mpl::true_ 126 >::type, 127 typename enable_recursive< 128 TN 129 , RecursiveVariant 130 , mpl::true_ 131 >::type... 132 > type; 133 134 #else // defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) 135 136 private: // helpers, for metafunction result (below) 137 138 #define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS(z,N,_) \ 139 typedef typename enable_recursive< \ 140 BOOST_PP_CAT(T,N) \ 141 , RecursiveVariant \ 142 , mpl::true_ \ 143 >::type BOOST_PP_CAT(wknd_T,N); \ 144 /**/ 145 146 BOOST_PP_REPEAT( 147 BOOST_VARIANT_LIMIT_TYPES 148 , BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS 149 , _ 150 ) 151 152 #undef BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS 153 154 public: // metafunction result 155 156 typedef ::boost::variant< BOOST_VARIANT_ENUM_PARAMS(wknd_T) > type; 157 #endif // BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES workaround 158 }; 159 160 #else // defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE) 161 162 // 163 // no specializations: embedded variants unsupported on these compilers! 164 // 165 166 #endif // !defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE) 167 168 }} // namespace detail::variant 169 170 /////////////////////////////////////////////////////////////////////////////// 171 // metafunction make_recursive_variant 172 // 173 // See docs and boost/variant/variant_fwd.hpp for more information. 174 // 175 template < BOOST_VARIANT_ENUM_PARAMS(typename T) > 176 struct make_recursive_variant 177 { 178 public: // metafunction result 179 180 typedef boost::variant< 181 detail::variant::recursive_flag< T0 > 182 , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T) 183 > type; 184 185 }; 186 187 /////////////////////////////////////////////////////////////////////////////// 188 // metafunction make_recursive_variant_over 189 // 190 // See docs and boost/variant/variant_fwd.hpp for more information. 191 // 192 template <typename Types> 193 struct make_recursive_variant_over 194 { 195 private: // precondition assertions 196 197 BOOST_STATIC_ASSERT(( ::boost::mpl::is_sequence<Types>::value )); 198 199 public: // metafunction result 200 201 typedef typename make_recursive_variant< 202 detail::variant::over_sequence< Types > 203 >::type type; 204 205 }; 206 207 } // namespace boost 208 209 #endif // BOOST_VARIANT_RECURSIVE_VARIANT_HPP 210