]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | //----------------------------------------------------------------------------- |
2 | // boost variant/get.hpp header file | |
3 | // See http://www.boost.org for updates, documentation, and revision history. | |
4 | //----------------------------------------------------------------------------- | |
5 | // | |
6 | // Copyright (c) 2003 Eric Friedman, Itay Maman | |
f67539c2 | 7 | // Copyright (c) 2014-2020 Antony Polukhin |
7c673cae FG |
8 | // |
9 | // Distributed under the Boost Software License, Version 1.0. (See | |
10 | // accompanying file LICENSE_1_0.txt or copy at | |
11 | // http://www.boost.org/LICENSE_1_0.txt) | |
12 | ||
13 | #ifndef BOOST_VARIANT_GET_HPP | |
14 | #define BOOST_VARIANT_GET_HPP | |
15 | ||
16 | #include <exception> | |
17 | ||
18 | #include <boost/config.hpp> | |
19 | #include <boost/detail/workaround.hpp> | |
20 | #include <boost/static_assert.hpp> | |
21 | #include <boost/throw_exception.hpp> | |
22 | #include <boost/utility/addressof.hpp> | |
23 | #include <boost/variant/variant_fwd.hpp> | |
24 | #include <boost/variant/detail/element_index.hpp> | |
b32b8144 | 25 | #include <boost/variant/detail/move.hpp> |
7c673cae FG |
26 | |
27 | #include <boost/type_traits/add_reference.hpp> | |
28 | #include <boost/type_traits/add_pointer.hpp> | |
b32b8144 | 29 | #include <boost/type_traits/is_lvalue_reference.hpp> |
7c673cae FG |
30 | |
31 | namespace boost { | |
32 | ||
33 | #if defined(BOOST_CLANG) | |
34 | # pragma clang diagnostic push | |
35 | # pragma clang diagnostic ignored "-Wweak-vtables" | |
36 | #endif | |
37 | ////////////////////////////////////////////////////////////////////////// | |
38 | // class bad_get | |
39 | // | |
40 | // The exception thrown in the event of a failed get of a value. | |
41 | // | |
42 | class BOOST_SYMBOL_VISIBLE bad_get | |
43 | : public std::exception | |
44 | { | |
45 | public: // std::exception implementation | |
46 | ||
20effc67 | 47 | const char * what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE |
7c673cae FG |
48 | { |
49 | return "boost::bad_get: " | |
50 | "failed value get using boost::get"; | |
51 | } | |
52 | ||
53 | }; | |
54 | #if defined(BOOST_CLANG) | |
55 | # pragma clang diagnostic pop | |
56 | #endif | |
57 | ||
58 | ||
59 | ////////////////////////////////////////////////////////////////////////// | |
60 | // function template get<T> | |
61 | // | |
62 | // Retrieves content of given variant object if content is of type T. | |
63 | // Otherwise: pointer ver. returns 0; reference ver. throws bad_get. | |
64 | // | |
65 | ||
66 | namespace detail { namespace variant { | |
67 | ||
68 | // (detail) class template get_visitor | |
69 | // | |
70 | // Generic static visitor that: if the value is of the specified type, | |
71 | // returns a pointer to the value it visits; else a null pointer. | |
72 | // | |
73 | template <typename T> | |
74 | struct get_visitor | |
75 | { | |
76 | private: // private typedefs | |
77 | ||
78 | typedef typename add_pointer<T>::type pointer; | |
79 | typedef typename add_reference<T>::type reference; | |
80 | ||
81 | public: // visitor typedefs | |
82 | ||
83 | typedef pointer result_type; | |
84 | ||
85 | public: // visitor interfaces | |
86 | ||
87 | pointer operator()(reference operand) const BOOST_NOEXCEPT | |
88 | { | |
89 | return boost::addressof(operand); | |
90 | } | |
91 | ||
92 | template <typename U> | |
93 | pointer operator()(const U&) const BOOST_NOEXCEPT | |
94 | { | |
95 | return static_cast<pointer>(0); | |
96 | } | |
97 | }; | |
98 | ||
99 | }} // namespace detail::variant | |
100 | ||
101 | #ifndef BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE | |
20effc67 | 102 | # if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0551)) |
7c673cae FG |
103 | # define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t) |
104 | # else | |
f67539c2 TL |
105 | # if defined(BOOST_NO_NULLPTR) |
106 | # define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t) \ | |
107 | , t* = 0 | |
108 | # else | |
109 | # define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t) \ | |
110 | , t* = nullptr | |
111 | # endif | |
7c673cae FG |
112 | # endif |
113 | #endif | |
114 | ||
115 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
116 | // relaxed_get<U>(variant) methods | |
117 | // | |
118 | template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) > | |
119 | inline | |
120 | typename add_pointer<U>::type | |
121 | relaxed_get( | |
122 | boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand | |
123 | BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) | |
124 | ) BOOST_NOEXCEPT | |
125 | { | |
126 | typedef typename add_pointer<U>::type U_ptr; | |
127 | if (!operand) return static_cast<U_ptr>(0); | |
128 | ||
129 | detail::variant::get_visitor<U> v; | |
130 | return operand->apply_visitor(v); | |
131 | } | |
132 | ||
133 | template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) > | |
134 | inline | |
135 | typename add_pointer<const U>::type | |
136 | relaxed_get( | |
137 | const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand | |
138 | BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) | |
139 | ) BOOST_NOEXCEPT | |
140 | { | |
141 | typedef typename add_pointer<const U>::type U_ptr; | |
142 | if (!operand) return static_cast<U_ptr>(0); | |
143 | ||
144 | detail::variant::get_visitor<const U> v; | |
145 | return operand->apply_visitor(v); | |
146 | } | |
147 | ||
148 | template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) > | |
149 | inline | |
150 | typename add_reference<U>::type | |
151 | relaxed_get( | |
152 | boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand | |
153 | BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) | |
154 | ) | |
155 | { | |
156 | typedef typename add_pointer<U>::type U_ptr; | |
157 | U_ptr result = relaxed_get<U>(boost::addressof(operand)); | |
158 | ||
159 | if (!result) | |
160 | boost::throw_exception(bad_get()); | |
161 | return *result; | |
162 | } | |
163 | ||
164 | template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) > | |
165 | inline | |
166 | typename add_reference<const U>::type | |
167 | relaxed_get( | |
168 | const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand | |
169 | BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) | |
170 | ) | |
171 | { | |
172 | typedef typename add_pointer<const U>::type U_ptr; | |
173 | U_ptr result = relaxed_get<const U>(boost::addressof(operand)); | |
174 | ||
175 | if (!result) | |
176 | boost::throw_exception(bad_get()); | |
177 | return *result; | |
178 | } | |
179 | ||
b32b8144 | 180 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
7c673cae | 181 | |
b32b8144 FG |
182 | #if defined(BOOST_MSVC) && (_MSC_VER < 1900) // MSVC-2014 has fixed the incorrect diagnostics. |
183 | # pragma warning(push) | |
184 | # pragma warning(disable: 4172) // returning address of local variable or temporary | |
185 | #endif | |
186 | ||
187 | template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) > | |
188 | inline | |
189 | U&& | |
190 | relaxed_get( | |
191 | boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >&& operand | |
192 | BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) | |
193 | ) | |
194 | { | |
195 | typedef typename add_pointer<U>::type U_ptr; | |
196 | U_ptr result = relaxed_get<U>(boost::addressof(operand)); | |
197 | ||
198 | if (!result) | |
199 | boost::throw_exception(bad_get()); | |
200 | return static_cast<U&&>(*result); | |
201 | } | |
202 | ||
203 | #if defined(BOOST_MSVC) && (_MSC_VER < 1900) | |
204 | # pragma warning(pop) | |
205 | #endif | |
206 | ||
207 | #endif | |
7c673cae FG |
208 | |
209 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
210 | // strict_get<U>(variant) methods | |
211 | // | |
212 | template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) > | |
213 | inline | |
214 | typename add_pointer<U>::type | |
215 | strict_get( | |
216 | boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand | |
217 | BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) | |
218 | ) BOOST_NOEXCEPT | |
219 | { | |
220 | BOOST_STATIC_ASSERT_MSG( | |
221 | (boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value), | |
222 | "boost::variant does not contain specified type U, " | |
223 | "call to boost::get<U>(boost::variant<T...>*) will always return NULL" | |
224 | ); | |
225 | ||
226 | return relaxed_get<U>(operand); | |
227 | } | |
228 | ||
229 | template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) > | |
230 | inline | |
231 | typename add_pointer<const U>::type | |
232 | strict_get( | |
233 | const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand | |
234 | BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) | |
235 | ) BOOST_NOEXCEPT | |
236 | { | |
237 | BOOST_STATIC_ASSERT_MSG( | |
238 | (boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, const U >::value), | |
239 | "boost::variant does not contain specified type U, " | |
240 | "call to boost::get<U>(const boost::variant<T...>*) will always return NULL" | |
241 | ); | |
242 | ||
243 | return relaxed_get<U>(operand); | |
244 | } | |
245 | ||
246 | template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) > | |
247 | inline | |
248 | typename add_reference<U>::type | |
249 | strict_get( | |
250 | boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand | |
251 | BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) | |
252 | ) | |
253 | { | |
254 | BOOST_STATIC_ASSERT_MSG( | |
255 | (boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value), | |
256 | "boost::variant does not contain specified type U, " | |
257 | "call to boost::get<U>(boost::variant<T...>&) will always throw boost::bad_get exception" | |
258 | ); | |
259 | ||
260 | return relaxed_get<U>(operand); | |
261 | } | |
262 | ||
263 | template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) > | |
264 | inline | |
265 | typename add_reference<const U>::type | |
266 | strict_get( | |
267 | const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand | |
268 | BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) | |
269 | ) | |
270 | { | |
271 | BOOST_STATIC_ASSERT_MSG( | |
272 | (boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, const U >::value), | |
273 | "boost::variant does not contain specified type U, " | |
274 | "call to boost::get<U>(const boost::variant<T...>&) will always throw boost::bad_get exception" | |
275 | ); | |
276 | ||
277 | return relaxed_get<U>(operand); | |
278 | } | |
279 | ||
b32b8144 FG |
280 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
281 | template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) > | |
282 | inline | |
283 | U&& | |
284 | strict_get( | |
285 | boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >&& operand | |
286 | BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) | |
287 | ) | |
288 | { | |
289 | BOOST_STATIC_ASSERT_MSG( | |
290 | (!boost::is_lvalue_reference<U>::value), | |
291 | "remove ampersand '&' from template type U in boost::get<U>(boost::variant<T...>&&) " | |
292 | ); | |
293 | ||
294 | BOOST_STATIC_ASSERT_MSG( | |
295 | (boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value), | |
296 | "boost::variant does not contain specified type U, " | |
297 | "call to boost::get<U>(const boost::variant<T...>&) will always throw boost::bad_get exception" | |
298 | ); | |
299 | ||
300 | return relaxed_get<U>(detail::variant::move(operand)); | |
301 | } | |
302 | #endif | |
303 | ||
7c673cae FG |
304 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////// |
305 | // get<U>(variant) methods | |
306 | // | |
307 | ||
308 | template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) > | |
309 | inline | |
310 | typename add_pointer<U>::type | |
311 | get( | |
312 | boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand | |
313 | BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) | |
314 | ) BOOST_NOEXCEPT | |
315 | { | |
316 | #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT | |
317 | return relaxed_get<U>(operand); | |
318 | #else | |
319 | return strict_get<U>(operand); | |
320 | #endif | |
321 | ||
322 | } | |
323 | ||
324 | template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) > | |
325 | inline | |
326 | typename add_pointer<const U>::type | |
327 | get( | |
328 | const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand | |
329 | BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) | |
330 | ) BOOST_NOEXCEPT | |
331 | { | |
332 | #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT | |
333 | return relaxed_get<U>(operand); | |
334 | #else | |
335 | return strict_get<U>(operand); | |
336 | #endif | |
337 | } | |
338 | ||
339 | template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) > | |
340 | inline | |
341 | typename add_reference<U>::type | |
342 | get( | |
343 | boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand | |
344 | BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) | |
345 | ) | |
346 | { | |
347 | #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT | |
348 | return relaxed_get<U>(operand); | |
349 | #else | |
350 | return strict_get<U>(operand); | |
351 | #endif | |
352 | } | |
353 | ||
354 | template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) > | |
355 | inline | |
356 | typename add_reference<const U>::type | |
357 | get( | |
358 | const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand | |
359 | BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) | |
360 | ) | |
361 | { | |
362 | #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT | |
363 | return relaxed_get<U>(operand); | |
364 | #else | |
365 | return strict_get<U>(operand); | |
366 | #endif | |
367 | } | |
368 | ||
b32b8144 FG |
369 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
370 | template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) > | |
371 | inline | |
372 | U&& | |
373 | get( | |
374 | boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >&& operand | |
375 | BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) | |
376 | ) | |
377 | { | |
378 | #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT | |
379 | return relaxed_get<U>(detail::variant::move(operand)); | |
380 | #else | |
381 | return strict_get<U>(detail::variant::move(operand)); | |
382 | #endif | |
383 | } | |
384 | #endif | |
385 | ||
7c673cae FG |
386 | } // namespace boost |
387 | ||
388 | #endif // BOOST_VARIANT_GET_HPP |