]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | //----------------------------------------------------------------------------- |
2 | // boost variant/detail/visitation_impl.hpp header file | |
3 | // See http://www.boost.org for updates, documentation, and revision history. | |
4 | //----------------------------------------------------------------------------- | |
5 | // | |
6 | // Copyright (c) 2003 | |
7 | // Eric Friedman | |
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_VISITATION_IMPL_HPP | |
14 | #define BOOST_VARIANT_DETAIL_VISITATION_IMPL_HPP | |
15 | ||
16 | #include <boost/config.hpp> | |
17 | ||
18 | #include <boost/variant/detail/backup_holder.hpp> | |
19 | #include <boost/variant/detail/cast_storage.hpp> | |
20 | #include <boost/variant/detail/forced_return.hpp> | |
21 | #include <boost/variant/detail/generic_result_type.hpp> | |
22 | #include <boost/variant/variant_fwd.hpp> // for BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES | |
23 | ||
24 | #include <boost/mpl/eval_if.hpp> | |
25 | #include <boost/mpl/bool.hpp> | |
26 | #include <boost/mpl/identity.hpp> | |
27 | #include <boost/mpl/int.hpp> | |
28 | #include <boost/mpl/next.hpp> | |
29 | #include <boost/mpl/deref.hpp> | |
30 | #include <boost/mpl/or.hpp> | |
31 | #include <boost/preprocessor/cat.hpp> | |
32 | #include <boost/preprocessor/inc.hpp> | |
33 | #include <boost/preprocessor/repeat.hpp> | |
34 | #include <boost/type_traits/is_same.hpp> | |
35 | #include <boost/type_traits/has_nothrow_copy.hpp> | |
36 | #include <boost/type_traits/is_nothrow_move_constructible.hpp> | |
37 | ||
38 | #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) | |
39 | # pragma warning (push) | |
40 | # pragma warning (disable : 4702) //unreachable code | |
41 | #endif | |
42 | ||
43 | /////////////////////////////////////////////////////////////////////////////// | |
44 | // BOOST_VARIANT_VISITATION_UNROLLING_LIMIT | |
45 | // | |
46 | // Unrolls variant's visitation mechanism to reduce template instantiation | |
47 | // and potentially increase runtime performance. (TODO: Investigate further.) | |
48 | // | |
49 | #if !defined(BOOST_VARIANT_VISITATION_UNROLLING_LIMIT) | |
50 | ||
51 | #ifndef BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES | |
52 | # include <boost/mpl/limits/list.hpp> | |
53 | # define BOOST_VARIANT_VISITATION_UNROLLING_LIMIT \ | |
54 | BOOST_MPL_LIMIT_LIST_SIZE | |
55 | #else | |
56 | # define BOOST_VARIANT_VISITATION_UNROLLING_LIMIT \ | |
57 | BOOST_VARIANT_LIMIT_TYPES | |
58 | #endif | |
59 | ||
60 | #endif | |
61 | ||
62 | namespace boost { | |
63 | namespace detail { namespace variant { | |
64 | ||
65 | /////////////////////////////////////////////////////////////////////////////// | |
66 | // (detail) class apply_visitor_unrolled | |
67 | // | |
68 | // Tag type indicates when visitation_impl is unrolled. | |
69 | // | |
70 | struct apply_visitor_unrolled {}; | |
71 | ||
72 | /////////////////////////////////////////////////////////////////////////////// | |
73 | // (detail) class template visitation_impl_step | |
74 | // | |
75 | // "Never ending" iterator range facilitates visitation_impl unrolling. | |
76 | // | |
77 | ||
78 | ||
79 | template <typename Iter, typename LastIter> | |
80 | struct visitation_impl_step | |
81 | { | |
82 | typedef typename mpl::deref<Iter>::type type; | |
83 | ||
84 | typedef typename mpl::next<Iter>::type next_iter; | |
85 | typedef visitation_impl_step< | |
86 | next_iter, LastIter | |
87 | > next; | |
88 | }; | |
89 | ||
90 | template <typename LastIter> | |
91 | struct visitation_impl_step< LastIter,LastIter > | |
92 | { | |
93 | typedef apply_visitor_unrolled type; | |
94 | typedef visitation_impl_step next; | |
95 | }; | |
96 | ||
97 | ||
98 | /////////////////////////////////////////////////////////////////////////////// | |
99 | // (detail) function template visitation_impl_invoke | |
100 | // | |
101 | // Invokes the given visitor on the specified type in the given storage. | |
102 | // | |
103 | ||
104 | template <typename Visitor, typename VoidPtrCV, typename T> | |
105 | inline | |
106 | BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type) | |
107 | visitation_impl_invoke_impl( | |
108 | int, Visitor& visitor, VoidPtrCV storage, T* | |
109 | , mpl::true_// never_uses_backup | |
110 | ) | |
111 | { | |
112 | return visitor.internal_visit( | |
113 | cast_storage<T>(storage), 1L | |
114 | ); | |
115 | } | |
116 | ||
117 | template <typename Visitor, typename VoidPtrCV, typename T> | |
118 | inline | |
119 | BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type) | |
120 | visitation_impl_invoke_impl( | |
121 | int internal_which, Visitor& visitor, VoidPtrCV storage, T* | |
122 | , mpl::false_// never_uses_backup | |
123 | ) | |
124 | { | |
125 | if (internal_which >= 0) | |
126 | { | |
127 | return visitor.internal_visit( | |
128 | cast_storage<T>(storage), 1L | |
129 | ); | |
130 | } | |
131 | else | |
132 | { | |
133 | return visitor.internal_visit( | |
134 | cast_storage< backup_holder<T> >(storage), 1L | |
135 | ); | |
136 | } | |
137 | } | |
138 | ||
139 | template <typename Visitor, typename VoidPtrCV, typename T, typename NoBackupFlag> | |
140 | inline | |
141 | BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type) | |
142 | visitation_impl_invoke( | |
143 | int internal_which, Visitor& visitor, VoidPtrCV storage, T* t | |
144 | , NoBackupFlag | |
145 | , int | |
146 | ) | |
147 | { | |
148 | typedef typename mpl::or_< | |
149 | NoBackupFlag | |
150 | , is_nothrow_move_constructible<T> | |
151 | , has_nothrow_copy<T> | |
152 | >::type never_uses_backup; | |
153 | ||
154 | return (visitation_impl_invoke_impl)( | |
155 | internal_which, visitor, storage, t | |
156 | , never_uses_backup() | |
157 | ); | |
158 | } | |
159 | ||
160 | template <typename Visitor, typename VoidPtrCV, typename NBF> | |
161 | inline | |
162 | BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type) | |
163 | visitation_impl_invoke(int, Visitor&, VoidPtrCV, apply_visitor_unrolled*, NBF, long) | |
164 | { | |
165 | // should never be here at runtime! | |
166 | typedef typename Visitor::result_type result_type; | |
167 | return ::boost::detail::variant::forced_return< result_type >(); | |
168 | } | |
169 | ||
170 | /////////////////////////////////////////////////////////////////////////////// | |
171 | // (detail) function template visitation_impl | |
172 | // | |
173 | // Invokes the given visitor on the type in the given variant storage. | |
174 | // | |
175 | ||
176 | template < | |
177 | typename W, typename S | |
178 | , typename Visitor, typename VPCV | |
179 | , typename NBF | |
180 | > | |
181 | inline | |
182 | BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type) | |
183 | visitation_impl( | |
184 | int, int, Visitor&, VPCV | |
185 | , mpl::true_ // is_apply_visitor_unrolled | |
186 | , NBF, W* = 0, S* = 0 | |
187 | ) | |
188 | { | |
189 | // should never be here at runtime! | |
190 | typedef typename Visitor::result_type result_type; | |
191 | return ::boost::detail::variant::forced_return< result_type >(); | |
192 | } | |
193 | ||
194 | template < | |
195 | typename Which, typename step0 | |
196 | , typename Visitor, typename VoidPtrCV | |
197 | , typename NoBackupFlag | |
198 | > | |
199 | inline | |
200 | BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type) | |
201 | visitation_impl( | |
202 | const int internal_which, const int logical_which | |
203 | , Visitor& visitor, VoidPtrCV storage | |
204 | , mpl::false_ // is_apply_visitor_unrolled | |
205 | , NoBackupFlag no_backup_flag | |
206 | , Which* = 0, step0* = 0 | |
207 | ) | |
208 | { | |
209 | // Typedef apply_visitor_unrolled steps and associated types... | |
210 | # define BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_TYPEDEF(z, N, _) \ | |
211 | typedef typename BOOST_PP_CAT(step,N)::type BOOST_PP_CAT(T,N); \ | |
212 | typedef typename BOOST_PP_CAT(step,N)::next \ | |
213 | BOOST_PP_CAT(step, BOOST_PP_INC(N)); \ | |
214 | /**/ | |
215 | ||
216 | BOOST_PP_REPEAT( | |
217 | BOOST_VARIANT_VISITATION_UNROLLING_LIMIT | |
218 | , BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_TYPEDEF | |
219 | , _ | |
220 | ) | |
221 | ||
222 | # undef BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_TYPEDEF | |
223 | ||
224 | // ...switch on the target which-index value... | |
225 | switch (logical_which) | |
226 | { | |
227 | ||
228 | // ...applying the appropriate case: | |
229 | # define BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_CASE(z, N, _) \ | |
230 | case (Which::value + (N)): \ | |
231 | return (visitation_impl_invoke)( \ | |
232 | internal_which, visitor, storage \ | |
233 | , static_cast<BOOST_PP_CAT(T,N)*>(0) \ | |
234 | , no_backup_flag, 1L \ | |
235 | ); \ | |
236 | /**/ | |
237 | ||
238 | BOOST_PP_REPEAT( | |
239 | BOOST_VARIANT_VISITATION_UNROLLING_LIMIT | |
240 | , BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_CASE | |
241 | , _ | |
242 | ) | |
243 | ||
244 | # undef BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_CASE | |
245 | ||
246 | default: break; | |
247 | } | |
248 | ||
249 | // If not handled in this iteration, continue unrolling: | |
250 | typedef mpl::int_< | |
251 | Which::value + (BOOST_VARIANT_VISITATION_UNROLLING_LIMIT) | |
252 | > next_which; | |
253 | ||
254 | typedef BOOST_PP_CAT(step, BOOST_VARIANT_VISITATION_UNROLLING_LIMIT) | |
255 | next_step; | |
256 | ||
257 | typedef typename next_step::type next_type; | |
258 | typedef typename is_same< next_type,apply_visitor_unrolled >::type | |
259 | is_apply_visitor_unrolled; | |
260 | ||
261 | return detail::variant::visitation_impl( | |
262 | internal_which, logical_which | |
263 | , visitor, storage | |
264 | , is_apply_visitor_unrolled() | |
265 | , no_backup_flag | |
266 | , static_cast<next_which*>(0), static_cast<next_step*>(0) | |
267 | ); | |
268 | } | |
269 | ||
270 | }} // namespace detail::variant | |
271 | } // namespace boost | |
272 | ||
273 | #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) | |
274 | # pragma warning(pop) | |
275 | #endif | |
276 | ||
277 | #endif // BOOST_VARIANT_DETAIL_VISITATION_IMPL_HPP |