Chris@16
|
1 //-----------------------------------------------------------------------------
|
Chris@16
|
2 // boost variant/variant.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) 2002-2003 Eric Friedman, Itay Maman
|
Chris@101
|
7 // Copyright (c) 2012-2014 Antony Polukhin
|
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 // Thanks to Adam Romanek for providing patches for exception-disabled env.
|
Chris@16
|
14
|
Chris@16
|
15 #ifndef BOOST_VARIANT_VARIANT_HPP
|
Chris@16
|
16 #define BOOST_VARIANT_VARIANT_HPP
|
Chris@16
|
17
|
Chris@16
|
18 #include <cstddef> // for std::size_t
|
Chris@16
|
19 #include <new> // for placement new
|
Chris@16
|
20
|
Chris@101
|
21 #include "boost/type_index.hpp"
|
Chris@16
|
22
|
Chris@16
|
23 #include "boost/variant/detail/config.hpp"
|
Chris@16
|
24 #include "boost/mpl/aux_/value_wknd.hpp"
|
Chris@16
|
25
|
Chris@16
|
26 #include "boost/variant/variant_fwd.hpp"
|
Chris@16
|
27 #include "boost/variant/detail/backup_holder.hpp"
|
Chris@16
|
28 #include "boost/variant/detail/enable_recursive_fwd.hpp"
|
Chris@16
|
29 #include "boost/variant/detail/forced_return.hpp"
|
Chris@16
|
30 #include "boost/variant/detail/initializer.hpp"
|
Chris@16
|
31 #include "boost/variant/detail/make_variant_list.hpp"
|
Chris@16
|
32 #include "boost/variant/detail/over_sequence.hpp"
|
Chris@16
|
33 #include "boost/variant/detail/visitation_impl.hpp"
|
Chris@16
|
34 #include "boost/variant/detail/hash_variant.hpp"
|
Chris@16
|
35
|
Chris@16
|
36 #include "boost/variant/detail/generic_result_type.hpp"
|
Chris@16
|
37 #include "boost/variant/detail/move.hpp"
|
Chris@16
|
38
|
Chris@16
|
39 #include "boost/detail/no_exceptions_support.hpp"
|
Chris@16
|
40 #include "boost/detail/reference_content.hpp"
|
Chris@16
|
41 #include "boost/aligned_storage.hpp"
|
Chris@16
|
42 #include "boost/blank.hpp"
|
Chris@16
|
43 #include "boost/math/common_factor_ct.hpp"
|
Chris@16
|
44 #include "boost/static_assert.hpp"
|
Chris@16
|
45 #include "boost/preprocessor/cat.hpp"
|
Chris@16
|
46 #include "boost/preprocessor/repeat.hpp"
|
Chris@16
|
47 #include "boost/type_traits/alignment_of.hpp"
|
Chris@16
|
48 #include "boost/type_traits/add_const.hpp"
|
Chris@16
|
49 #include "boost/type_traits/has_nothrow_constructor.hpp"
|
Chris@16
|
50 #include "boost/type_traits/has_nothrow_copy.hpp"
|
Chris@101
|
51 #include "boost/type_traits/is_nothrow_move_assignable.hpp"
|
Chris@16
|
52 #include "boost/type_traits/is_nothrow_move_constructible.hpp"
|
Chris@16
|
53 #include "boost/type_traits/is_const.hpp"
|
Chris@16
|
54 #include "boost/type_traits/is_same.hpp"
|
Chris@16
|
55 #include "boost/type_traits/is_rvalue_reference.hpp"
|
Chris@16
|
56 #include "boost/utility/enable_if.hpp"
|
Chris@16
|
57 #include "boost/utility/declval.hpp"
|
Chris@16
|
58 #include "boost/variant/recursive_wrapper_fwd.hpp"
|
Chris@16
|
59 #include "boost/variant/static_visitor.hpp"
|
Chris@16
|
60
|
Chris@16
|
61 #include "boost/mpl/assert.hpp"
|
Chris@16
|
62 #include "boost/mpl/begin_end.hpp"
|
Chris@16
|
63 #include "boost/mpl/bool.hpp"
|
Chris@16
|
64 #include "boost/mpl/deref.hpp"
|
Chris@16
|
65 #include "boost/mpl/empty.hpp"
|
Chris@16
|
66 #include "boost/mpl/eval_if.hpp"
|
Chris@16
|
67 #include "boost/mpl/find_if.hpp"
|
Chris@16
|
68 #include "boost/mpl/fold.hpp"
|
Chris@16
|
69 #include "boost/mpl/front.hpp"
|
Chris@16
|
70 #include "boost/mpl/identity.hpp"
|
Chris@16
|
71 #include "boost/mpl/if.hpp"
|
Chris@16
|
72 #include "boost/mpl/int.hpp"
|
Chris@16
|
73 #include "boost/mpl/is_sequence.hpp"
|
Chris@16
|
74 #include "boost/mpl/iterator_range.hpp"
|
Chris@16
|
75 #include "boost/mpl/iter_fold_if.hpp"
|
Chris@16
|
76 #include "boost/mpl/logical.hpp"
|
Chris@16
|
77 #include "boost/mpl/max_element.hpp"
|
Chris@16
|
78 #include "boost/mpl/next.hpp"
|
Chris@16
|
79 #include "boost/mpl/not.hpp"
|
Chris@16
|
80 #include "boost/mpl/pair.hpp"
|
Chris@16
|
81 #include "boost/mpl/protect.hpp"
|
Chris@16
|
82 #include "boost/mpl/push_front.hpp"
|
Chris@16
|
83 #include "boost/mpl/same_as.hpp"
|
Chris@16
|
84 #include "boost/mpl/size_t.hpp"
|
Chris@16
|
85 #include "boost/mpl/sizeof.hpp"
|
Chris@16
|
86 #include "boost/mpl/transform.hpp"
|
Chris@16
|
87
|
Chris@16
|
88 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
89 // Implementation Macros:
|
Chris@16
|
90 //
|
Chris@16
|
91 // BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
|
Chris@16
|
92 // Defined in boost/variant/detail/visitation_impl.hpp.
|
Chris@16
|
93 //
|
Chris@16
|
94 // BOOST_VARIANT_MINIMIZE_SIZE
|
Chris@16
|
95 // When #defined, implementation employs all known means to minimize the
|
Chris@16
|
96 // size of variant obje cts. However, often unsuccessful due to alignment
|
Chris@16
|
97 // issues, and potentially harmful to runtime speed, so not enabled by
|
Chris@16
|
98 // default. (TODO: Investigate further.)
|
Chris@16
|
99
|
Chris@16
|
100 #if defined(BOOST_VARIANT_MINIMIZE_SIZE)
|
Chris@16
|
101 # include <climits> // for SCHAR_MAX
|
Chris@16
|
102 # include "boost/mpl/eval_if.hpp"
|
Chris@16
|
103 # include "boost/mpl/equal_to.hpp"
|
Chris@16
|
104 # include "boost/mpl/identity.hpp"
|
Chris@16
|
105 # include "boost/mpl/int.hpp"
|
Chris@16
|
106 # include "boost/mpl/if.hpp"
|
Chris@16
|
107 # include "boost/mpl/less.hpp"
|
Chris@16
|
108 # include "boost/mpl/long.hpp"
|
Chris@16
|
109 # include "boost/mpl/O1_size.hpp"
|
Chris@16
|
110 #endif
|
Chris@16
|
111
|
Chris@16
|
112
|
Chris@16
|
113 namespace boost {
|
Chris@16
|
114
|
Chris@16
|
115 namespace detail { namespace variant {
|
Chris@16
|
116
|
Chris@16
|
117 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
118 // (detail) metafunction max_value
|
Chris@16
|
119 //
|
Chris@16
|
120 // Finds the maximum value of the unary metafunction F over Sequence.
|
Chris@16
|
121 //
|
Chris@16
|
122 template <typename Sequence, typename F>
|
Chris@16
|
123 struct max_value
|
Chris@16
|
124 {
|
Chris@16
|
125 private: // helpers, for metafunction result (below)
|
Chris@16
|
126
|
Chris@16
|
127 typedef typename mpl::transform1<Sequence, F>::type transformed_;
|
Chris@16
|
128 typedef typename mpl::max_element<transformed_
|
Chris@16
|
129
|
Chris@16
|
130 >::type max_it;
|
Chris@16
|
131
|
Chris@16
|
132 public: // metafunction result
|
Chris@16
|
133
|
Chris@16
|
134 typedef typename mpl::deref<max_it>::type
|
Chris@16
|
135 type;
|
Chris@16
|
136
|
Chris@16
|
137 };
|
Chris@16
|
138
|
Chris@16
|
139 struct add_alignment
|
Chris@16
|
140 {
|
Chris@16
|
141 template <typename State, typename Item>
|
Chris@16
|
142 struct apply
|
Chris@16
|
143 : mpl::size_t<
|
Chris@16
|
144 ::boost::math::static_lcm<
|
Chris@16
|
145 BOOST_MPL_AUX_VALUE_WKND(State)::value
|
Chris@16
|
146 , ::boost::alignment_of<Item>::value
|
Chris@16
|
147 >::value
|
Chris@16
|
148 >
|
Chris@16
|
149 {};
|
Chris@16
|
150 };
|
Chris@16
|
151
|
Chris@16
|
152 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
153 // (detail) metafunction find_fallback_type
|
Chris@16
|
154 //
|
Chris@16
|
155 // Provides a fallback (i.e., nothrow default-constructible) type from the
|
Chris@16
|
156 // specified sequence, or no_fallback_type if not found.
|
Chris@16
|
157 //
|
Chris@16
|
158 // This implementation is designed to prefer boost::blank over other potential
|
Chris@16
|
159 // fallback types, regardless of its position in the specified sequence.
|
Chris@16
|
160 //
|
Chris@16
|
161
|
Chris@16
|
162 class no_fallback_type;
|
Chris@16
|
163
|
Chris@16
|
164 struct find_fallback_type_pred
|
Chris@16
|
165 {
|
Chris@16
|
166 template <typename Iterator>
|
Chris@16
|
167 struct apply
|
Chris@16
|
168 {
|
Chris@16
|
169 private:
|
Chris@16
|
170 typedef typename mpl::deref<Iterator>::type t_;
|
Chris@16
|
171
|
Chris@16
|
172 public:
|
Chris@16
|
173 typedef mpl::not_< has_nothrow_constructor<t_> > type;
|
Chris@16
|
174 };
|
Chris@16
|
175 };
|
Chris@16
|
176
|
Chris@16
|
177 template <typename Types>
|
Chris@16
|
178 struct find_fallback_type
|
Chris@16
|
179 {
|
Chris@16
|
180 private: // helpers, for metafunction result (below)
|
Chris@16
|
181
|
Chris@16
|
182 typedef typename mpl::end<Types>::type end_it;
|
Chris@16
|
183
|
Chris@16
|
184 // [Find the first suitable fallback type...]
|
Chris@16
|
185
|
Chris@16
|
186 typedef typename mpl::iter_fold_if<
|
Chris@16
|
187 Types
|
Chris@16
|
188 , mpl::int_<0>, mpl::protect< mpl::next<> >
|
Chris@16
|
189 , mpl::protect< find_fallback_type_pred >
|
Chris@16
|
190 >::type first_result_;
|
Chris@16
|
191
|
Chris@16
|
192 typedef typename first_result_::first first_result_index;
|
Chris@16
|
193 typedef typename first_result_::second first_result_it;
|
Chris@16
|
194
|
Chris@16
|
195 // [...now search the rest of the sequence for boost::blank...]
|
Chris@16
|
196
|
Chris@16
|
197 typedef typename mpl::iter_fold_if<
|
Chris@16
|
198 mpl::iterator_range< first_result_it,end_it >
|
Chris@16
|
199 , first_result_index, mpl::protect< mpl::next<> >
|
Chris@16
|
200 , mpl::protect< mpl::not_same_as<boost::blank> >
|
Chris@16
|
201 >::type second_result_;
|
Chris@16
|
202
|
Chris@16
|
203 typedef typename second_result_::second second_result_it;
|
Chris@16
|
204
|
Chris@16
|
205 public: // metafunction result
|
Chris@16
|
206
|
Chris@16
|
207 // [...and return the results of the search:]
|
Chris@16
|
208 typedef typename mpl::eval_if<
|
Chris@16
|
209 is_same< second_result_it,end_it >
|
Chris@16
|
210 , mpl::if_<
|
Chris@16
|
211 is_same< first_result_it,end_it >
|
Chris@16
|
212 , mpl::pair< no_fallback_type,no_fallback_type >
|
Chris@16
|
213 , first_result_
|
Chris@16
|
214 >
|
Chris@16
|
215 , mpl::identity< second_result_ >
|
Chris@16
|
216 >::type type;
|
Chris@16
|
217
|
Chris@16
|
218 };
|
Chris@16
|
219
|
Chris@16
|
220 #ifndef BOOST_NO_CXX11_NOEXCEPT
|
Chris@16
|
221 ///////////////////////////////////////////////////////////////////////////////
|
Chris@101
|
222 // (detail) metafunction is_variant_move_noexcept_constructible
|
Chris@16
|
223 //
|
Chris@16
|
224 // Returns true_type if all the types are nothrow move constructible.
|
Chris@16
|
225 //
|
Chris@16
|
226 template <class Types>
|
Chris@101
|
227 struct is_variant_move_noexcept_constructible {
|
Chris@16
|
228 typedef typename boost::mpl::find_if<
|
Chris@16
|
229 Types, mpl::not_<boost::is_nothrow_move_constructible<boost::mpl::_1> >
|
Chris@16
|
230 >::type iterator_t;
|
Chris@16
|
231
|
Chris@16
|
232 typedef typename boost::mpl::end<Types>::type end_t;
|
Chris@16
|
233 typedef typename boost::is_same<
|
Chris@16
|
234 iterator_t, end_t
|
Chris@16
|
235 >::type type;
|
Chris@16
|
236 };
|
Chris@101
|
237
|
Chris@101
|
238 ///////////////////////////////////////////////////////////////////////////////
|
Chris@101
|
239 // (detail) metafunction is_variant_move_noexcept_assignable
|
Chris@101
|
240 //
|
Chris@101
|
241 // Returns true_type if all the types are nothrow move constructible.
|
Chris@101
|
242 //
|
Chris@101
|
243 template <class Types>
|
Chris@101
|
244 struct is_variant_move_noexcept_assignable {
|
Chris@101
|
245 typedef typename boost::mpl::find_if<
|
Chris@101
|
246 Types, mpl::not_<boost::is_nothrow_move_assignable<boost::mpl::_1> >
|
Chris@101
|
247 >::type iterator_t;
|
Chris@101
|
248
|
Chris@101
|
249 typedef typename boost::mpl::end<Types>::type end_t;
|
Chris@101
|
250 typedef typename boost::is_same<
|
Chris@101
|
251 iterator_t, end_t
|
Chris@101
|
252 >::type type;
|
Chris@101
|
253 };
|
Chris@16
|
254 #endif // BOOST_NO_CXX11_NOEXCEPT
|
Chris@16
|
255
|
Chris@16
|
256 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
257 // (detail) metafunction make_storage
|
Chris@16
|
258 //
|
Chris@16
|
259 // Provides an aligned storage type capable of holding any of the types
|
Chris@16
|
260 // specified in the given type-sequence.
|
Chris@16
|
261 //
|
Chris@16
|
262
|
Chris@16
|
263 template <typename Types, typename NeverUsesBackupFlag>
|
Chris@16
|
264 struct make_storage
|
Chris@16
|
265 {
|
Chris@16
|
266 private: // helpers, for metafunction result (below)
|
Chris@16
|
267
|
Chris@16
|
268 typedef typename mpl::eval_if<
|
Chris@16
|
269 NeverUsesBackupFlag
|
Chris@16
|
270 , mpl::identity< Types >
|
Chris@16
|
271 , mpl::push_front<
|
Chris@16
|
272 Types, backup_holder<void*>
|
Chris@16
|
273 >
|
Chris@16
|
274 >::type types;
|
Chris@16
|
275
|
Chris@16
|
276 typedef typename max_value<
|
Chris@16
|
277 types, mpl::sizeof_<mpl::_1>
|
Chris@16
|
278 >::type max_size;
|
Chris@16
|
279
|
Chris@16
|
280 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551))
|
Chris@16
|
281
|
Chris@16
|
282 typedef typename mpl::fold<
|
Chris@16
|
283 types
|
Chris@16
|
284 , mpl::size_t<1>
|
Chris@16
|
285 , add_alignment
|
Chris@16
|
286 >::type max_alignment;
|
Chris@16
|
287
|
Chris@16
|
288 #else // borland
|
Chris@16
|
289
|
Chris@16
|
290 // temporary workaround -- use maximal alignment
|
Chris@16
|
291 typedef mpl::size_t< -1 > max_alignment;
|
Chris@16
|
292
|
Chris@16
|
293 #endif // borland workaround
|
Chris@16
|
294
|
Chris@16
|
295 public: // metafunction result
|
Chris@16
|
296
|
Chris@16
|
297 typedef ::boost::aligned_storage<
|
Chris@16
|
298 BOOST_MPL_AUX_VALUE_WKND(max_size)::value
|
Chris@16
|
299 , BOOST_MPL_AUX_VALUE_WKND(max_alignment)::value
|
Chris@16
|
300 > type;
|
Chris@16
|
301 };
|
Chris@16
|
302
|
Chris@16
|
303 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
304 // (detail) class destroyer
|
Chris@16
|
305 //
|
Chris@16
|
306 // Internal visitor that destroys the value it visits.
|
Chris@16
|
307 //
|
Chris@16
|
308 struct destroyer
|
Chris@16
|
309 : public static_visitor<>
|
Chris@16
|
310 {
|
Chris@16
|
311 public: // visitor interfaces
|
Chris@16
|
312
|
Chris@16
|
313 template <typename T>
|
Chris@16
|
314 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
|
Chris@101
|
315 internal_visit(T& operand, int) const BOOST_NOEXCEPT
|
Chris@16
|
316 {
|
Chris@101
|
317 operand.~T(); // must be noexcept
|
Chris@16
|
318
|
Chris@16
|
319 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551)) || \
|
Chris@16
|
320 BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
|
Chris@16
|
321 operand; // suppresses warnings
|
Chris@16
|
322 #endif
|
Chris@16
|
323
|
Chris@16
|
324 BOOST_VARIANT_AUX_RETURN_VOID;
|
Chris@16
|
325 }
|
Chris@16
|
326
|
Chris@16
|
327 };
|
Chris@16
|
328
|
Chris@16
|
329 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
330 // (detail) class template known_get
|
Chris@16
|
331 //
|
Chris@16
|
332 // Visitor that returns a reference to content of the specified type.
|
Chris@16
|
333 //
|
Chris@16
|
334 // Precondition: visited variant MUST contain logical content of type T.
|
Chris@16
|
335 //
|
Chris@16
|
336 template <typename T>
|
Chris@16
|
337 class known_get
|
Chris@16
|
338 : public static_visitor<T&>
|
Chris@16
|
339 {
|
Chris@16
|
340
|
Chris@16
|
341 public: // visitor interface
|
Chris@16
|
342
|
Chris@16
|
343 T& operator()(T& operand) const BOOST_NOEXCEPT
|
Chris@16
|
344 {
|
Chris@16
|
345 return operand;
|
Chris@16
|
346 }
|
Chris@16
|
347
|
Chris@16
|
348 template <typename U>
|
Chris@16
|
349 T& operator()(U&) const
|
Chris@16
|
350 {
|
Chris@16
|
351 // logical error to be here: see precondition above
|
Chris@16
|
352 return ::boost::detail::variant::forced_return< T& >();
|
Chris@16
|
353 }
|
Chris@16
|
354 };
|
Chris@16
|
355
|
Chris@16
|
356 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
357 // (detail) class copy_into
|
Chris@16
|
358 //
|
Chris@16
|
359 // Internal visitor that copies the value it visits into the given buffer.
|
Chris@16
|
360 //
|
Chris@16
|
361 class copy_into
|
Chris@16
|
362 : public static_visitor<>
|
Chris@16
|
363 {
|
Chris@16
|
364 private: // representation
|
Chris@16
|
365
|
Chris@16
|
366 void* storage_;
|
Chris@16
|
367
|
Chris@16
|
368 public: // structors
|
Chris@16
|
369
|
Chris@16
|
370 explicit copy_into(void* storage) BOOST_NOEXCEPT
|
Chris@16
|
371 : storage_(storage)
|
Chris@16
|
372 {
|
Chris@16
|
373 }
|
Chris@16
|
374
|
Chris@16
|
375 public: // internal visitor interface
|
Chris@16
|
376
|
Chris@16
|
377 template <typename T>
|
Chris@16
|
378 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
|
Chris@16
|
379 internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
|
Chris@16
|
380 {
|
Chris@16
|
381 new(storage_) T( operand.get() );
|
Chris@16
|
382 BOOST_VARIANT_AUX_RETURN_VOID;
|
Chris@16
|
383 }
|
Chris@16
|
384
|
Chris@16
|
385 template <typename T>
|
Chris@16
|
386 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
|
Chris@16
|
387 internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
|
Chris@16
|
388 {
|
Chris@16
|
389 new(storage_) T( operand.get() );
|
Chris@16
|
390 BOOST_VARIANT_AUX_RETURN_VOID;
|
Chris@16
|
391 }
|
Chris@16
|
392
|
Chris@16
|
393 template <typename T>
|
Chris@16
|
394 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
|
Chris@16
|
395 internal_visit(const T& operand, int) const
|
Chris@16
|
396 {
|
Chris@16
|
397 new(storage_) T(operand);
|
Chris@16
|
398 BOOST_VARIANT_AUX_RETURN_VOID;
|
Chris@16
|
399 }
|
Chris@16
|
400
|
Chris@16
|
401 };
|
Chris@16
|
402
|
Chris@16
|
403 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
404 // (detail) class move_into
|
Chris@16
|
405 //
|
Chris@16
|
406 // Internal visitor that moves the value it visits into the given buffer.
|
Chris@16
|
407 //
|
Chris@16
|
408 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
409 class move_into
|
Chris@16
|
410 : public static_visitor<>
|
Chris@16
|
411 {
|
Chris@16
|
412 private: // representation
|
Chris@16
|
413
|
Chris@16
|
414 void* storage_;
|
Chris@16
|
415
|
Chris@16
|
416 public: // structors
|
Chris@16
|
417
|
Chris@16
|
418 explicit move_into(void* storage) BOOST_NOEXCEPT
|
Chris@16
|
419 : storage_(storage)
|
Chris@16
|
420 {
|
Chris@16
|
421 }
|
Chris@16
|
422
|
Chris@16
|
423 public: // internal visitor interface
|
Chris@16
|
424
|
Chris@16
|
425 template <typename T>
|
Chris@16
|
426 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
|
Chris@16
|
427 internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
|
Chris@16
|
428 {
|
Chris@16
|
429 new(storage_) T( ::boost::detail::variant::move(operand.get()) );
|
Chris@16
|
430 BOOST_VARIANT_AUX_RETURN_VOID;
|
Chris@16
|
431 }
|
Chris@16
|
432
|
Chris@16
|
433 template <typename T>
|
Chris@16
|
434 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
|
Chris@16
|
435 internal_visit(T& operand, int) const BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T(boost::declval<T>())))
|
Chris@16
|
436 {
|
Chris@16
|
437 new(storage_) T(::boost::detail::variant::move(operand));
|
Chris@16
|
438 BOOST_VARIANT_AUX_RETURN_VOID;
|
Chris@16
|
439 }
|
Chris@16
|
440 };
|
Chris@16
|
441 #endif
|
Chris@16
|
442
|
Chris@16
|
443 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
444 // (detail) class assign_storage
|
Chris@16
|
445 //
|
Chris@16
|
446 // Internal visitor that assigns the given storage (which must be a
|
Chris@16
|
447 // constructed value of the same type) to the value it visits.
|
Chris@16
|
448 //
|
Chris@16
|
449 struct assign_storage
|
Chris@16
|
450 : public static_visitor<>
|
Chris@16
|
451 {
|
Chris@16
|
452 private: // representation
|
Chris@16
|
453
|
Chris@16
|
454 const void* rhs_storage_;
|
Chris@16
|
455
|
Chris@16
|
456 public: // structors
|
Chris@16
|
457
|
Chris@16
|
458 explicit assign_storage(const void* rhs_storage) BOOST_NOEXCEPT
|
Chris@16
|
459 : rhs_storage_(rhs_storage)
|
Chris@16
|
460 {
|
Chris@16
|
461 }
|
Chris@16
|
462
|
Chris@16
|
463 public: // internal visitor interfaces
|
Chris@16
|
464
|
Chris@16
|
465 template <typename T>
|
Chris@16
|
466 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
|
Chris@16
|
467 internal_visit(backup_holder<T>& lhs_content, long) const
|
Chris@16
|
468 {
|
Chris@16
|
469 lhs_content.get()
|
Chris@16
|
470 = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
|
Chris@16
|
471 BOOST_VARIANT_AUX_RETURN_VOID;
|
Chris@16
|
472 }
|
Chris@16
|
473
|
Chris@16
|
474 template <typename T>
|
Chris@16
|
475 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
|
Chris@16
|
476 internal_visit(const backup_holder<T>& lhs_content, long) const
|
Chris@16
|
477 {
|
Chris@16
|
478 lhs_content.get()
|
Chris@16
|
479 = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
|
Chris@16
|
480 BOOST_VARIANT_AUX_RETURN_VOID;
|
Chris@16
|
481 }
|
Chris@16
|
482
|
Chris@16
|
483 template <typename T>
|
Chris@16
|
484 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
|
Chris@16
|
485 internal_visit(T& lhs_content, int) const
|
Chris@16
|
486 {
|
Chris@16
|
487 // NOTE TO USER :
|
Chris@16
|
488 // Compile error here indicates one of variant's bounded types does
|
Chris@16
|
489 // not meet the requirements of the Assignable concept. Thus,
|
Chris@16
|
490 // variant is not Assignable.
|
Chris@16
|
491 //
|
Chris@16
|
492 // Hint: Are any of the bounded types const-qualified or references?
|
Chris@16
|
493 //
|
Chris@16
|
494 lhs_content = *static_cast< const T* >(rhs_storage_);
|
Chris@16
|
495 BOOST_VARIANT_AUX_RETURN_VOID;
|
Chris@16
|
496 }
|
Chris@16
|
497
|
Chris@16
|
498 };
|
Chris@16
|
499
|
Chris@16
|
500 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
501 // (detail) class move_storage
|
Chris@16
|
502 //
|
Chris@16
|
503 // Internal visitor that moves the given storage (which must be a
|
Chris@16
|
504 // constructed value of the same type) to the value it visits.
|
Chris@16
|
505 //
|
Chris@16
|
506 struct move_storage
|
Chris@16
|
507 : public static_visitor<>
|
Chris@16
|
508 {
|
Chris@16
|
509 private: // representation
|
Chris@16
|
510
|
Chris@16
|
511 void* rhs_storage_;
|
Chris@16
|
512
|
Chris@16
|
513 public: // structors
|
Chris@16
|
514
|
Chris@16
|
515 explicit move_storage(void* rhs_storage) BOOST_NOEXCEPT
|
Chris@16
|
516 : rhs_storage_(rhs_storage)
|
Chris@16
|
517 {
|
Chris@16
|
518 }
|
Chris@16
|
519
|
Chris@16
|
520 public: // internal visitor interfaces
|
Chris@16
|
521
|
Chris@16
|
522 template <typename T>
|
Chris@16
|
523 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
|
Chris@16
|
524 internal_visit(backup_holder<T>& lhs_content, long) const
|
Chris@16
|
525 {
|
Chris@16
|
526 lhs_content.get()
|
Chris@16
|
527 = ::boost::detail::variant::move(static_cast<backup_holder<T>* >(rhs_storage_)->get());
|
Chris@16
|
528 BOOST_VARIANT_AUX_RETURN_VOID;
|
Chris@16
|
529 }
|
Chris@16
|
530
|
Chris@16
|
531 template <typename T>
|
Chris@16
|
532 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
|
Chris@16
|
533 internal_visit(const backup_holder<T>& lhs_content, long) const
|
Chris@16
|
534 {
|
Chris@16
|
535 lhs_content.get()
|
Chris@16
|
536 = ::boost::detail::variant::move(static_cast<backup_holder<T>* >(rhs_storage_)->get());
|
Chris@16
|
537 BOOST_VARIANT_AUX_RETURN_VOID;
|
Chris@16
|
538 }
|
Chris@16
|
539
|
Chris@16
|
540 template <typename T>
|
Chris@16
|
541 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
|
Chris@16
|
542 internal_visit(T& lhs_content, int) const
|
Chris@16
|
543 {
|
Chris@16
|
544 // NOTE TO USER :
|
Chris@16
|
545 // Compile error here indicates one of variant's bounded types does
|
Chris@16
|
546 // not meet the requirements of the Assignable concept. Thus,
|
Chris@16
|
547 // variant is not Assignable.
|
Chris@16
|
548 //
|
Chris@16
|
549 // Hint: Are any of the bounded types const-qualified or references?
|
Chris@16
|
550 //
|
Chris@16
|
551 lhs_content = ::boost::detail::variant::move(*static_cast<T* >(rhs_storage_));
|
Chris@16
|
552 BOOST_VARIANT_AUX_RETURN_VOID;
|
Chris@16
|
553 }
|
Chris@16
|
554
|
Chris@16
|
555 };
|
Chris@16
|
556
|
Chris@16
|
557 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
558 // (detail) class direct_assigner
|
Chris@16
|
559 //
|
Chris@16
|
560 // Generic static visitor that: if and only if the visited value is of the
|
Chris@16
|
561 // specified type, assigns the given value to the visited value and returns
|
Chris@16
|
562 // true; else returns false.
|
Chris@16
|
563 //
|
Chris@16
|
564 template <typename T>
|
Chris@16
|
565 class direct_assigner
|
Chris@16
|
566 : public static_visitor<bool>
|
Chris@16
|
567 {
|
Chris@16
|
568 private: // representation
|
Chris@16
|
569
|
Chris@16
|
570 const T& rhs_;
|
Chris@16
|
571
|
Chris@16
|
572 public: // structors
|
Chris@16
|
573
|
Chris@16
|
574 explicit direct_assigner(const T& rhs) BOOST_NOEXCEPT
|
Chris@16
|
575 : rhs_(rhs)
|
Chris@16
|
576 {
|
Chris@16
|
577 }
|
Chris@16
|
578
|
Chris@16
|
579 public: // visitor interface
|
Chris@16
|
580
|
Chris@16
|
581 bool operator()(T& lhs)
|
Chris@16
|
582 {
|
Chris@16
|
583 lhs = rhs_;
|
Chris@16
|
584 return true;
|
Chris@16
|
585 }
|
Chris@16
|
586
|
Chris@16
|
587 template <typename U>
|
Chris@16
|
588 bool operator()(U&) BOOST_NOEXCEPT
|
Chris@16
|
589 {
|
Chris@16
|
590 return false;
|
Chris@16
|
591 }
|
Chris@16
|
592
|
Chris@16
|
593 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
|
Chris@16
|
594 private:
|
Chris@16
|
595 // silence MSVC warning C4512: assignment operator could not be generated
|
Chris@16
|
596 direct_assigner& operator= (direct_assigner const&);
|
Chris@16
|
597 #endif
|
Chris@16
|
598 };
|
Chris@16
|
599
|
Chris@16
|
600 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
601 // (detail) class direct_mover
|
Chris@16
|
602 //
|
Chris@16
|
603 // Generic static visitor that: if and only if the visited value is of the
|
Chris@16
|
604 // specified type, move assigns the given value to the visited value and returns
|
Chris@16
|
605 // true; else returns false.
|
Chris@16
|
606 //
|
Chris@16
|
607 template <typename T>
|
Chris@16
|
608 class direct_mover
|
Chris@16
|
609 : public static_visitor<bool>
|
Chris@16
|
610 {
|
Chris@16
|
611 private: // representation
|
Chris@16
|
612
|
Chris@16
|
613 T& rhs_;
|
Chris@16
|
614
|
Chris@16
|
615 public: // structors
|
Chris@16
|
616
|
Chris@16
|
617 explicit direct_mover(T& rhs) BOOST_NOEXCEPT
|
Chris@16
|
618 : rhs_(rhs)
|
Chris@16
|
619 {
|
Chris@16
|
620 }
|
Chris@16
|
621
|
Chris@16
|
622 public: // visitor interface
|
Chris@16
|
623
|
Chris@16
|
624 bool operator()(T& lhs)
|
Chris@16
|
625 {
|
Chris@16
|
626 lhs = ::boost::detail::variant::move(rhs_);
|
Chris@16
|
627 return true;
|
Chris@16
|
628 }
|
Chris@16
|
629
|
Chris@16
|
630 template <typename U>
|
Chris@16
|
631 bool operator()(U&) BOOST_NOEXCEPT
|
Chris@16
|
632 {
|
Chris@16
|
633 return false;
|
Chris@16
|
634 }
|
Chris@16
|
635
|
Chris@16
|
636 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
|
Chris@16
|
637 private:
|
Chris@16
|
638 // silence MSVC warning C4512: assignment operator could not be generated
|
Chris@16
|
639 direct_mover& operator= (direct_mover const&);
|
Chris@16
|
640 #endif
|
Chris@16
|
641 };
|
Chris@16
|
642
|
Chris@16
|
643
|
Chris@16
|
644 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
645 // (detail) class backup_assigner
|
Chris@16
|
646 //
|
Chris@16
|
647 // Internal visitor that "assigns" the given value to the visited value,
|
Chris@16
|
648 // using backup to recover if the destroy-copy sequence fails.
|
Chris@16
|
649 //
|
Chris@16
|
650 // NOTE: This needs to be a friend of variant, as it needs access to
|
Chris@16
|
651 // indicate_which, indicate_backup_which, etc.
|
Chris@16
|
652 //
|
Chris@16
|
653 template <typename Variant>
|
Chris@16
|
654 class backup_assigner
|
Chris@16
|
655 : public static_visitor<>
|
Chris@16
|
656 {
|
Chris@16
|
657 private: // representation
|
Chris@16
|
658
|
Chris@16
|
659 Variant& lhs_;
|
Chris@16
|
660 int rhs_which_;
|
Chris@16
|
661 const void* rhs_content_;
|
Chris@16
|
662 void (*copy_rhs_content_)(void*, const void*);
|
Chris@16
|
663
|
Chris@16
|
664 public: // structors
|
Chris@16
|
665
|
Chris@16
|
666 template<class RhsT>
|
Chris@16
|
667 backup_assigner(Variant& lhs, int rhs_which, const RhsT& rhs_content)
|
Chris@16
|
668 : lhs_(lhs)
|
Chris@16
|
669 , rhs_which_(rhs_which)
|
Chris@16
|
670 , rhs_content_(&rhs_content)
|
Chris@16
|
671 , copy_rhs_content_(&construct_impl<RhsT>)
|
Chris@16
|
672 {
|
Chris@16
|
673 }
|
Chris@16
|
674
|
Chris@16
|
675 private: // helpers, for visitor interface (below)
|
Chris@16
|
676
|
Chris@16
|
677 template<class RhsT>
|
Chris@16
|
678 static void construct_impl(void* addr, const void* obj)
|
Chris@16
|
679 {
|
Chris@16
|
680 new(addr) RhsT(*static_cast<const RhsT*>(obj));
|
Chris@16
|
681 }
|
Chris@16
|
682
|
Chris@16
|
683 template <typename LhsT>
|
Chris@16
|
684 void backup_assign_impl(
|
Chris@101
|
685 backup_holder<LhsT>& lhs_content
|
Chris@101
|
686 , mpl::false_ // is_nothrow_move_constructible
|
Chris@101
|
687 , long
|
Chris@101
|
688 )
|
Chris@101
|
689 {
|
Chris@101
|
690 // Move lhs content to backup...
|
Chris@101
|
691 backup_holder<LhsT> backup_lhs_content(0);
|
Chris@101
|
692 backup_lhs_content.swap(lhs_content); // nothrow
|
Chris@101
|
693
|
Chris@101
|
694 // ...destroy lhs content...
|
Chris@101
|
695 lhs_content.~backup_holder<LhsT>(); // nothrow
|
Chris@101
|
696
|
Chris@101
|
697 BOOST_TRY
|
Chris@101
|
698 {
|
Chris@101
|
699 // ...and attempt to copy rhs content into lhs storage:
|
Chris@101
|
700 copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
|
Chris@101
|
701 }
|
Chris@101
|
702 BOOST_CATCH (...)
|
Chris@101
|
703 {
|
Chris@101
|
704 // In case of failure, copy backup pointer to lhs storage...
|
Chris@101
|
705 new(lhs_.storage_.address())
|
Chris@101
|
706 backup_holder<LhsT>( 0 ); // nothrow
|
Chris@101
|
707
|
Chris@101
|
708 static_cast<backup_holder<LhsT>* >(lhs_.storage_.address())
|
Chris@101
|
709 ->swap(backup_lhs_content); // nothrow
|
Chris@101
|
710
|
Chris@101
|
711 // ...and rethrow:
|
Chris@101
|
712 BOOST_RETHROW;
|
Chris@101
|
713 }
|
Chris@101
|
714 BOOST_CATCH_END
|
Chris@101
|
715
|
Chris@101
|
716 // In case of success, indicate new content type:
|
Chris@101
|
717 lhs_.indicate_which(rhs_which_); // nothrow
|
Chris@101
|
718 }
|
Chris@101
|
719
|
Chris@101
|
720 template <typename LhsT>
|
Chris@101
|
721 void backup_assign_impl(
|
Chris@16
|
722 LhsT& lhs_content
|
Chris@16
|
723 , mpl::true_ // is_nothrow_move_constructible
|
Chris@101
|
724 , int
|
Chris@16
|
725 )
|
Chris@16
|
726 {
|
Chris@16
|
727 // Move lhs content to backup...
|
Chris@16
|
728 LhsT backup_lhs_content(
|
Chris@16
|
729 ::boost::detail::variant::move(lhs_content)
|
Chris@16
|
730 ); // nothrow
|
Chris@16
|
731
|
Chris@16
|
732 // ...destroy lhs content...
|
Chris@16
|
733 lhs_content.~LhsT(); // nothrow
|
Chris@16
|
734
|
Chris@16
|
735 BOOST_TRY
|
Chris@16
|
736 {
|
Chris@16
|
737 // ...and attempt to copy rhs content into lhs storage:
|
Chris@16
|
738 copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
|
Chris@16
|
739 }
|
Chris@16
|
740 BOOST_CATCH (...)
|
Chris@16
|
741 {
|
Chris@16
|
742 // In case of failure, restore backup content to lhs storage...
|
Chris@16
|
743 new(lhs_.storage_.address())
|
Chris@16
|
744 LhsT(
|
Chris@16
|
745 ::boost::detail::variant::move(backup_lhs_content)
|
Chris@16
|
746 ); // nothrow
|
Chris@16
|
747
|
Chris@16
|
748 // ...and rethrow:
|
Chris@16
|
749 BOOST_RETHROW;
|
Chris@16
|
750 }
|
Chris@16
|
751 BOOST_CATCH_END
|
Chris@16
|
752
|
Chris@16
|
753 // In case of success, indicate new content type:
|
Chris@16
|
754 lhs_.indicate_which(rhs_which_); // nothrow
|
Chris@16
|
755 }
|
Chris@16
|
756
|
Chris@16
|
757 template <typename LhsT>
|
Chris@16
|
758 void backup_assign_impl(
|
Chris@16
|
759 LhsT& lhs_content
|
Chris@16
|
760 , mpl::false_ // is_nothrow_move_constructible
|
Chris@101
|
761 , int
|
Chris@16
|
762 )
|
Chris@16
|
763 {
|
Chris@16
|
764 // Backup lhs content...
|
Chris@16
|
765 LhsT* backup_lhs_ptr = new LhsT(lhs_content);
|
Chris@16
|
766
|
Chris@16
|
767 // ...destroy lhs content...
|
Chris@16
|
768 lhs_content.~LhsT(); // nothrow
|
Chris@16
|
769
|
Chris@16
|
770 BOOST_TRY
|
Chris@16
|
771 {
|
Chris@16
|
772 // ...and attempt to copy rhs content into lhs storage:
|
Chris@16
|
773 copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
|
Chris@16
|
774 }
|
Chris@16
|
775 BOOST_CATCH (...)
|
Chris@16
|
776 {
|
Chris@16
|
777 // In case of failure, copy backup pointer to lhs storage...
|
Chris@16
|
778 new(lhs_.storage_.address())
|
Chris@16
|
779 backup_holder<LhsT>( backup_lhs_ptr ); // nothrow
|
Chris@16
|
780
|
Chris@16
|
781 // ...indicate now using backup...
|
Chris@16
|
782 lhs_.indicate_backup_which( lhs_.which() ); // nothrow
|
Chris@16
|
783
|
Chris@16
|
784 // ...and rethrow:
|
Chris@16
|
785 BOOST_RETHROW;
|
Chris@16
|
786 }
|
Chris@16
|
787 BOOST_CATCH_END
|
Chris@16
|
788
|
Chris@16
|
789 // In case of success, indicate new content type...
|
Chris@16
|
790 lhs_.indicate_which(rhs_which_); // nothrow
|
Chris@16
|
791
|
Chris@16
|
792 // ...and delete backup:
|
Chris@16
|
793 delete backup_lhs_ptr; // nothrow
|
Chris@16
|
794 }
|
Chris@16
|
795
|
Chris@16
|
796 public: // visitor interface
|
Chris@16
|
797
|
Chris@16
|
798 template <typename LhsT>
|
Chris@16
|
799 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
|
Chris@16
|
800 internal_visit(LhsT& lhs_content, int)
|
Chris@16
|
801 {
|
Chris@16
|
802 typedef typename is_nothrow_move_constructible<LhsT>::type
|
Chris@16
|
803 nothrow_move;
|
Chris@16
|
804
|
Chris@101
|
805 backup_assign_impl( lhs_content, nothrow_move(), 1L);
|
Chris@16
|
806
|
Chris@16
|
807 BOOST_VARIANT_AUX_RETURN_VOID;
|
Chris@16
|
808 }
|
Chris@16
|
809
|
Chris@16
|
810 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
|
Chris@16
|
811 private:
|
Chris@16
|
812 // silence MSVC warning C4512: assignment operator could not be generated
|
Chris@16
|
813 backup_assigner& operator= (backup_assigner const&);
|
Chris@16
|
814 #endif
|
Chris@16
|
815 };
|
Chris@16
|
816
|
Chris@16
|
817 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
818 // (detail) class swap_with
|
Chris@16
|
819 //
|
Chris@16
|
820 // Visitor that swaps visited value with content of given variant.
|
Chris@16
|
821 //
|
Chris@16
|
822 // Precondition: Given variant MUST have same logical type as visited value.
|
Chris@16
|
823 //
|
Chris@16
|
824 template <typename Variant>
|
Chris@16
|
825 struct swap_with
|
Chris@16
|
826 : public static_visitor<>
|
Chris@16
|
827 {
|
Chris@16
|
828 private: // representation
|
Chris@16
|
829
|
Chris@16
|
830 Variant& toswap_;
|
Chris@16
|
831
|
Chris@16
|
832 public: // structors
|
Chris@16
|
833
|
Chris@101
|
834 explicit swap_with(Variant& toswap) BOOST_NOEXCEPT
|
Chris@16
|
835 : toswap_(toswap)
|
Chris@16
|
836 {
|
Chris@16
|
837 }
|
Chris@16
|
838
|
Chris@16
|
839 public: // internal visitor interfaces
|
Chris@16
|
840
|
Chris@16
|
841 template <typename T>
|
Chris@16
|
842 void operator()(T& operand) const
|
Chris@16
|
843 {
|
Chris@16
|
844 // Since the precondition ensures types are same, get T...
|
Chris@16
|
845 known_get<T> getter;
|
Chris@16
|
846 T& other = toswap_.apply_visitor(getter);
|
Chris@16
|
847
|
Chris@16
|
848 // ...and swap:
|
Chris@16
|
849 ::boost::detail::variant::move_swap( operand, other );
|
Chris@16
|
850 }
|
Chris@16
|
851
|
Chris@16
|
852 private:
|
Chris@16
|
853 swap_with& operator=(const swap_with&);
|
Chris@16
|
854
|
Chris@16
|
855 };
|
Chris@16
|
856
|
Chris@16
|
857 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
858 // (detail) class reflect
|
Chris@16
|
859 //
|
Chris@16
|
860 // Generic static visitor that performs a typeid on the value it visits.
|
Chris@16
|
861 //
|
Chris@16
|
862
|
Chris@16
|
863 class reflect
|
Chris@101
|
864 : public static_visitor<const boost::typeindex::type_info&>
|
Chris@16
|
865 {
|
Chris@16
|
866 public: // visitor interfaces
|
Chris@16
|
867
|
Chris@16
|
868 template <typename T>
|
Chris@101
|
869 const boost::typeindex::type_info& operator()(const T&) const BOOST_NOEXCEPT
|
Chris@16
|
870 {
|
Chris@101
|
871 return boost::typeindex::type_id<T>().type_info();
|
Chris@16
|
872 }
|
Chris@16
|
873
|
Chris@16
|
874 };
|
Chris@16
|
875
|
Chris@16
|
876 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
877 // (detail) class comparer
|
Chris@16
|
878 //
|
Chris@16
|
879 // Generic static visitor that compares the content of the given lhs variant
|
Chris@16
|
880 // with the visited rhs content using Comp.
|
Chris@16
|
881 //
|
Chris@16
|
882 // Precondition: lhs.which() == rhs.which()
|
Chris@16
|
883 //
|
Chris@16
|
884 template <typename Variant, typename Comp>
|
Chris@16
|
885 class comparer
|
Chris@16
|
886 : public static_visitor<bool>
|
Chris@16
|
887 {
|
Chris@16
|
888 private: // representation
|
Chris@16
|
889
|
Chris@16
|
890 const Variant& lhs_;
|
Chris@16
|
891
|
Chris@16
|
892 public: // structors
|
Chris@16
|
893
|
Chris@16
|
894 explicit comparer(const Variant& lhs) BOOST_NOEXCEPT
|
Chris@16
|
895 : lhs_(lhs)
|
Chris@16
|
896 {
|
Chris@16
|
897 }
|
Chris@16
|
898
|
Chris@16
|
899 public: // visitor interfaces
|
Chris@16
|
900
|
Chris@16
|
901 template <typename T>
|
Chris@16
|
902 bool operator()(const T& rhs_content) const
|
Chris@16
|
903 {
|
Chris@16
|
904 // Since the precondition ensures lhs and rhs types are same, get T...
|
Chris@16
|
905 known_get<const T> getter;
|
Chris@16
|
906 const T& lhs_content = lhs_.apply_visitor(getter);
|
Chris@16
|
907
|
Chris@16
|
908 // ...and compare lhs and rhs contents:
|
Chris@16
|
909 return Comp()(lhs_content, rhs_content);
|
Chris@16
|
910 }
|
Chris@16
|
911
|
Chris@16
|
912 private:
|
Chris@16
|
913 comparer& operator=(const comparer&);
|
Chris@16
|
914
|
Chris@16
|
915 };
|
Chris@16
|
916
|
Chris@16
|
917 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
918 // (detail) class equal_comp
|
Chris@16
|
919 //
|
Chris@16
|
920 // Generic function object compares lhs with rhs using operator==.
|
Chris@16
|
921 //
|
Chris@16
|
922 struct equal_comp
|
Chris@16
|
923 {
|
Chris@16
|
924 template <typename T>
|
Chris@16
|
925 bool operator()(const T& lhs, const T& rhs) const
|
Chris@16
|
926 {
|
Chris@16
|
927 return lhs == rhs;
|
Chris@16
|
928 }
|
Chris@16
|
929 };
|
Chris@16
|
930
|
Chris@16
|
931 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
932 // (detail) class less_comp
|
Chris@16
|
933 //
|
Chris@16
|
934 // Generic function object compares lhs with rhs using operator<.
|
Chris@16
|
935 //
|
Chris@16
|
936 struct less_comp
|
Chris@16
|
937 {
|
Chris@16
|
938 template <typename T>
|
Chris@16
|
939 bool operator()(const T& lhs, const T& rhs) const
|
Chris@16
|
940 {
|
Chris@16
|
941 return lhs < rhs;
|
Chris@16
|
942 }
|
Chris@16
|
943 };
|
Chris@16
|
944
|
Chris@16
|
945 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
946 // (detail) class template invoke_visitor
|
Chris@16
|
947 //
|
Chris@16
|
948 // Internal visitor that invokes the given visitor using:
|
Chris@16
|
949 // * for wrappers (e.g., recursive_wrapper), the wrapper's held value.
|
Chris@16
|
950 // * for all other values, the value itself.
|
Chris@16
|
951 //
|
Chris@16
|
952 template <typename Visitor>
|
Chris@16
|
953 class invoke_visitor
|
Chris@16
|
954 {
|
Chris@16
|
955 private: // representation
|
Chris@16
|
956
|
Chris@16
|
957 Visitor& visitor_;
|
Chris@16
|
958
|
Chris@16
|
959 public: // visitor typedefs
|
Chris@16
|
960
|
Chris@16
|
961 typedef typename Visitor::result_type
|
Chris@16
|
962 result_type;
|
Chris@16
|
963
|
Chris@16
|
964 public: // structors
|
Chris@16
|
965
|
Chris@16
|
966 explicit invoke_visitor(Visitor& visitor) BOOST_NOEXCEPT
|
Chris@16
|
967 : visitor_(visitor)
|
Chris@16
|
968 {
|
Chris@16
|
969 }
|
Chris@16
|
970
|
Chris@16
|
971 #if !defined(BOOST_NO_VOID_RETURNS)
|
Chris@16
|
972
|
Chris@16
|
973 public: // internal visitor interfaces
|
Chris@16
|
974
|
Chris@16
|
975 template <typename T>
|
Chris@16
|
976 result_type internal_visit(T& operand, int)
|
Chris@16
|
977 {
|
Chris@16
|
978 return visitor_(operand);
|
Chris@16
|
979 }
|
Chris@16
|
980
|
Chris@16
|
981 # if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
|
Chris@16
|
982 template <typename T>
|
Chris@16
|
983 result_type internal_visit(const T& operand, int)
|
Chris@16
|
984 {
|
Chris@16
|
985 return visitor_(operand);
|
Chris@16
|
986 }
|
Chris@16
|
987 # endif
|
Chris@16
|
988
|
Chris@16
|
989 #else // defined(BOOST_NO_VOID_RETURNS)
|
Chris@16
|
990
|
Chris@16
|
991 private: // helpers, for internal visitor interfaces (below)
|
Chris@16
|
992
|
Chris@16
|
993 template <typename T>
|
Chris@16
|
994 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
|
Chris@16
|
995 visit_impl(T& operand, mpl::false_)
|
Chris@16
|
996 {
|
Chris@16
|
997 return visitor_(operand);
|
Chris@16
|
998 }
|
Chris@16
|
999
|
Chris@16
|
1000 template <typename T>
|
Chris@16
|
1001 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
|
Chris@16
|
1002 visit_impl(T& operand, mpl::true_)
|
Chris@16
|
1003 {
|
Chris@16
|
1004 visitor_(operand);
|
Chris@16
|
1005 BOOST_VARIANT_AUX_RETURN_VOID;
|
Chris@16
|
1006 }
|
Chris@16
|
1007
|
Chris@16
|
1008 public: // internal visitor interfaces
|
Chris@16
|
1009
|
Chris@16
|
1010 template <typename T>
|
Chris@16
|
1011 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
|
Chris@16
|
1012 internal_visit(T& operand, int)
|
Chris@16
|
1013 {
|
Chris@16
|
1014 typedef typename is_same<result_type, void>::type
|
Chris@16
|
1015 has_void_result_type;
|
Chris@16
|
1016
|
Chris@16
|
1017 return visit_impl(operand, has_void_result_type());
|
Chris@16
|
1018 }
|
Chris@16
|
1019
|
Chris@16
|
1020 #endif // BOOST_NO_VOID_RETURNS) workaround
|
Chris@16
|
1021
|
Chris@16
|
1022 public: // internal visitor interfaces, cont.
|
Chris@16
|
1023
|
Chris@16
|
1024 template <typename T>
|
Chris@16
|
1025 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
|
Chris@16
|
1026 internal_visit(boost::recursive_wrapper<T>& operand, long)
|
Chris@16
|
1027 {
|
Chris@16
|
1028 return internal_visit( operand.get(), 1L );
|
Chris@16
|
1029 }
|
Chris@16
|
1030
|
Chris@16
|
1031 template <typename T>
|
Chris@16
|
1032 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
|
Chris@16
|
1033 internal_visit(const boost::recursive_wrapper<T>& operand, long)
|
Chris@16
|
1034 {
|
Chris@16
|
1035 return internal_visit( operand.get(), 1L );
|
Chris@16
|
1036 }
|
Chris@16
|
1037
|
Chris@16
|
1038 template <typename T>
|
Chris@16
|
1039 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
|
Chris@16
|
1040 internal_visit(boost::detail::reference_content<T>& operand, long)
|
Chris@16
|
1041 {
|
Chris@16
|
1042 return internal_visit( operand.get(), 1L );
|
Chris@16
|
1043 }
|
Chris@16
|
1044
|
Chris@16
|
1045 template <typename T>
|
Chris@16
|
1046 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
|
Chris@16
|
1047 internal_visit(const boost::detail::reference_content<T>& operand, long)
|
Chris@16
|
1048 {
|
Chris@16
|
1049 return internal_visit( operand.get(), 1L );
|
Chris@16
|
1050 }
|
Chris@16
|
1051
|
Chris@16
|
1052 template <typename T>
|
Chris@16
|
1053 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
|
Chris@16
|
1054 internal_visit(boost::detail::variant::backup_holder<T>& operand, long)
|
Chris@16
|
1055 {
|
Chris@16
|
1056 return internal_visit( operand.get(), 1L );
|
Chris@16
|
1057 }
|
Chris@16
|
1058
|
Chris@16
|
1059 template <typename T>
|
Chris@16
|
1060 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
|
Chris@16
|
1061 internal_visit(const boost::detail::variant::backup_holder<T>& operand, long)
|
Chris@16
|
1062 {
|
Chris@16
|
1063 return internal_visit( operand.get(), 1L );
|
Chris@16
|
1064 }
|
Chris@16
|
1065
|
Chris@16
|
1066 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
|
Chris@16
|
1067 private:
|
Chris@16
|
1068 // silence MSVC warning C4512: assignment operator could not be generated
|
Chris@16
|
1069 invoke_visitor& operator= (invoke_visitor const&);
|
Chris@16
|
1070 #endif
|
Chris@16
|
1071 };
|
Chris@16
|
1072
|
Chris@16
|
1073 }} // namespace detail::variant
|
Chris@16
|
1074
|
Chris@16
|
1075 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
1076 // class template variant (concept inspired by Andrei Alexandrescu)
|
Chris@16
|
1077 //
|
Chris@16
|
1078 // See docs and boost/variant/variant_fwd.hpp for more information.
|
Chris@16
|
1079 //
|
Chris@16
|
1080 template <
|
Chris@16
|
1081 typename T0_
|
Chris@16
|
1082 , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename T)
|
Chris@16
|
1083 >
|
Chris@16
|
1084 class variant
|
Chris@16
|
1085 {
|
Chris@16
|
1086 private: // helpers, for typedefs (below)
|
Chris@16
|
1087
|
Chris@16
|
1088 typedef variant wknd_self_t;
|
Chris@16
|
1089
|
Chris@16
|
1090 struct is_recursive_
|
Chris@16
|
1091 : detail::variant::is_recursive_flag<T0_>
|
Chris@16
|
1092 {
|
Chris@16
|
1093 };
|
Chris@16
|
1094
|
Chris@16
|
1095 typedef typename mpl::eval_if<
|
Chris@16
|
1096 is_recursive_
|
Chris@16
|
1097 , T0_
|
Chris@16
|
1098 , mpl::identity< T0_ >
|
Chris@16
|
1099 >::type unwrapped_T0_;
|
Chris@16
|
1100
|
Chris@16
|
1101 struct is_sequence_based_
|
Chris@16
|
1102 : detail::variant::is_over_sequence<unwrapped_T0_>
|
Chris@16
|
1103 {
|
Chris@16
|
1104 };
|
Chris@16
|
1105
|
Chris@16
|
1106 #if !defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
|
Chris@16
|
1107
|
Chris@16
|
1108 private: // helpers, for typedefs (below)
|
Chris@16
|
1109
|
Chris@16
|
1110 typedef typename mpl::eval_if<
|
Chris@16
|
1111 is_sequence_based_
|
Chris@16
|
1112 , unwrapped_T0_ // over_sequence<...>::type
|
Chris@16
|
1113 , detail::variant::make_variant_list<
|
Chris@16
|
1114 unwrapped_T0_
|
Chris@16
|
1115 , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T)
|
Chris@16
|
1116 >
|
Chris@16
|
1117 >::type specified_types;
|
Chris@16
|
1118
|
Chris@16
|
1119 BOOST_STATIC_ASSERT((
|
Chris@16
|
1120 ::boost::mpl::not_< mpl::empty<specified_types> >::value
|
Chris@16
|
1121 ));
|
Chris@16
|
1122
|
Chris@16
|
1123 typedef typename mpl::eval_if<
|
Chris@16
|
1124 is_recursive_
|
Chris@16
|
1125 , mpl::transform<
|
Chris@16
|
1126 specified_types
|
Chris@16
|
1127 , mpl::protect<
|
Chris@16
|
1128 detail::variant::quoted_enable_recursive<wknd_self_t>
|
Chris@16
|
1129 >
|
Chris@16
|
1130 >
|
Chris@16
|
1131 , mpl::identity< specified_types >
|
Chris@16
|
1132 >::type recursive_enabled_types;
|
Chris@16
|
1133
|
Chris@16
|
1134 public: // public typedefs
|
Chris@16
|
1135
|
Chris@16
|
1136 typedef typename mpl::transform<
|
Chris@16
|
1137 recursive_enabled_types
|
Chris@16
|
1138 , unwrap_recursive<mpl::_1>
|
Chris@16
|
1139 >::type types;
|
Chris@16
|
1140
|
Chris@16
|
1141 private: // internal typedefs
|
Chris@16
|
1142
|
Chris@16
|
1143 typedef typename mpl::transform<
|
Chris@16
|
1144 recursive_enabled_types
|
Chris@16
|
1145 , mpl::protect< detail::make_reference_content<> >
|
Chris@16
|
1146 >::type internal_types;
|
Chris@16
|
1147
|
Chris@16
|
1148 typedef typename mpl::front<
|
Chris@16
|
1149 internal_types
|
Chris@16
|
1150 >::type internal_T0;
|
Chris@16
|
1151
|
Chris@16
|
1152 #else // defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
|
Chris@16
|
1153
|
Chris@16
|
1154 private: // helpers, for typedefs (below)
|
Chris@16
|
1155
|
Chris@16
|
1156 typedef unwrapped_T0_ T0;
|
Chris@16
|
1157
|
Chris@16
|
1158 #define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS(z,N,_) \
|
Chris@16
|
1159 typedef typename mpl::eval_if< \
|
Chris@16
|
1160 is_recursive_ \
|
Chris@16
|
1161 , detail::variant::enable_recursive< \
|
Chris@16
|
1162 BOOST_PP_CAT(T,N) \
|
Chris@16
|
1163 , wknd_self_t \
|
Chris@16
|
1164 > \
|
Chris@16
|
1165 , mpl::identity< BOOST_PP_CAT(T,N) > \
|
Chris@16
|
1166 >::type BOOST_PP_CAT(recursive_enabled_T,N); \
|
Chris@16
|
1167 /**/
|
Chris@16
|
1168
|
Chris@16
|
1169 BOOST_PP_REPEAT(
|
Chris@16
|
1170 BOOST_VARIANT_LIMIT_TYPES
|
Chris@16
|
1171 , BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
|
Chris@16
|
1172 , _
|
Chris@16
|
1173 )
|
Chris@16
|
1174
|
Chris@16
|
1175 #undef BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
|
Chris@16
|
1176
|
Chris@16
|
1177 #define BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS(z,N,_) \
|
Chris@16
|
1178 typedef typename unwrap_recursive< \
|
Chris@16
|
1179 BOOST_PP_CAT(recursive_enabled_T,N) \
|
Chris@16
|
1180 >::type BOOST_PP_CAT(public_T,N); \
|
Chris@16
|
1181 /**/
|
Chris@16
|
1182
|
Chris@16
|
1183 BOOST_PP_REPEAT(
|
Chris@16
|
1184 BOOST_VARIANT_LIMIT_TYPES
|
Chris@16
|
1185 , BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
|
Chris@16
|
1186 , _
|
Chris@16
|
1187 )
|
Chris@16
|
1188
|
Chris@16
|
1189 #undef BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
|
Chris@16
|
1190
|
Chris@16
|
1191 public: // public typedefs
|
Chris@16
|
1192
|
Chris@16
|
1193 typedef typename detail::variant::make_variant_list<
|
Chris@16
|
1194 BOOST_VARIANT_ENUM_PARAMS(public_T)
|
Chris@16
|
1195 >::type types;
|
Chris@16
|
1196
|
Chris@16
|
1197 private: // helpers, for internal typedefs (below)
|
Chris@16
|
1198
|
Chris@16
|
1199 #define BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS(z,N,_) \
|
Chris@16
|
1200 typedef detail::make_reference_content< \
|
Chris@16
|
1201 BOOST_PP_CAT(recursive_enabled_T,N) \
|
Chris@16
|
1202 >::type BOOST_PP_CAT(internal_T,N); \
|
Chris@16
|
1203 /**/
|
Chris@16
|
1204
|
Chris@16
|
1205 BOOST_PP_REPEAT(
|
Chris@16
|
1206 BOOST_VARIANT_LIMIT_TYPES
|
Chris@16
|
1207 , BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
|
Chris@16
|
1208 , _
|
Chris@16
|
1209 )
|
Chris@16
|
1210
|
Chris@16
|
1211 #undef BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
|
Chris@16
|
1212
|
Chris@16
|
1213 private: // internal typedefs
|
Chris@16
|
1214
|
Chris@16
|
1215 typedef typename detail::variant::make_variant_list<
|
Chris@16
|
1216 BOOST_VARIANT_ENUM_PARAMS(internal_T)
|
Chris@16
|
1217 >::type internal_types;
|
Chris@16
|
1218
|
Chris@16
|
1219 private: // static precondition assertions
|
Chris@16
|
1220
|
Chris@16
|
1221 // NOTE TO USER :
|
Chris@16
|
1222 // variant< type-sequence > syntax is not supported on this compiler!
|
Chris@16
|
1223 //
|
Chris@16
|
1224 BOOST_MPL_ASSERT_NOT(( is_sequence_based_ ));
|
Chris@16
|
1225
|
Chris@16
|
1226 #endif // BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT workaround
|
Chris@16
|
1227
|
Chris@16
|
1228 private: // helpers, for representation (below)
|
Chris@16
|
1229
|
Chris@16
|
1230 typedef typename detail::variant::find_fallback_type<
|
Chris@16
|
1231 internal_types
|
Chris@16
|
1232 >::type fallback_type_result_;
|
Chris@16
|
1233
|
Chris@16
|
1234 typedef typename fallback_type_result_::first
|
Chris@16
|
1235 fallback_type_index_;
|
Chris@16
|
1236 typedef typename fallback_type_result_::second
|
Chris@16
|
1237 fallback_type_;
|
Chris@16
|
1238
|
Chris@16
|
1239 struct has_fallback_type_
|
Chris@16
|
1240 : mpl::not_<
|
Chris@16
|
1241 is_same< fallback_type_, detail::variant::no_fallback_type >
|
Chris@16
|
1242 >
|
Chris@16
|
1243 {
|
Chris@16
|
1244 };
|
Chris@16
|
1245
|
Chris@16
|
1246 typedef has_fallback_type_
|
Chris@16
|
1247 never_uses_backup_flag;
|
Chris@16
|
1248
|
Chris@16
|
1249 typedef typename detail::variant::make_storage<
|
Chris@16
|
1250 internal_types, never_uses_backup_flag
|
Chris@16
|
1251 >::type storage_t;
|
Chris@16
|
1252
|
Chris@16
|
1253 #ifndef BOOST_NO_CXX11_NOEXCEPT
|
Chris@101
|
1254 typedef typename detail::variant::is_variant_move_noexcept_constructible<
|
Chris@16
|
1255 internal_types
|
Chris@101
|
1256 > variant_move_noexcept_constructible;
|
Chris@101
|
1257
|
Chris@101
|
1258 typedef typename detail::variant::is_variant_move_noexcept_assignable<
|
Chris@101
|
1259 internal_types
|
Chris@101
|
1260 > variant_move_noexcept_assignable;
|
Chris@101
|
1261
|
Chris@16
|
1262 #endif
|
Chris@16
|
1263
|
Chris@16
|
1264 private: // helpers, for representation (below)
|
Chris@16
|
1265
|
Chris@16
|
1266 // which_ on:
|
Chris@16
|
1267 // * [0, size<internal_types>) indicates stack content
|
Chris@16
|
1268 // * [-size<internal_types>, 0) indicates pointer to heap backup
|
Chris@16
|
1269 // if which_ >= 0:
|
Chris@16
|
1270 // * then which() -> which_
|
Chris@16
|
1271 // * else which() -> -(which_ + 1)
|
Chris@16
|
1272
|
Chris@16
|
1273 #if !defined(BOOST_VARIANT_MINIMIZE_SIZE)
|
Chris@16
|
1274
|
Chris@16
|
1275 typedef int which_t;
|
Chris@16
|
1276
|
Chris@16
|
1277 #else // defined(BOOST_VARIANT_MINIMIZE_SIZE)
|
Chris@16
|
1278
|
Chris@16
|
1279 // [if O1_size available, then attempt which_t size optimization...]
|
Chris@16
|
1280 // [select signed char if fewer than SCHAR_MAX types, else signed int:]
|
Chris@16
|
1281 typedef typename mpl::eval_if<
|
Chris@16
|
1282 mpl::equal_to< mpl::O1_size<internal_types>, mpl::long_<-1> >
|
Chris@16
|
1283 , mpl::identity< int >
|
Chris@16
|
1284 , mpl::if_<
|
Chris@16
|
1285 mpl::less< mpl::O1_size<internal_types>, mpl::int_<SCHAR_MAX> >
|
Chris@16
|
1286 , signed char
|
Chris@16
|
1287 , int
|
Chris@16
|
1288 >
|
Chris@16
|
1289 >::type which_t;
|
Chris@16
|
1290
|
Chris@16
|
1291 #endif // BOOST_VARIANT_MINIMIZE_SIZE switch
|
Chris@16
|
1292
|
Chris@16
|
1293 // representation -- private when possible
|
Chris@16
|
1294 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
Chris@16
|
1295 private:
|
Chris@16
|
1296 #else
|
Chris@16
|
1297 public:
|
Chris@16
|
1298 #endif
|
Chris@16
|
1299
|
Chris@16
|
1300 which_t which_;
|
Chris@16
|
1301 storage_t storage_;
|
Chris@16
|
1302
|
Chris@16
|
1303 void indicate_which(int which_arg) BOOST_NOEXCEPT
|
Chris@16
|
1304 {
|
Chris@16
|
1305 which_ = static_cast<which_t>( which_arg );
|
Chris@16
|
1306 }
|
Chris@16
|
1307
|
Chris@16
|
1308 void indicate_backup_which(int which_arg) BOOST_NOEXCEPT
|
Chris@16
|
1309 {
|
Chris@16
|
1310 which_ = static_cast<which_t>( -(which_arg + 1) );
|
Chris@16
|
1311 }
|
Chris@16
|
1312
|
Chris@16
|
1313 private: // helpers, for queries (below)
|
Chris@16
|
1314
|
Chris@16
|
1315 bool using_backup() const BOOST_NOEXCEPT
|
Chris@16
|
1316 {
|
Chris@16
|
1317 return which_ < 0;
|
Chris@16
|
1318 }
|
Chris@16
|
1319
|
Chris@16
|
1320 public: // queries
|
Chris@16
|
1321
|
Chris@16
|
1322 int which() const BOOST_NOEXCEPT
|
Chris@16
|
1323 {
|
Chris@16
|
1324 // If using heap backup...
|
Chris@16
|
1325 if (using_backup())
|
Chris@16
|
1326 // ...then return adjusted which_:
|
Chris@16
|
1327 return -(which_ + 1);
|
Chris@16
|
1328
|
Chris@16
|
1329 // Otherwise, return which_ directly:
|
Chris@16
|
1330 return which_;
|
Chris@16
|
1331 }
|
Chris@16
|
1332
|
Chris@16
|
1333 private: // helpers, for structors (below)
|
Chris@16
|
1334
|
Chris@16
|
1335 struct initializer
|
Chris@16
|
1336 : BOOST_VARIANT_AUX_INITIALIZER_T(
|
Chris@16
|
1337 recursive_enabled_types, recursive_enabled_T
|
Chris@16
|
1338 )
|
Chris@16
|
1339 {
|
Chris@16
|
1340 };
|
Chris@16
|
1341
|
Chris@101
|
1342 void destroy_content() BOOST_NOEXCEPT
|
Chris@16
|
1343 {
|
Chris@16
|
1344 detail::variant::destroyer visitor;
|
Chris@16
|
1345 this->internal_apply_visitor(visitor);
|
Chris@16
|
1346 }
|
Chris@16
|
1347
|
Chris@16
|
1348 public: // structors
|
Chris@16
|
1349
|
Chris@16
|
1350 ~variant() BOOST_NOEXCEPT
|
Chris@16
|
1351 {
|
Chris@16
|
1352 destroy_content();
|
Chris@16
|
1353 }
|
Chris@16
|
1354
|
Chris@101
|
1355 variant() BOOST_NOEXCEPT_IF(boost::has_nothrow_constructor<internal_T0>::value)
|
Chris@16
|
1356 {
|
Chris@101
|
1357 #ifdef _MSC_VER
|
Chris@101
|
1358 #pragma warning( push )
|
Chris@101
|
1359 // behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized
|
Chris@101
|
1360 #pragma warning( disable : 4345 )
|
Chris@101
|
1361 #endif
|
Chris@16
|
1362 // NOTE TO USER :
|
Chris@16
|
1363 // Compile error from here indicates that the first bound
|
Chris@16
|
1364 // type is not default-constructible, and so variant cannot
|
Chris@16
|
1365 // support its own default-construction.
|
Chris@16
|
1366 //
|
Chris@16
|
1367 new( storage_.address() ) internal_T0();
|
Chris@16
|
1368 indicate_which(0); // zero is the index of the first bounded type
|
Chris@101
|
1369 #ifdef _MSC_VER
|
Chris@101
|
1370 #pragma warning( pop )
|
Chris@101
|
1371 #endif
|
Chris@16
|
1372 }
|
Chris@16
|
1373
|
Chris@16
|
1374 private: // helpers, for structors, cont. (below)
|
Chris@16
|
1375
|
Chris@16
|
1376 class convert_copy_into
|
Chris@16
|
1377 : public static_visitor<int>
|
Chris@16
|
1378 {
|
Chris@16
|
1379 private: // representation
|
Chris@16
|
1380
|
Chris@16
|
1381 void* storage_;
|
Chris@16
|
1382
|
Chris@16
|
1383 public: // structors
|
Chris@16
|
1384
|
Chris@16
|
1385 explicit convert_copy_into(void* storage) BOOST_NOEXCEPT
|
Chris@16
|
1386 : storage_(storage)
|
Chris@16
|
1387 {
|
Chris@16
|
1388 }
|
Chris@16
|
1389
|
Chris@16
|
1390 public: // internal visitor interfaces (below)
|
Chris@16
|
1391
|
Chris@16
|
1392 template <typename T>
|
Chris@16
|
1393 int internal_visit(T& operand, int) const
|
Chris@16
|
1394 {
|
Chris@16
|
1395 // NOTE TO USER :
|
Chris@16
|
1396 // Compile error here indicates one of the source variant's types
|
Chris@16
|
1397 // cannot be unambiguously converted to the destination variant's
|
Chris@16
|
1398 // types (or that no conversion exists).
|
Chris@16
|
1399 //
|
Chris@16
|
1400 return initializer::initialize(storage_, operand);
|
Chris@16
|
1401 }
|
Chris@16
|
1402
|
Chris@16
|
1403 # if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
|
Chris@16
|
1404 template <typename T>
|
Chris@16
|
1405 result_type internal_visit(const T& operand, int) const
|
Chris@16
|
1406 {
|
Chris@16
|
1407 return initializer::initialize(storage_, operand);
|
Chris@16
|
1408 }
|
Chris@16
|
1409 # endif
|
Chris@16
|
1410
|
Chris@16
|
1411 template <typename T>
|
Chris@16
|
1412 int internal_visit(boost::detail::reference_content<T>& operand, long) const
|
Chris@16
|
1413 {
|
Chris@16
|
1414 return internal_visit( operand.get(), 1L );
|
Chris@16
|
1415 }
|
Chris@16
|
1416
|
Chris@16
|
1417 template <typename T>
|
Chris@16
|
1418 int internal_visit(const boost::detail::reference_content<T>& operand, long) const
|
Chris@16
|
1419 {
|
Chris@16
|
1420 return internal_visit( operand.get(), 1L );
|
Chris@16
|
1421 }
|
Chris@16
|
1422
|
Chris@16
|
1423 template <typename T>
|
Chris@16
|
1424 int internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
|
Chris@16
|
1425 {
|
Chris@16
|
1426 return internal_visit( operand.get(), 1L );
|
Chris@16
|
1427 }
|
Chris@16
|
1428
|
Chris@16
|
1429 template <typename T>
|
Chris@16
|
1430 int internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
|
Chris@16
|
1431 {
|
Chris@16
|
1432 return internal_visit( operand.get(), 1L );
|
Chris@16
|
1433 }
|
Chris@16
|
1434
|
Chris@16
|
1435 template <typename T>
|
Chris@16
|
1436 int internal_visit(boost::recursive_wrapper<T>& operand, long) const
|
Chris@16
|
1437 {
|
Chris@16
|
1438 return internal_visit( operand.get(), 1L );
|
Chris@16
|
1439 }
|
Chris@16
|
1440
|
Chris@16
|
1441 template <typename T>
|
Chris@16
|
1442 int internal_visit(const boost::recursive_wrapper<T>& operand, long) const
|
Chris@16
|
1443 {
|
Chris@16
|
1444 return internal_visit( operand.get(), 1L );
|
Chris@16
|
1445 }
|
Chris@16
|
1446
|
Chris@16
|
1447 };
|
Chris@16
|
1448
|
Chris@16
|
1449 friend class convert_copy_into;
|
Chris@16
|
1450
|
Chris@16
|
1451 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
1452 class convert_move_into
|
Chris@16
|
1453 : public static_visitor<int>
|
Chris@16
|
1454 {
|
Chris@16
|
1455 private: // representation
|
Chris@16
|
1456
|
Chris@16
|
1457 void* storage_;
|
Chris@16
|
1458
|
Chris@16
|
1459 public: // structors
|
Chris@16
|
1460
|
Chris@16
|
1461 explicit convert_move_into(void* storage) BOOST_NOEXCEPT
|
Chris@16
|
1462 : storage_(storage)
|
Chris@16
|
1463 {
|
Chris@16
|
1464 }
|
Chris@16
|
1465
|
Chris@16
|
1466 public: // internal visitor interfaces (below)
|
Chris@16
|
1467
|
Chris@16
|
1468 template <typename T>
|
Chris@16
|
1469 int internal_visit(T& operand, int) const
|
Chris@16
|
1470 {
|
Chris@16
|
1471 // NOTE TO USER :
|
Chris@16
|
1472 // Compile error here indicates one of the source variant's types
|
Chris@16
|
1473 // cannot be unambiguously converted to the destination variant's
|
Chris@16
|
1474 // types (or that no conversion exists).
|
Chris@16
|
1475 //
|
Chris@16
|
1476 return initializer::initialize(storage_, detail::variant::move(operand) );
|
Chris@16
|
1477 }
|
Chris@16
|
1478
|
Chris@16
|
1479 template <typename T>
|
Chris@16
|
1480 int internal_visit(boost::detail::reference_content<T>& operand, long) const
|
Chris@16
|
1481 {
|
Chris@16
|
1482 return internal_visit( operand.get(), 1L );
|
Chris@16
|
1483 }
|
Chris@16
|
1484
|
Chris@16
|
1485 template <typename T>
|
Chris@16
|
1486 int internal_visit(const boost::detail::reference_content<T>& operand, long) const
|
Chris@16
|
1487 {
|
Chris@16
|
1488 return internal_visit( operand.get(), 1L );
|
Chris@16
|
1489 }
|
Chris@16
|
1490
|
Chris@16
|
1491 template <typename T>
|
Chris@16
|
1492 int internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
|
Chris@16
|
1493 {
|
Chris@16
|
1494 return internal_visit( operand.get(), 1L );
|
Chris@16
|
1495 }
|
Chris@16
|
1496
|
Chris@16
|
1497 template <typename T>
|
Chris@16
|
1498 int internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
|
Chris@16
|
1499 {
|
Chris@16
|
1500 return internal_visit( operand.get(), 1L );
|
Chris@16
|
1501 }
|
Chris@16
|
1502
|
Chris@16
|
1503 template <typename T>
|
Chris@16
|
1504 int internal_visit(boost::recursive_wrapper<T>& operand, long) const
|
Chris@16
|
1505 {
|
Chris@16
|
1506 return internal_visit( operand.get(), 1L );
|
Chris@16
|
1507 }
|
Chris@16
|
1508
|
Chris@16
|
1509 template <typename T>
|
Chris@16
|
1510 int internal_visit(const boost::recursive_wrapper<T>& operand, long) const
|
Chris@16
|
1511 {
|
Chris@16
|
1512 return internal_visit( operand.get(), 1L );
|
Chris@16
|
1513 }
|
Chris@16
|
1514 };
|
Chris@16
|
1515
|
Chris@16
|
1516 friend class convert_move_into;
|
Chris@16
|
1517 #endif
|
Chris@16
|
1518
|
Chris@16
|
1519 private: // helpers, for structors, below
|
Chris@16
|
1520
|
Chris@16
|
1521 template <typename T>
|
Chris@16
|
1522 void convert_construct(
|
Chris@16
|
1523 T& operand
|
Chris@16
|
1524 , int
|
Chris@16
|
1525 , mpl::false_ = mpl::false_() // is_foreign_variant
|
Chris@16
|
1526 )
|
Chris@16
|
1527 {
|
Chris@16
|
1528 // NOTE TO USER :
|
Chris@16
|
1529 // Compile error here indicates that the given type is not
|
Chris@16
|
1530 // unambiguously convertible to one of the variant's types
|
Chris@16
|
1531 // (or that no conversion exists).
|
Chris@16
|
1532 //
|
Chris@16
|
1533 indicate_which(
|
Chris@16
|
1534 initializer::initialize(
|
Chris@16
|
1535 storage_.address()
|
Chris@16
|
1536 , operand
|
Chris@16
|
1537 )
|
Chris@16
|
1538 );
|
Chris@16
|
1539 }
|
Chris@16
|
1540
|
Chris@16
|
1541 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
1542 template <typename T>
|
Chris@16
|
1543 typename boost::enable_if<boost::is_rvalue_reference<T&&> >::type convert_construct(
|
Chris@16
|
1544 T&& operand
|
Chris@16
|
1545 , int
|
Chris@16
|
1546 , mpl::false_ = mpl::false_() // is_foreign_variant
|
Chris@16
|
1547 )
|
Chris@16
|
1548 {
|
Chris@16
|
1549 // NOTE TO USER :
|
Chris@16
|
1550 // Compile error here indicates that the given type is not
|
Chris@16
|
1551 // unambiguously convertible to one of the variant's types
|
Chris@16
|
1552 // (or that no conversion exists).
|
Chris@16
|
1553 //
|
Chris@16
|
1554 indicate_which(
|
Chris@16
|
1555 initializer::initialize(
|
Chris@16
|
1556 storage_.address()
|
Chris@16
|
1557 , detail::variant::move(operand)
|
Chris@16
|
1558 )
|
Chris@16
|
1559 );
|
Chris@16
|
1560 }
|
Chris@16
|
1561 #endif
|
Chris@16
|
1562
|
Chris@16
|
1563 template <typename Variant>
|
Chris@16
|
1564 void convert_construct(
|
Chris@16
|
1565 Variant& operand
|
Chris@16
|
1566 , long
|
Chris@16
|
1567 , mpl::true_// is_foreign_variant
|
Chris@16
|
1568 )
|
Chris@16
|
1569 {
|
Chris@16
|
1570 convert_copy_into visitor(storage_.address());
|
Chris@16
|
1571 indicate_which(
|
Chris@16
|
1572 operand.internal_apply_visitor(visitor)
|
Chris@16
|
1573 );
|
Chris@16
|
1574 }
|
Chris@16
|
1575
|
Chris@16
|
1576 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
1577 template <typename Variant>
|
Chris@16
|
1578 typename boost::enable_if<boost::is_rvalue_reference<Variant&&> >::type convert_construct(
|
Chris@16
|
1579 Variant&& operand
|
Chris@16
|
1580 , long
|
Chris@16
|
1581 , mpl::true_// is_foreign_variant
|
Chris@16
|
1582 )
|
Chris@16
|
1583 {
|
Chris@16
|
1584 convert_move_into visitor(storage_.address());
|
Chris@16
|
1585 indicate_which(
|
Chris@16
|
1586 operand.internal_apply_visitor(visitor)
|
Chris@16
|
1587 );
|
Chris@16
|
1588 }
|
Chris@16
|
1589 #endif
|
Chris@16
|
1590
|
Chris@16
|
1591 template <typename Variant>
|
Chris@16
|
1592 void convert_construct_variant(Variant& operand)
|
Chris@16
|
1593 {
|
Chris@16
|
1594 // [Determine if the given variant is itself a bounded type, or if its
|
Chris@16
|
1595 // content needs to be converted (i.e., it is a 'foreign' variant):]
|
Chris@16
|
1596 //
|
Chris@16
|
1597
|
Chris@16
|
1598 typedef typename mpl::find_if<
|
Chris@16
|
1599 types
|
Chris@16
|
1600 , is_same<
|
Chris@16
|
1601 add_const<mpl::_1>
|
Chris@16
|
1602 , const Variant
|
Chris@16
|
1603 >
|
Chris@16
|
1604 >::type found_it;
|
Chris@16
|
1605
|
Chris@16
|
1606 typedef typename mpl::end<types>::type not_found;
|
Chris@16
|
1607 typedef typename is_same<
|
Chris@16
|
1608 found_it, not_found
|
Chris@16
|
1609 >::type is_foreign_variant;
|
Chris@16
|
1610
|
Chris@16
|
1611 // Convert construct from operand:
|
Chris@16
|
1612 convert_construct(
|
Chris@16
|
1613 operand, 1L
|
Chris@16
|
1614 , is_foreign_variant()
|
Chris@16
|
1615 );
|
Chris@16
|
1616 }
|
Chris@16
|
1617
|
Chris@16
|
1618 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
1619 template <typename Variant>
|
Chris@16
|
1620 typename boost::enable_if<boost::is_rvalue_reference<Variant&&> >::type convert_construct_variant(Variant&& operand)
|
Chris@16
|
1621 {
|
Chris@16
|
1622 // [Determine if the given variant is itself a bounded type, or if its
|
Chris@16
|
1623 // content needs to be converted (i.e., it is a 'foreign' variant):]
|
Chris@16
|
1624 //
|
Chris@16
|
1625
|
Chris@16
|
1626 typedef typename mpl::find_if<
|
Chris@16
|
1627 types
|
Chris@16
|
1628 , is_same<
|
Chris@16
|
1629 add_const<mpl::_1>
|
Chris@16
|
1630 , const Variant
|
Chris@16
|
1631 >
|
Chris@16
|
1632 >::type found_it;
|
Chris@16
|
1633
|
Chris@16
|
1634 typedef typename mpl::end<types>::type not_found;
|
Chris@16
|
1635 typedef typename is_same<
|
Chris@16
|
1636 found_it, not_found
|
Chris@16
|
1637 >::type is_foreign_variant;
|
Chris@16
|
1638
|
Chris@16
|
1639 // Convert move construct from operand:
|
Chris@16
|
1640 convert_construct(
|
Chris@16
|
1641 detail::variant::move(operand), 1L
|
Chris@16
|
1642 , is_foreign_variant()
|
Chris@16
|
1643 );
|
Chris@16
|
1644 }
|
Chris@16
|
1645 #endif
|
Chris@16
|
1646
|
Chris@16
|
1647 template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
|
Chris@16
|
1648 void convert_construct(
|
Chris@16
|
1649 boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
|
Chris@16
|
1650 , long
|
Chris@16
|
1651 )
|
Chris@16
|
1652 {
|
Chris@16
|
1653 convert_construct_variant(operand);
|
Chris@16
|
1654 }
|
Chris@16
|
1655
|
Chris@16
|
1656 template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
|
Chris@16
|
1657 void convert_construct(
|
Chris@16
|
1658 const boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
|
Chris@16
|
1659 , long
|
Chris@16
|
1660 )
|
Chris@16
|
1661 {
|
Chris@16
|
1662 convert_construct_variant(operand);
|
Chris@16
|
1663 }
|
Chris@16
|
1664
|
Chris@16
|
1665 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
1666 template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
|
Chris@16
|
1667 void convert_construct(
|
Chris@16
|
1668 boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>&& operand
|
Chris@16
|
1669 , long
|
Chris@16
|
1670 )
|
Chris@16
|
1671 {
|
Chris@16
|
1672 convert_construct_variant( detail::variant::move(operand) );
|
Chris@16
|
1673 }
|
Chris@16
|
1674 #endif
|
Chris@16
|
1675
|
Chris@16
|
1676 public: // structors, cont.
|
Chris@16
|
1677
|
Chris@16
|
1678 #if !defined(BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING)
|
Chris@16
|
1679
|
Chris@16
|
1680 template <typename T>
|
Chris@16
|
1681 variant(const T& operand)
|
Chris@16
|
1682 {
|
Chris@16
|
1683 convert_construct(operand, 1L);
|
Chris@16
|
1684 }
|
Chris@16
|
1685
|
Chris@16
|
1686 template <typename T>
|
Chris@16
|
1687 variant(T& operand)
|
Chris@16
|
1688 {
|
Chris@16
|
1689 convert_construct(operand, 1L);
|
Chris@16
|
1690 }
|
Chris@16
|
1691
|
Chris@16
|
1692 #elif defined(BOOST_VARIANT_AUX_HAS_CONSTRUCTOR_TEMPLATE_ORDERING_SFINAE_WKND)
|
Chris@16
|
1693
|
Chris@16
|
1694 // For compilers that cannot distinguish between T& and const T& in
|
Chris@16
|
1695 // template constructors, but do fully support SFINAE, we can workaround:
|
Chris@16
|
1696
|
Chris@16
|
1697 template <typename T>
|
Chris@16
|
1698 variant(const T& operand)
|
Chris@16
|
1699 {
|
Chris@16
|
1700 convert_construct(operand, 1L);
|
Chris@16
|
1701 }
|
Chris@16
|
1702
|
Chris@16
|
1703 template <typename T>
|
Chris@16
|
1704 variant(
|
Chris@16
|
1705 T& operand
|
Chris@16
|
1706 , typename enable_if<
|
Chris@16
|
1707 mpl::not_< is_const<T> >
|
Chris@16
|
1708 , void
|
Chris@16
|
1709 >::type* = 0
|
Chris@16
|
1710 )
|
Chris@16
|
1711 {
|
Chris@16
|
1712 convert_construct(operand, 1L);
|
Chris@16
|
1713 }
|
Chris@16
|
1714
|
Chris@16
|
1715 #else // !defined(BOOST_VARIANT_AUX_HAS_CONSTRUCTOR_TEMPLATE_ORDERING_SFINAE_WKND)
|
Chris@16
|
1716
|
Chris@16
|
1717 // For compilers that cannot distinguish between T& and const T& in
|
Chris@16
|
1718 // template constructors, and do NOT support SFINAE, we can't workaround:
|
Chris@16
|
1719
|
Chris@16
|
1720 template <typename T>
|
Chris@16
|
1721 variant(const T& operand)
|
Chris@16
|
1722 {
|
Chris@16
|
1723 convert_construct(operand, 1L);
|
Chris@16
|
1724 }
|
Chris@16
|
1725 #endif // BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING workarounds
|
Chris@16
|
1726
|
Chris@16
|
1727 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
1728 template <class T>
|
Chris@16
|
1729 variant(T&& operand, typename boost::enable_if<boost::is_rvalue_reference<T&&> >::type* = 0,
|
Chris@16
|
1730 typename boost::disable_if<boost::is_const<T> >::type* = 0)
|
Chris@16
|
1731 {
|
Chris@16
|
1732 convert_construct( detail::variant::move(operand), 1L);
|
Chris@16
|
1733 }
|
Chris@16
|
1734 #endif
|
Chris@16
|
1735
|
Chris@16
|
1736 public: // structors, cont.
|
Chris@16
|
1737
|
Chris@16
|
1738 // [MSVC6 requires copy constructor appear after template constructors]
|
Chris@16
|
1739 variant(const variant& operand)
|
Chris@16
|
1740 {
|
Chris@16
|
1741 // Copy the value of operand into *this...
|
Chris@16
|
1742 detail::variant::copy_into visitor( storage_.address() );
|
Chris@16
|
1743 operand.internal_apply_visitor(visitor);
|
Chris@16
|
1744
|
Chris@16
|
1745 // ...and activate the *this's primary storage on success:
|
Chris@16
|
1746 indicate_which(operand.which());
|
Chris@16
|
1747 }
|
Chris@16
|
1748
|
Chris@16
|
1749 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@101
|
1750 variant(variant&& operand) BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value)
|
Chris@16
|
1751 {
|
Chris@16
|
1752 // Move the value of operand into *this...
|
Chris@16
|
1753 detail::variant::move_into visitor( storage_.address() );
|
Chris@16
|
1754 operand.internal_apply_visitor(visitor);
|
Chris@16
|
1755
|
Chris@16
|
1756 // ...and activate the *this's primary storage on success:
|
Chris@16
|
1757 indicate_which(operand.which());
|
Chris@16
|
1758 }
|
Chris@16
|
1759 #endif
|
Chris@16
|
1760
|
Chris@16
|
1761 private: // helpers, for modifiers (below)
|
Chris@16
|
1762
|
Chris@16
|
1763 # if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
Chris@16
|
1764 template <typename Variant>
|
Chris@16
|
1765 friend class detail::variant::backup_assigner;
|
Chris@16
|
1766 # endif
|
Chris@16
|
1767
|
Chris@16
|
1768 // class assigner
|
Chris@16
|
1769 //
|
Chris@16
|
1770 // Internal visitor that "assigns" the visited value to the given variant
|
Chris@16
|
1771 // by appropriate destruction and copy-construction.
|
Chris@16
|
1772 //
|
Chris@16
|
1773
|
Chris@16
|
1774 class assigner
|
Chris@16
|
1775 : public static_visitor<>
|
Chris@16
|
1776 {
|
Chris@101
|
1777 protected: // representation
|
Chris@16
|
1778
|
Chris@16
|
1779 variant& lhs_;
|
Chris@101
|
1780 const int rhs_which_;
|
Chris@16
|
1781
|
Chris@16
|
1782 public: // structors
|
Chris@16
|
1783
|
Chris@16
|
1784 assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT
|
Chris@16
|
1785 : lhs_(lhs)
|
Chris@16
|
1786 , rhs_which_(rhs_which)
|
Chris@16
|
1787 {
|
Chris@16
|
1788 }
|
Chris@16
|
1789
|
Chris@101
|
1790 protected: // helpers, for internal visitor interface (below)
|
Chris@16
|
1791
|
Chris@16
|
1792 template <typename RhsT, typename B1, typename B2>
|
Chris@16
|
1793 void assign_impl(
|
Chris@16
|
1794 const RhsT& rhs_content
|
Chris@16
|
1795 , mpl::true_ // has_nothrow_copy
|
Chris@16
|
1796 , B1 // is_nothrow_move_constructible
|
Chris@16
|
1797 , B2 // has_fallback_type
|
Chris@101
|
1798 ) const BOOST_NOEXCEPT
|
Chris@16
|
1799 {
|
Chris@16
|
1800 // Destroy lhs's content...
|
Chris@16
|
1801 lhs_.destroy_content(); // nothrow
|
Chris@16
|
1802
|
Chris@16
|
1803 // ...copy rhs content into lhs's storage...
|
Chris@16
|
1804 new(lhs_.storage_.address())
|
Chris@16
|
1805 RhsT( rhs_content ); // nothrow
|
Chris@16
|
1806
|
Chris@16
|
1807 // ...and indicate new content type:
|
Chris@16
|
1808 lhs_.indicate_which(rhs_which_); // nothrow
|
Chris@16
|
1809 }
|
Chris@16
|
1810
|
Chris@16
|
1811 template <typename RhsT, typename B>
|
Chris@16
|
1812 void assign_impl(
|
Chris@16
|
1813 const RhsT& rhs_content
|
Chris@16
|
1814 , mpl::false_ // has_nothrow_copy
|
Chris@16
|
1815 , mpl::true_ // is_nothrow_move_constructible
|
Chris@16
|
1816 , B // has_fallback_type
|
Chris@101
|
1817 ) const
|
Chris@16
|
1818 {
|
Chris@16
|
1819 // Attempt to make a temporary copy (so as to move it below)...
|
Chris@16
|
1820 RhsT temp(rhs_content);
|
Chris@16
|
1821
|
Chris@16
|
1822 // ...and upon success destroy lhs's content...
|
Chris@16
|
1823 lhs_.destroy_content(); // nothrow
|
Chris@16
|
1824
|
Chris@16
|
1825 // ...move the temporary copy into lhs's storage...
|
Chris@16
|
1826 new(lhs_.storage_.address())
|
Chris@16
|
1827 RhsT( detail::variant::move(temp) ); // nothrow
|
Chris@16
|
1828
|
Chris@16
|
1829 // ...and indicate new content type:
|
Chris@16
|
1830 lhs_.indicate_which(rhs_which_); // nothrow
|
Chris@16
|
1831 }
|
Chris@16
|
1832
|
Chris@101
|
1833 void construct_fallback() const BOOST_NOEXCEPT {
|
Chris@101
|
1834 // In case of failure, default-construct fallback type in lhs's storage...
|
Chris@101
|
1835 new (lhs_.storage_.address())
|
Chris@101
|
1836 fallback_type_; // nothrow
|
Chris@101
|
1837
|
Chris@101
|
1838 // ...indicate construction of fallback type...
|
Chris@101
|
1839 lhs_.indicate_which(
|
Chris@101
|
1840 BOOST_MPL_AUX_VALUE_WKND(fallback_type_index_)::value
|
Chris@101
|
1841 ); // nothrow
|
Chris@101
|
1842 }
|
Chris@101
|
1843
|
Chris@16
|
1844 template <typename RhsT>
|
Chris@16
|
1845 void assign_impl(
|
Chris@16
|
1846 const RhsT& rhs_content
|
Chris@16
|
1847 , mpl::false_ // has_nothrow_copy
|
Chris@16
|
1848 , mpl::false_ // is_nothrow_move_constructible
|
Chris@16
|
1849 , mpl::true_ // has_fallback_type
|
Chris@101
|
1850 ) const
|
Chris@16
|
1851 {
|
Chris@16
|
1852 // Destroy lhs's content...
|
Chris@16
|
1853 lhs_.destroy_content(); // nothrow
|
Chris@16
|
1854
|
Chris@16
|
1855 BOOST_TRY
|
Chris@16
|
1856 {
|
Chris@16
|
1857 // ...and attempt to copy rhs's content into lhs's storage:
|
Chris@16
|
1858 new(lhs_.storage_.address())
|
Chris@16
|
1859 RhsT( rhs_content );
|
Chris@16
|
1860 }
|
Chris@16
|
1861 BOOST_CATCH (...)
|
Chris@16
|
1862 {
|
Chris@101
|
1863 construct_fallback();
|
Chris@16
|
1864
|
Chris@16
|
1865 // ...and rethrow:
|
Chris@16
|
1866 BOOST_RETHROW;
|
Chris@16
|
1867 }
|
Chris@16
|
1868 BOOST_CATCH_END
|
Chris@16
|
1869
|
Chris@16
|
1870 // In the event of success, indicate new content type:
|
Chris@16
|
1871 lhs_.indicate_which(rhs_which_); // nothrow
|
Chris@16
|
1872 }
|
Chris@16
|
1873
|
Chris@16
|
1874 template <typename RhsT>
|
Chris@16
|
1875 void assign_impl(
|
Chris@16
|
1876 const RhsT& rhs_content
|
Chris@16
|
1877 , mpl::false_ // has_nothrow_copy
|
Chris@16
|
1878 , mpl::false_ // is_nothrow_move_constructible
|
Chris@16
|
1879 , mpl::false_ // has_fallback_type
|
Chris@101
|
1880 ) const
|
Chris@16
|
1881 {
|
Chris@16
|
1882 detail::variant::backup_assigner<wknd_self_t>
|
Chris@16
|
1883 visitor(lhs_, rhs_which_, rhs_content);
|
Chris@16
|
1884 lhs_.internal_apply_visitor(visitor);
|
Chris@16
|
1885 }
|
Chris@16
|
1886
|
Chris@16
|
1887 public: // internal visitor interfaces
|
Chris@16
|
1888
|
Chris@16
|
1889 template <typename RhsT>
|
Chris@16
|
1890 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
|
Chris@101
|
1891 internal_visit(const RhsT& rhs_content, int) const
|
Chris@16
|
1892 {
|
Chris@16
|
1893 typedef typename has_nothrow_copy<RhsT>::type
|
Chris@16
|
1894 nothrow_copy;
|
Chris@16
|
1895 typedef typename mpl::or_< // reduces compile-time
|
Chris@16
|
1896 nothrow_copy
|
Chris@16
|
1897 , is_nothrow_move_constructible<RhsT>
|
Chris@16
|
1898 >::type nothrow_move_constructor;
|
Chris@16
|
1899
|
Chris@16
|
1900 assign_impl(
|
Chris@16
|
1901 rhs_content
|
Chris@16
|
1902 , nothrow_copy()
|
Chris@16
|
1903 , nothrow_move_constructor()
|
Chris@16
|
1904 , has_fallback_type_()
|
Chris@16
|
1905 );
|
Chris@16
|
1906
|
Chris@16
|
1907 BOOST_VARIANT_AUX_RETURN_VOID;
|
Chris@16
|
1908 }
|
Chris@16
|
1909
|
Chris@16
|
1910 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
|
Chris@16
|
1911 private:
|
Chris@16
|
1912 // silence MSVC warning C4512: assignment operator could not be generated
|
Chris@16
|
1913 assigner& operator= (assigner const&);
|
Chris@16
|
1914 #endif
|
Chris@16
|
1915 };
|
Chris@16
|
1916
|
Chris@16
|
1917 friend class assigner;
|
Chris@16
|
1918
|
Chris@16
|
1919 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
1920 // class move_assigner
|
Chris@16
|
1921 //
|
Chris@16
|
1922 // Internal visitor that "move assigns" the visited value to the given variant
|
Chris@16
|
1923 // by appropriate destruction and move-construction.
|
Chris@16
|
1924 //
|
Chris@16
|
1925
|
Chris@16
|
1926 class move_assigner
|
Chris@101
|
1927 : public assigner
|
Chris@16
|
1928 {
|
Chris@16
|
1929 public: // structors
|
Chris@16
|
1930
|
Chris@16
|
1931 move_assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT
|
Chris@101
|
1932 : assigner(lhs, rhs_which)
|
Chris@16
|
1933 {
|
Chris@16
|
1934 }
|
Chris@16
|
1935
|
Chris@16
|
1936 private: // helpers, for internal visitor interface (below)
|
Chris@101
|
1937
|
Chris@16
|
1938 template <typename RhsT, typename B2>
|
Chris@16
|
1939 void assign_impl(
|
Chris@16
|
1940 RhsT& rhs_content
|
Chris@16
|
1941 , mpl::true_ // has_nothrow_copy
|
Chris@16
|
1942 , mpl::false_ // is_nothrow_move_constructible
|
Chris@16
|
1943 , B2 // has_fallback_type
|
Chris@101
|
1944 ) const BOOST_NOEXCEPT
|
Chris@16
|
1945 {
|
Chris@101
|
1946 assigner::assign_impl(rhs_content, mpl::true_(), mpl::false_(), B2());
|
Chris@16
|
1947 }
|
Chris@16
|
1948
|
Chris@101
|
1949 template <typename RhsT, typename B, typename B2>
|
Chris@16
|
1950 void assign_impl(
|
Chris@16
|
1951 RhsT& rhs_content
|
Chris@101
|
1952 , B // has_nothrow_copy
|
Chris@16
|
1953 , mpl::true_ // is_nothrow_move_constructible
|
Chris@101
|
1954 , B2 // has_fallback_type
|
Chris@101
|
1955 ) const BOOST_NOEXCEPT
|
Chris@16
|
1956 {
|
Chris@16
|
1957 // ...destroy lhs's content...
|
Chris@101
|
1958 assigner::lhs_.destroy_content(); // nothrow
|
Chris@16
|
1959
|
Chris@16
|
1960 // ...move the rhs_content into lhs's storage...
|
Chris@101
|
1961 new(assigner::lhs_.storage_.address())
|
Chris@16
|
1962 RhsT( detail::variant::move(rhs_content) ); // nothrow
|
Chris@16
|
1963
|
Chris@16
|
1964 // ...and indicate new content type:
|
Chris@101
|
1965 assigner::lhs_.indicate_which(assigner::rhs_which_); // nothrow
|
Chris@16
|
1966 }
|
Chris@16
|
1967
|
Chris@16
|
1968 template <typename RhsT>
|
Chris@16
|
1969 void assign_impl(
|
Chris@16
|
1970 RhsT& rhs_content
|
Chris@16
|
1971 , mpl::false_ // has_nothrow_copy
|
Chris@16
|
1972 , mpl::false_ // is_nothrow_move_constructible
|
Chris@16
|
1973 , mpl::true_ // has_fallback_type
|
Chris@101
|
1974 ) const
|
Chris@16
|
1975 {
|
Chris@16
|
1976 // Destroy lhs's content...
|
Chris@101
|
1977 assigner::lhs_.destroy_content(); // nothrow
|
Chris@16
|
1978
|
Chris@16
|
1979 BOOST_TRY
|
Chris@16
|
1980 {
|
Chris@16
|
1981 // ...and attempt to copy rhs's content into lhs's storage:
|
Chris@101
|
1982 new(assigner::lhs_.storage_.address())
|
Chris@16
|
1983 RhsT( detail::variant::move(rhs_content) );
|
Chris@16
|
1984 }
|
Chris@16
|
1985 BOOST_CATCH (...)
|
Chris@16
|
1986 {
|
Chris@101
|
1987 assigner::construct_fallback();
|
Chris@16
|
1988
|
Chris@16
|
1989 // ...and rethrow:
|
Chris@16
|
1990 BOOST_RETHROW;
|
Chris@16
|
1991 }
|
Chris@16
|
1992 BOOST_CATCH_END
|
Chris@16
|
1993
|
Chris@16
|
1994 // In the event of success, indicate new content type:
|
Chris@101
|
1995 assigner::lhs_.indicate_which(assigner::rhs_which_); // nothrow
|
Chris@16
|
1996 }
|
Chris@101
|
1997
|
Chris@16
|
1998 template <typename RhsT>
|
Chris@16
|
1999 void assign_impl(
|
Chris@101
|
2000 RhsT& rhs_content
|
Chris@16
|
2001 , mpl::false_ // has_nothrow_copy
|
Chris@16
|
2002 , mpl::false_ // is_nothrow_move_constructible
|
Chris@16
|
2003 , mpl::false_ // has_fallback_type
|
Chris@101
|
2004 ) const
|
Chris@16
|
2005 {
|
Chris@101
|
2006 assigner::assign_impl(rhs_content, mpl::false_(), mpl::false_(), mpl::false_());
|
Chris@16
|
2007 }
|
Chris@16
|
2008
|
Chris@16
|
2009 public: // internal visitor interfaces
|
Chris@16
|
2010
|
Chris@16
|
2011 template <typename RhsT>
|
Chris@16
|
2012 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
|
Chris@101
|
2013 internal_visit(RhsT& rhs_content, int) const
|
Chris@16
|
2014 {
|
Chris@16
|
2015 typedef typename is_nothrow_move_constructible<RhsT>::type
|
Chris@16
|
2016 nothrow_move_constructor;
|
Chris@16
|
2017 typedef typename mpl::or_< // reduces compile-time
|
Chris@16
|
2018 nothrow_move_constructor
|
Chris@16
|
2019 , has_nothrow_copy<RhsT>
|
Chris@16
|
2020 >::type nothrow_copy;
|
Chris@16
|
2021
|
Chris@16
|
2022 assign_impl(
|
Chris@16
|
2023 rhs_content
|
Chris@16
|
2024 , nothrow_copy()
|
Chris@16
|
2025 , nothrow_move_constructor()
|
Chris@16
|
2026 , has_fallback_type_()
|
Chris@16
|
2027 );
|
Chris@16
|
2028
|
Chris@16
|
2029 BOOST_VARIANT_AUX_RETURN_VOID;
|
Chris@16
|
2030 }
|
Chris@16
|
2031
|
Chris@16
|
2032 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
|
Chris@16
|
2033 private:
|
Chris@16
|
2034 // silence MSVC warning C4512: assignment operator could not be generated
|
Chris@16
|
2035 move_assigner& operator= (move_assigner const&);
|
Chris@16
|
2036 #endif
|
Chris@16
|
2037 };
|
Chris@16
|
2038
|
Chris@16
|
2039 friend class move_assigner;
|
Chris@16
|
2040 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
2041
|
Chris@16
|
2042 void variant_assign(const variant& rhs)
|
Chris@16
|
2043 {
|
Chris@16
|
2044 // If the contained types are EXACTLY the same...
|
Chris@16
|
2045 if (which_ == rhs.which_)
|
Chris@16
|
2046 {
|
Chris@16
|
2047 // ...then assign rhs's storage to lhs's content:
|
Chris@16
|
2048 detail::variant::assign_storage visitor(rhs.storage_.address());
|
Chris@16
|
2049 this->internal_apply_visitor(visitor);
|
Chris@16
|
2050 }
|
Chris@16
|
2051 else
|
Chris@16
|
2052 {
|
Chris@16
|
2053 // Otherwise, perform general (copy-based) variant assignment:
|
Chris@16
|
2054 assigner visitor(*this, rhs.which());
|
Chris@16
|
2055 rhs.internal_apply_visitor(visitor);
|
Chris@16
|
2056 }
|
Chris@16
|
2057 }
|
Chris@16
|
2058
|
Chris@16
|
2059 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
2060 void variant_assign(variant&& rhs)
|
Chris@16
|
2061 {
|
Chris@16
|
2062 // If the contained types are EXACTLY the same...
|
Chris@16
|
2063 if (which_ == rhs.which_)
|
Chris@16
|
2064 {
|
Chris@16
|
2065 // ...then move rhs's storage to lhs's content:
|
Chris@16
|
2066 detail::variant::move_storage visitor(rhs.storage_.address());
|
Chris@16
|
2067 this->internal_apply_visitor(visitor);
|
Chris@16
|
2068 }
|
Chris@16
|
2069 else
|
Chris@16
|
2070 {
|
Chris@16
|
2071 // Otherwise, perform general (move-based) variant assignment:
|
Chris@16
|
2072 move_assigner visitor(*this, rhs.which());
|
Chris@16
|
2073 rhs.internal_apply_visitor(visitor);
|
Chris@16
|
2074 }
|
Chris@16
|
2075 }
|
Chris@16
|
2076 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
2077
|
Chris@16
|
2078 private: // helpers, for modifiers (below)
|
Chris@16
|
2079
|
Chris@16
|
2080 template <typename T>
|
Chris@16
|
2081 void assign(const T& rhs)
|
Chris@16
|
2082 {
|
Chris@16
|
2083 // If direct T-to-T assignment is not possible...
|
Chris@16
|
2084 detail::variant::direct_assigner<T> direct_assign(rhs);
|
Chris@16
|
2085 if (this->apply_visitor(direct_assign) == false)
|
Chris@16
|
2086 {
|
Chris@16
|
2087 // ...then convert rhs to variant and assign:
|
Chris@16
|
2088 //
|
Chris@16
|
2089 // While potentially inefficient, the following construction of a
|
Chris@16
|
2090 // variant allows T as any type convertible to one of the bounded
|
Chris@16
|
2091 // types without excessive code redundancy.
|
Chris@16
|
2092 //
|
Chris@16
|
2093 variant temp(rhs);
|
Chris@16
|
2094 variant_assign( detail::variant::move(temp) );
|
Chris@16
|
2095 }
|
Chris@16
|
2096 }
|
Chris@16
|
2097
|
Chris@16
|
2098 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
2099 template <typename T>
|
Chris@16
|
2100 void move_assign(T&& rhs)
|
Chris@16
|
2101 {
|
Chris@16
|
2102 // If direct T-to-T move assignment is not possible...
|
Chris@16
|
2103 detail::variant::direct_mover<T> direct_move(rhs);
|
Chris@16
|
2104 if (this->apply_visitor(direct_move) == false)
|
Chris@16
|
2105 {
|
Chris@16
|
2106 // ...then convert rhs to variant and assign:
|
Chris@16
|
2107 //
|
Chris@16
|
2108 // While potentially inefficient, the following construction of a
|
Chris@16
|
2109 // variant allows T as any type convertible to one of the bounded
|
Chris@16
|
2110 // types without excessive code redundancy.
|
Chris@16
|
2111 //
|
Chris@16
|
2112 variant temp( detail::variant::move(rhs) );
|
Chris@16
|
2113 variant_assign( detail::variant::move(temp) );
|
Chris@16
|
2114 }
|
Chris@16
|
2115 }
|
Chris@16
|
2116 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
2117
|
Chris@16
|
2118 public: // modifiers
|
Chris@16
|
2119
|
Chris@16
|
2120 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
2121 template <class T>
|
Chris@16
|
2122 typename boost::enable_if_c<boost::is_rvalue_reference<T&&>::value && !boost::is_const<T>::value, variant& >::type
|
Chris@101
|
2123 operator=(T&& rhs)
|
Chris@16
|
2124 {
|
Chris@16
|
2125 move_assign( detail::variant::move(rhs) );
|
Chris@16
|
2126 return *this;
|
Chris@16
|
2127 }
|
Chris@16
|
2128 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
2129
|
Chris@16
|
2130 template <typename T>
|
Chris@16
|
2131 variant& operator=(const T& rhs)
|
Chris@16
|
2132 {
|
Chris@16
|
2133 assign(rhs);
|
Chris@16
|
2134 return *this;
|
Chris@16
|
2135 }
|
Chris@16
|
2136
|
Chris@16
|
2137 // [MSVC6 requires copy assign appear after templated operator=]
|
Chris@16
|
2138 variant& operator=(const variant& rhs)
|
Chris@16
|
2139 {
|
Chris@16
|
2140 variant_assign(rhs);
|
Chris@16
|
2141 return *this;
|
Chris@16
|
2142 }
|
Chris@16
|
2143
|
Chris@16
|
2144 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@101
|
2145 variant& operator=(variant&& rhs)
|
Chris@101
|
2146 #if !defined(__GNUC__) || (__GNUC__ != 4) || (__GNUC_MINOR__ > 6)
|
Chris@101
|
2147 BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value && variant_move_noexcept_assignable::type::value)
|
Chris@101
|
2148 #endif
|
Chris@16
|
2149 {
|
Chris@16
|
2150 variant_assign( detail::variant::move(rhs) );
|
Chris@16
|
2151 return *this;
|
Chris@16
|
2152 }
|
Chris@16
|
2153 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
2154
|
Chris@16
|
2155 void swap(variant& rhs)
|
Chris@16
|
2156 {
|
Chris@16
|
2157 // If the contained types are the same...
|
Chris@16
|
2158 if (which() == rhs.which())
|
Chris@16
|
2159 {
|
Chris@16
|
2160 // ...then swap the values directly:
|
Chris@16
|
2161 detail::variant::swap_with<variant> visitor(rhs);
|
Chris@16
|
2162 this->apply_visitor(visitor);
|
Chris@16
|
2163 }
|
Chris@16
|
2164 else
|
Chris@16
|
2165 {
|
Chris@16
|
2166 // ...otherwise, perform general variant swap:
|
Chris@16
|
2167 variant tmp( detail::variant::move(rhs) );
|
Chris@16
|
2168 rhs = detail::variant::move(*this);
|
Chris@16
|
2169 *this = detail::variant::move(tmp);
|
Chris@16
|
2170 }
|
Chris@16
|
2171 }
|
Chris@16
|
2172
|
Chris@16
|
2173 public: // queries
|
Chris@16
|
2174
|
Chris@16
|
2175 //
|
Chris@16
|
2176 // NOTE: member which() defined above.
|
Chris@16
|
2177 //
|
Chris@16
|
2178
|
Chris@16
|
2179 bool empty() const BOOST_NOEXCEPT
|
Chris@16
|
2180 {
|
Chris@16
|
2181 return false;
|
Chris@16
|
2182 }
|
Chris@16
|
2183
|
Chris@101
|
2184 const boost::typeindex::type_info& type() const
|
Chris@16
|
2185 {
|
Chris@16
|
2186 detail::variant::reflect visitor;
|
Chris@16
|
2187 return this->apply_visitor(visitor);
|
Chris@16
|
2188 }
|
Chris@16
|
2189
|
Chris@16
|
2190 public: // prevent comparison with foreign types
|
Chris@16
|
2191
|
Chris@101
|
2192 // Obsolete. Remove.
|
Chris@16
|
2193 # define BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE \
|
Chris@16
|
2194 void
|
Chris@16
|
2195
|
Chris@16
|
2196 template <typename U>
|
Chris@101
|
2197 void operator==(const U&) const
|
Chris@16
|
2198 {
|
Chris@16
|
2199 BOOST_STATIC_ASSERT( false && sizeof(U) );
|
Chris@16
|
2200 }
|
Chris@16
|
2201
|
Chris@16
|
2202 template <typename U>
|
Chris@101
|
2203 void operator<(const U&) const
|
Chris@101
|
2204 {
|
Chris@101
|
2205 BOOST_STATIC_ASSERT( false && sizeof(U) );
|
Chris@101
|
2206 }
|
Chris@101
|
2207
|
Chris@101
|
2208 template <typename U>
|
Chris@101
|
2209 void operator!=(const U&) const
|
Chris@101
|
2210 {
|
Chris@101
|
2211 BOOST_STATIC_ASSERT( false && sizeof(U) );
|
Chris@101
|
2212 }
|
Chris@101
|
2213
|
Chris@101
|
2214 template <typename U>
|
Chris@101
|
2215 void operator>(const U&) const
|
Chris@101
|
2216 {
|
Chris@101
|
2217 BOOST_STATIC_ASSERT( false && sizeof(U) );
|
Chris@101
|
2218 }
|
Chris@101
|
2219
|
Chris@101
|
2220 template <typename U>
|
Chris@101
|
2221 void operator<=(const U&) const
|
Chris@101
|
2222 {
|
Chris@101
|
2223 BOOST_STATIC_ASSERT( false && sizeof(U) );
|
Chris@101
|
2224 }
|
Chris@101
|
2225
|
Chris@101
|
2226 template <typename U>
|
Chris@101
|
2227 void operator>=(const U&) const
|
Chris@16
|
2228 {
|
Chris@16
|
2229 BOOST_STATIC_ASSERT( false && sizeof(U) );
|
Chris@16
|
2230 }
|
Chris@16
|
2231
|
Chris@16
|
2232 public: // comparison operators
|
Chris@16
|
2233
|
Chris@16
|
2234 // [MSVC6 requires these operators appear after template operators]
|
Chris@16
|
2235
|
Chris@16
|
2236 bool operator==(const variant& rhs) const
|
Chris@16
|
2237 {
|
Chris@16
|
2238 if (this->which() != rhs.which())
|
Chris@16
|
2239 return false;
|
Chris@16
|
2240
|
Chris@16
|
2241 detail::variant::comparer<
|
Chris@16
|
2242 variant, detail::variant::equal_comp
|
Chris@16
|
2243 > visitor(*this);
|
Chris@16
|
2244 return rhs.apply_visitor(visitor);
|
Chris@16
|
2245 }
|
Chris@16
|
2246
|
Chris@16
|
2247 bool operator<(const variant& rhs) const
|
Chris@16
|
2248 {
|
Chris@16
|
2249 //
|
Chris@16
|
2250 // Dirk Schreib suggested this collating order.
|
Chris@16
|
2251 //
|
Chris@16
|
2252
|
Chris@16
|
2253 if (this->which() != rhs.which())
|
Chris@16
|
2254 return this->which() < rhs.which();
|
Chris@16
|
2255
|
Chris@16
|
2256 detail::variant::comparer<
|
Chris@16
|
2257 variant, detail::variant::less_comp
|
Chris@16
|
2258 > visitor(*this);
|
Chris@16
|
2259 return rhs.apply_visitor(visitor);
|
Chris@16
|
2260 }
|
Chris@16
|
2261
|
Chris@101
|
2262 ///////////////////////////////////////////////////////////////////////////////
|
Chris@101
|
2263 // comparison operators != > <= >=
|
Chris@101
|
2264 inline bool operator!=(const variant& rhs) const
|
Chris@101
|
2265 {
|
Chris@101
|
2266 return !(*this == rhs);
|
Chris@101
|
2267 }
|
Chris@101
|
2268
|
Chris@101
|
2269 inline bool operator>(const variant& rhs) const
|
Chris@101
|
2270 {
|
Chris@101
|
2271 return rhs < *this;
|
Chris@101
|
2272 }
|
Chris@101
|
2273
|
Chris@101
|
2274 inline bool operator<=(const variant& rhs) const
|
Chris@101
|
2275 {
|
Chris@101
|
2276 return !(*this > rhs);
|
Chris@101
|
2277 }
|
Chris@101
|
2278
|
Chris@101
|
2279 inline bool operator>=(const variant& rhs) const
|
Chris@101
|
2280 {
|
Chris@101
|
2281 return !(*this < rhs);
|
Chris@101
|
2282 }
|
Chris@101
|
2283
|
Chris@16
|
2284 // helpers, for visitation support (below) -- private when possible
|
Chris@16
|
2285 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
Chris@16
|
2286
|
Chris@16
|
2287 template < BOOST_VARIANT_ENUM_PARAMS(typename U) >
|
Chris@16
|
2288 friend class variant;
|
Chris@16
|
2289
|
Chris@16
|
2290 private:
|
Chris@16
|
2291
|
Chris@16
|
2292 #else// defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
Chris@16
|
2293
|
Chris@16
|
2294 public:
|
Chris@16
|
2295
|
Chris@16
|
2296 #endif// !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
Chris@16
|
2297
|
Chris@16
|
2298 template <typename Visitor, typename VoidPtrCV>
|
Chris@16
|
2299 static
|
Chris@16
|
2300 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
|
Chris@16
|
2301 typename Visitor::result_type
|
Chris@16
|
2302 )
|
Chris@16
|
2303 internal_apply_visitor_impl(
|
Chris@16
|
2304 int internal_which
|
Chris@16
|
2305 , int logical_which
|
Chris@16
|
2306 , Visitor& visitor
|
Chris@16
|
2307 , VoidPtrCV storage
|
Chris@16
|
2308 )
|
Chris@16
|
2309 {
|
Chris@16
|
2310 typedef mpl::int_<0> first_which;
|
Chris@16
|
2311 typedef typename mpl::begin<internal_types>::type first_it;
|
Chris@16
|
2312 typedef typename mpl::end<internal_types>::type last_it;
|
Chris@16
|
2313
|
Chris@16
|
2314 typedef detail::variant::visitation_impl_step<
|
Chris@16
|
2315 first_it, last_it
|
Chris@16
|
2316 > first_step;
|
Chris@16
|
2317
|
Chris@16
|
2318 return detail::variant::visitation_impl(
|
Chris@16
|
2319 internal_which, logical_which
|
Chris@16
|
2320 , visitor, storage, mpl::false_()
|
Chris@16
|
2321 , never_uses_backup_flag()
|
Chris@16
|
2322 , static_cast<first_which*>(0), static_cast<first_step*>(0)
|
Chris@16
|
2323 );
|
Chris@16
|
2324 }
|
Chris@16
|
2325
|
Chris@16
|
2326 template <typename Visitor>
|
Chris@16
|
2327 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
|
Chris@16
|
2328 typename Visitor::result_type
|
Chris@16
|
2329 )
|
Chris@16
|
2330 internal_apply_visitor(Visitor& visitor)
|
Chris@16
|
2331 {
|
Chris@16
|
2332 return internal_apply_visitor_impl(
|
Chris@16
|
2333 which_, which(), visitor, storage_.address()
|
Chris@16
|
2334 );
|
Chris@16
|
2335 }
|
Chris@16
|
2336
|
Chris@16
|
2337 template <typename Visitor>
|
Chris@16
|
2338 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
|
Chris@16
|
2339 typename Visitor::result_type
|
Chris@16
|
2340 )
|
Chris@16
|
2341 internal_apply_visitor(Visitor& visitor) const
|
Chris@16
|
2342 {
|
Chris@16
|
2343 return internal_apply_visitor_impl(
|
Chris@16
|
2344 which_, which(), visitor, storage_.address()
|
Chris@16
|
2345 );
|
Chris@16
|
2346 }
|
Chris@16
|
2347
|
Chris@16
|
2348 public: // visitation support
|
Chris@16
|
2349
|
Chris@16
|
2350 template <typename Visitor>
|
Chris@16
|
2351 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
|
Chris@16
|
2352 typename Visitor::result_type
|
Chris@16
|
2353 )
|
Chris@16
|
2354 apply_visitor(Visitor& visitor)
|
Chris@16
|
2355 {
|
Chris@16
|
2356 detail::variant::invoke_visitor<Visitor> invoker(visitor);
|
Chris@16
|
2357 return this->internal_apply_visitor(invoker);
|
Chris@16
|
2358 }
|
Chris@16
|
2359
|
Chris@16
|
2360 template <typename Visitor>
|
Chris@16
|
2361 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
|
Chris@16
|
2362 typename Visitor::result_type
|
Chris@16
|
2363 )
|
Chris@16
|
2364 apply_visitor(Visitor& visitor) const
|
Chris@16
|
2365 {
|
Chris@16
|
2366 detail::variant::invoke_visitor<Visitor> invoker(visitor);
|
Chris@16
|
2367 return this->internal_apply_visitor(invoker);
|
Chris@16
|
2368 }
|
Chris@16
|
2369
|
Chris@16
|
2370 }; // class variant
|
Chris@16
|
2371
|
Chris@16
|
2372 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
2373 // metafunction make_variant_over
|
Chris@16
|
2374 //
|
Chris@16
|
2375 // See docs and boost/variant/variant_fwd.hpp for more information.
|
Chris@16
|
2376 //
|
Chris@16
|
2377 template <typename Types>
|
Chris@16
|
2378 struct make_variant_over
|
Chris@16
|
2379 {
|
Chris@16
|
2380 private: // precondition assertions
|
Chris@16
|
2381
|
Chris@16
|
2382 BOOST_STATIC_ASSERT(( ::boost::mpl::is_sequence<Types>::value ));
|
Chris@16
|
2383
|
Chris@16
|
2384 public: // metafunction result
|
Chris@16
|
2385
|
Chris@16
|
2386 typedef variant<
|
Chris@16
|
2387 detail::variant::over_sequence< Types >
|
Chris@16
|
2388 > type;
|
Chris@16
|
2389
|
Chris@16
|
2390 };
|
Chris@16
|
2391
|
Chris@101
|
2392
|
Chris@16
|
2393 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
2394 // function template swap
|
Chris@16
|
2395 //
|
Chris@16
|
2396 // Swaps two variants of the same type (i.e., identical specification).
|
Chris@16
|
2397 //
|
Chris@16
|
2398 template < BOOST_VARIANT_ENUM_PARAMS(typename T) >
|
Chris@16
|
2399 inline void swap(
|
Chris@16
|
2400 variant< BOOST_VARIANT_ENUM_PARAMS(T) >& lhs
|
Chris@16
|
2401 , variant< BOOST_VARIANT_ENUM_PARAMS(T) >& rhs
|
Chris@16
|
2402 )
|
Chris@16
|
2403 {
|
Chris@16
|
2404 lhs.swap(rhs);
|
Chris@16
|
2405 }
|
Chris@16
|
2406
|
Chris@16
|
2407 } // namespace boost
|
Chris@16
|
2408
|
Chris@16
|
2409 // implementation additions
|
Chris@16
|
2410
|
Chris@16
|
2411 #if !defined(BOOST_NO_IOSTREAM)
|
Chris@16
|
2412 #include "boost/variant/detail/variant_io.hpp"
|
Chris@16
|
2413 #endif // BOOST_NO_IOSTREAM
|
Chris@16
|
2414
|
Chris@16
|
2415 #endif // BOOST_VARIANT_VARIANT_HPP
|