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