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