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