recursive_variant.hpp 5.9 KB

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