Chris@102
|
1 //-----------------------------------------------------------------------------
|
Chris@102
|
2 // boost variant/polymorphic_get.hpp header file
|
Chris@102
|
3 // See http://www.boost.org for updates, documentation, and revision history.
|
Chris@102
|
4 //-----------------------------------------------------------------------------
|
Chris@102
|
5 //
|
Chris@102
|
6 // Copyright (c) 2013-2015 Antony Polukhin
|
Chris@102
|
7 //
|
Chris@102
|
8 // Distributed under the Boost Software License, Version 1.0. (See
|
Chris@102
|
9 // accompanying file LICENSE_1_0.txt or copy at
|
Chris@102
|
10 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@102
|
11
|
Chris@102
|
12 #ifndef BOOST_VARIANT_POLYMORPHIC_GET_HPP
|
Chris@102
|
13 #define BOOST_VARIANT_POLYMORPHIC_GET_HPP
|
Chris@102
|
14
|
Chris@102
|
15 #include <exception>
|
Chris@102
|
16
|
Chris@102
|
17 #include "boost/config.hpp"
|
Chris@102
|
18 #include "boost/detail/workaround.hpp"
|
Chris@102
|
19 #include "boost/static_assert.hpp"
|
Chris@102
|
20 #include "boost/throw_exception.hpp"
|
Chris@102
|
21 #include "boost/utility/addressof.hpp"
|
Chris@102
|
22 #include "boost/variant/variant_fwd.hpp"
|
Chris@102
|
23 #include "boost/variant/get.hpp"
|
Chris@102
|
24
|
Chris@102
|
25 #include "boost/type_traits/add_reference.hpp"
|
Chris@102
|
26 #include "boost/type_traits/add_pointer.hpp"
|
Chris@102
|
27 #include "boost/type_traits/is_base_of.hpp"
|
Chris@102
|
28
|
Chris@102
|
29 namespace boost {
|
Chris@102
|
30
|
Chris@102
|
31 //////////////////////////////////////////////////////////////////////////
|
Chris@102
|
32 // class bad_polymorphic_get
|
Chris@102
|
33 //
|
Chris@102
|
34 // The exception thrown in the event of a failed get of a value.
|
Chris@102
|
35 //
|
Chris@102
|
36 class BOOST_SYMBOL_VISIBLE bad_polymorphic_get
|
Chris@102
|
37 : public bad_get
|
Chris@102
|
38 {
|
Chris@102
|
39 public: // std::exception implementation
|
Chris@102
|
40
|
Chris@102
|
41 virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@102
|
42 {
|
Chris@102
|
43 return "boost::bad_polymorphic_get: "
|
Chris@102
|
44 "failed value get using boost::polymorphic_get";
|
Chris@102
|
45 }
|
Chris@102
|
46
|
Chris@102
|
47 };
|
Chris@102
|
48
|
Chris@102
|
49 //////////////////////////////////////////////////////////////////////////
|
Chris@102
|
50 // function template get<T>
|
Chris@102
|
51 //
|
Chris@102
|
52 // Retrieves content of given variant object if content is of type T.
|
Chris@102
|
53 // Otherwise: pointer ver. returns 0; reference ver. throws bad_get.
|
Chris@102
|
54 //
|
Chris@102
|
55
|
Chris@102
|
56 namespace detail { namespace variant {
|
Chris@102
|
57
|
Chris@102
|
58
|
Chris@102
|
59 ///////////////////////////////////////////////////////////////////////////////////////////////////
|
Chris@102
|
60 // polymorphic metafunctions to detect index of a value
|
Chris@102
|
61 //
|
Chris@102
|
62
|
Chris@102
|
63 template <class Types, class T>
|
Chris@102
|
64 struct element_polymorphic_iterator_impl :
|
Chris@102
|
65 boost::mpl::find_if<
|
Chris@102
|
66 Types,
|
Chris@102
|
67 boost::mpl::or_<
|
Chris@102
|
68 variant_element_functor<boost::mpl::_1, T>,
|
Chris@102
|
69 variant_element_functor<boost::mpl::_1, typename boost::remove_cv<T>::type >,
|
Chris@102
|
70 boost::is_base_of<T, boost::mpl::_1>
|
Chris@102
|
71 >
|
Chris@102
|
72 >
|
Chris@102
|
73 {};
|
Chris@102
|
74
|
Chris@102
|
75 template <class Variant, class T>
|
Chris@102
|
76 struct holds_element_polymorphic :
|
Chris@102
|
77 boost::mpl::not_<
|
Chris@102
|
78 boost::is_same<
|
Chris@102
|
79 typename boost::mpl::end<typename Variant::types>::type,
|
Chris@102
|
80 typename element_polymorphic_iterator_impl<typename Variant::types, T>::type
|
Chris@102
|
81 >
|
Chris@102
|
82 >
|
Chris@102
|
83 {};
|
Chris@102
|
84
|
Chris@102
|
85 // (detail) class template get_polymorphic_visitor
|
Chris@102
|
86 //
|
Chris@102
|
87 // Generic static visitor that: if the value is of the specified
|
Chris@102
|
88 // type or of a type derived from specified, returns a pointer
|
Chris@102
|
89 // to the value it visits; else a null pointer.
|
Chris@102
|
90 //
|
Chris@102
|
91 template <typename Base>
|
Chris@102
|
92 struct get_polymorphic_visitor
|
Chris@102
|
93 {
|
Chris@102
|
94 private: // private typedefs
|
Chris@102
|
95 typedef get_polymorphic_visitor<Base> this_type;
|
Chris@102
|
96 typedef typename add_pointer<Base>::type pointer;
|
Chris@102
|
97 typedef typename add_reference<Base>::type reference;
|
Chris@102
|
98
|
Chris@102
|
99 pointer get(reference operand, boost::true_type) const BOOST_NOEXCEPT
|
Chris@102
|
100 {
|
Chris@102
|
101 return boost::addressof(operand);
|
Chris@102
|
102 }
|
Chris@102
|
103
|
Chris@102
|
104 template <class T>
|
Chris@102
|
105 pointer get(T&, boost::false_type) const BOOST_NOEXCEPT
|
Chris@102
|
106 {
|
Chris@102
|
107 return static_cast<pointer>(0);
|
Chris@102
|
108 }
|
Chris@102
|
109
|
Chris@102
|
110 public: // visitor interfaces
|
Chris@102
|
111 typedef pointer result_type;
|
Chris@102
|
112
|
Chris@102
|
113 template <typename U>
|
Chris@102
|
114 pointer operator()(U& operand) const BOOST_NOEXCEPT
|
Chris@102
|
115 {
|
Chris@102
|
116 typedef boost::integral_constant<
|
Chris@102
|
117 bool,
|
Chris@102
|
118 boost::mpl::or_<
|
Chris@102
|
119 boost::is_base_of<Base, U>,
|
Chris@102
|
120 boost::is_same<Base, U>,
|
Chris@102
|
121 boost::is_same<typename boost::remove_cv<Base>::type, U >
|
Chris@102
|
122 >::value
|
Chris@102
|
123 > tag_t;
|
Chris@102
|
124
|
Chris@102
|
125 return this_type::get(operand, tag_t());
|
Chris@102
|
126 }
|
Chris@102
|
127 };
|
Chris@102
|
128
|
Chris@102
|
129 }} // namespace detail::variant
|
Chris@102
|
130
|
Chris@102
|
131 #ifndef BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE
|
Chris@102
|
132 # if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551))
|
Chris@102
|
133 # define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t)
|
Chris@102
|
134 # else
|
Chris@102
|
135 # define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t) \
|
Chris@102
|
136 , t* = 0
|
Chris@102
|
137 # endif
|
Chris@102
|
138 #endif
|
Chris@102
|
139
|
Chris@102
|
140 //////////////////////////////////////////////////////////////////////////////////////////////////////////
|
Chris@102
|
141 // polymorphic_relaxed_get
|
Chris@102
|
142 //
|
Chris@102
|
143
|
Chris@102
|
144 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
|
Chris@102
|
145 inline
|
Chris@102
|
146 typename add_pointer<U>::type
|
Chris@102
|
147 polymorphic_relaxed_get(
|
Chris@102
|
148 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
|
Chris@102
|
149 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
|
Chris@102
|
150 ) BOOST_NOEXCEPT
|
Chris@102
|
151 {
|
Chris@102
|
152 typedef typename add_pointer<U>::type U_ptr;
|
Chris@102
|
153 if (!operand) return static_cast<U_ptr>(0);
|
Chris@102
|
154
|
Chris@102
|
155 detail::variant::get_polymorphic_visitor<U> v;
|
Chris@102
|
156 return operand->apply_visitor(v);
|
Chris@102
|
157 }
|
Chris@102
|
158
|
Chris@102
|
159 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
|
Chris@102
|
160 inline
|
Chris@102
|
161 typename add_pointer<const U>::type
|
Chris@102
|
162 polymorphic_relaxed_get(
|
Chris@102
|
163 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
|
Chris@102
|
164 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
|
Chris@102
|
165 ) BOOST_NOEXCEPT
|
Chris@102
|
166 {
|
Chris@102
|
167 typedef typename add_pointer<const U>::type U_ptr;
|
Chris@102
|
168 if (!operand) return static_cast<U_ptr>(0);
|
Chris@102
|
169
|
Chris@102
|
170 detail::variant::get_polymorphic_visitor<const U> v;
|
Chris@102
|
171 return operand->apply_visitor(v);
|
Chris@102
|
172 }
|
Chris@102
|
173
|
Chris@102
|
174 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
|
Chris@102
|
175 inline
|
Chris@102
|
176 typename add_reference<U>::type
|
Chris@102
|
177 polymorphic_relaxed_get(
|
Chris@102
|
178 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
|
Chris@102
|
179 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
|
Chris@102
|
180 )
|
Chris@102
|
181 {
|
Chris@102
|
182 typedef typename add_pointer<U>::type U_ptr;
|
Chris@102
|
183 U_ptr result = polymorphic_relaxed_get<U>(&operand);
|
Chris@102
|
184
|
Chris@102
|
185 if (!result)
|
Chris@102
|
186 boost::throw_exception(bad_polymorphic_get());
|
Chris@102
|
187 return *result;
|
Chris@102
|
188 }
|
Chris@102
|
189
|
Chris@102
|
190 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
|
Chris@102
|
191 inline
|
Chris@102
|
192 typename add_reference<const U>::type
|
Chris@102
|
193 polymorphic_relaxed_get(
|
Chris@102
|
194 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
|
Chris@102
|
195 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
|
Chris@102
|
196 )
|
Chris@102
|
197 {
|
Chris@102
|
198 typedef typename add_pointer<const U>::type U_ptr;
|
Chris@102
|
199 U_ptr result = polymorphic_relaxed_get<const U>(&operand);
|
Chris@102
|
200
|
Chris@102
|
201 if (!result)
|
Chris@102
|
202 boost::throw_exception(bad_polymorphic_get());
|
Chris@102
|
203 return *result;
|
Chris@102
|
204 }
|
Chris@102
|
205
|
Chris@102
|
206 //////////////////////////////////////////////////////////////////////////////////////////////////////////
|
Chris@102
|
207 // polymorphic_strict_get
|
Chris@102
|
208 //
|
Chris@102
|
209
|
Chris@102
|
210 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
|
Chris@102
|
211 inline
|
Chris@102
|
212 typename add_pointer<U>::type
|
Chris@102
|
213 polymorphic_strict_get(
|
Chris@102
|
214 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
|
Chris@102
|
215 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
|
Chris@102
|
216 ) BOOST_NOEXCEPT
|
Chris@102
|
217 {
|
Chris@102
|
218 BOOST_STATIC_ASSERT_MSG(
|
Chris@102
|
219 (boost::detail::variant::holds_element_polymorphic<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
|
Chris@102
|
220 "boost::variant does not contain specified type U, "
|
Chris@102
|
221 "call to boost::polymorphic_get<U>(boost::variant<T...>*) will always return NULL"
|
Chris@102
|
222 );
|
Chris@102
|
223
|
Chris@102
|
224 return polymorphic_relaxed_get<U>(operand);
|
Chris@102
|
225 }
|
Chris@102
|
226
|
Chris@102
|
227 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
|
Chris@102
|
228 inline
|
Chris@102
|
229 typename add_pointer<const U>::type
|
Chris@102
|
230 polymorphic_strict_get(
|
Chris@102
|
231 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
|
Chris@102
|
232 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
|
Chris@102
|
233 ) BOOST_NOEXCEPT
|
Chris@102
|
234 {
|
Chris@102
|
235 BOOST_STATIC_ASSERT_MSG(
|
Chris@102
|
236 (boost::detail::variant::holds_element_polymorphic<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
|
Chris@102
|
237 "boost::variant does not contain specified type U, "
|
Chris@102
|
238 "call to boost::polymorphic_get<U>(const boost::variant<T...>*) will always return NULL"
|
Chris@102
|
239 );
|
Chris@102
|
240
|
Chris@102
|
241 return polymorphic_relaxed_get<U>(operand);
|
Chris@102
|
242 }
|
Chris@102
|
243
|
Chris@102
|
244 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
|
Chris@102
|
245 inline
|
Chris@102
|
246 typename add_reference<U>::type
|
Chris@102
|
247 polymorphic_strict_get(
|
Chris@102
|
248 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
|
Chris@102
|
249 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
|
Chris@102
|
250 )
|
Chris@102
|
251 {
|
Chris@102
|
252 BOOST_STATIC_ASSERT_MSG(
|
Chris@102
|
253 (boost::detail::variant::holds_element_polymorphic<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
|
Chris@102
|
254 "boost::variant does not contain specified type U, "
|
Chris@102
|
255 "call to boost::polymorphic_get<U>(boost::variant<T...>&) will always throw boost::bad_polymorphic_get exception"
|
Chris@102
|
256 );
|
Chris@102
|
257
|
Chris@102
|
258 return polymorphic_relaxed_get<U>(operand);
|
Chris@102
|
259 }
|
Chris@102
|
260
|
Chris@102
|
261 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
|
Chris@102
|
262 inline
|
Chris@102
|
263 typename add_reference<const U>::type
|
Chris@102
|
264 polymorphic_strict_get(
|
Chris@102
|
265 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
|
Chris@102
|
266 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
|
Chris@102
|
267 )
|
Chris@102
|
268 {
|
Chris@102
|
269 BOOST_STATIC_ASSERT_MSG(
|
Chris@102
|
270 (boost::detail::variant::holds_element_polymorphic<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
|
Chris@102
|
271 "boost::variant does not contain specified type U, "
|
Chris@102
|
272 "call to boost::polymorphic_get<U>(const boost::variant<T...>&) will always throw boost::bad_polymorphic_get exception"
|
Chris@102
|
273 );
|
Chris@102
|
274
|
Chris@102
|
275 return polymorphic_relaxed_get<U>(operand);
|
Chris@102
|
276 }
|
Chris@102
|
277
|
Chris@102
|
278 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
Chris@102
|
279 // polymorphic_get<U>(variant) methods
|
Chris@102
|
280 //
|
Chris@102
|
281
|
Chris@102
|
282 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
|
Chris@102
|
283 inline
|
Chris@102
|
284 typename add_pointer<U>::type
|
Chris@102
|
285 polymorphic_get(
|
Chris@102
|
286 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
|
Chris@102
|
287 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
|
Chris@102
|
288 ) BOOST_NOEXCEPT
|
Chris@102
|
289 {
|
Chris@102
|
290 #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
|
Chris@102
|
291 return polymorphic_relaxed_get<U>(operand);
|
Chris@102
|
292 #else
|
Chris@102
|
293 return polymorphic_strict_get<U>(operand);
|
Chris@102
|
294 #endif
|
Chris@102
|
295
|
Chris@102
|
296 }
|
Chris@102
|
297
|
Chris@102
|
298 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
|
Chris@102
|
299 inline
|
Chris@102
|
300 typename add_pointer<const U>::type
|
Chris@102
|
301 polymorphic_get(
|
Chris@102
|
302 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
|
Chris@102
|
303 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
|
Chris@102
|
304 ) BOOST_NOEXCEPT
|
Chris@102
|
305 {
|
Chris@102
|
306 #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
|
Chris@102
|
307 return polymorphic_relaxed_get<U>(operand);
|
Chris@102
|
308 #else
|
Chris@102
|
309 return polymorphic_strict_get<U>(operand);
|
Chris@102
|
310 #endif
|
Chris@102
|
311 }
|
Chris@102
|
312
|
Chris@102
|
313 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
|
Chris@102
|
314 inline
|
Chris@102
|
315 typename add_reference<U>::type
|
Chris@102
|
316 polymorphic_get(
|
Chris@102
|
317 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
|
Chris@102
|
318 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
|
Chris@102
|
319 )
|
Chris@102
|
320 {
|
Chris@102
|
321 #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
|
Chris@102
|
322 return polymorphic_relaxed_get<U>(operand);
|
Chris@102
|
323 #else
|
Chris@102
|
324 return polymorphic_strict_get<U>(operand);
|
Chris@102
|
325 #endif
|
Chris@102
|
326 }
|
Chris@102
|
327
|
Chris@102
|
328 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
|
Chris@102
|
329 inline
|
Chris@102
|
330 typename add_reference<const U>::type
|
Chris@102
|
331 polymorphic_get(
|
Chris@102
|
332 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
|
Chris@102
|
333 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
|
Chris@102
|
334 )
|
Chris@102
|
335 {
|
Chris@102
|
336 #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
|
Chris@102
|
337 return polymorphic_relaxed_get<U>(operand);
|
Chris@102
|
338 #else
|
Chris@102
|
339 return polymorphic_strict_get<U>(operand);
|
Chris@102
|
340 #endif
|
Chris@102
|
341 }
|
Chris@102
|
342 } // namespace boost
|
Chris@102
|
343
|
Chris@102
|
344 #endif // BOOST_VARIANT_POLYMORPHIC_GET_HPP
|