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