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 |
7 | // Copyright (c) 2014 Antony Polukhin |
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" |
25 | |
26 | #include "boost/type_traits/add_reference.hpp" |
27 | #include "boost/type_traits/add_pointer.hpp" |
28 | |
29 | namespace boost { |
30 | |
31 | ////////////////////////////////////////////////////////////////////////// |
32 | // class bad_get |
33 | // |
34 | // The exception thrown in the event of a failed get of a value. |
35 | // |
36 | class BOOST_SYMBOL_VISIBLE bad_get |
37 | : public std::exception |
38 | { |
39 | public: // std::exception implementation |
40 | |
41 | virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW |
42 | { |
43 | return "boost::bad_get: " |
44 | "failed value get using boost::get" ; |
45 | } |
46 | |
47 | }; |
48 | |
49 | ////////////////////////////////////////////////////////////////////////// |
50 | // function template get<T> |
51 | // |
52 | // Retrieves content of given variant object if content is of type T. |
53 | // Otherwise: pointer ver. returns 0; reference ver. throws bad_get. |
54 | // |
55 | |
56 | namespace detail { namespace variant { |
57 | |
58 | // (detail) class template get_visitor |
59 | // |
60 | // Generic static visitor that: if the value is of the specified type, |
61 | // returns a pointer to the value it visits; else a null pointer. |
62 | // |
63 | template <typename T> |
64 | struct get_visitor |
65 | { |
66 | private: // private typedefs |
67 | |
68 | typedef typename add_pointer<T>::type pointer; |
69 | typedef typename add_reference<T>::type reference; |
70 | |
71 | public: // visitor typedefs |
72 | |
73 | typedef pointer result_type; |
74 | |
75 | public: // visitor interfaces |
76 | |
77 | pointer operator()(reference operand) const BOOST_NOEXCEPT |
78 | { |
79 | return boost::addressof(operand); |
80 | } |
81 | |
82 | template <typename U> |
83 | pointer operator()(const U&) const BOOST_NOEXCEPT |
84 | { |
85 | return static_cast<pointer>(0); |
86 | } |
87 | }; |
88 | |
89 | }} // namespace detail::variant |
90 | |
91 | #ifndef BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE |
92 | # if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551)) |
93 | # define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t) |
94 | # else |
95 | # define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t) \ |
96 | , t* = 0 |
97 | # endif |
98 | #endif |
99 | |
100 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////// |
101 | // relaxed_get<U>(variant) methods |
102 | // |
103 | template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) > |
104 | inline |
105 | typename add_pointer<U>::type |
106 | relaxed_get( |
107 | boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand |
108 | BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) |
109 | ) BOOST_NOEXCEPT |
110 | { |
111 | typedef typename add_pointer<U>::type U_ptr; |
112 | if (!operand) return static_cast<U_ptr>(0); |
113 | |
114 | detail::variant::get_visitor<U> v; |
115 | return operand->apply_visitor(v); |
116 | } |
117 | |
118 | template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) > |
119 | inline |
120 | typename add_pointer<const U>::type |
121 | relaxed_get( |
122 | const 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<const U>::type U_ptr; |
127 | if (!operand) return static_cast<U_ptr>(0); |
128 | |
129 | detail::variant::get_visitor<const 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_reference<U>::type |
136 | relaxed_get( |
137 | boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand |
138 | BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) |
139 | ) |
140 | { |
141 | typedef typename add_pointer<U>::type U_ptr; |
142 | U_ptr result = relaxed_get<U>(&operand); |
143 | |
144 | if (!result) |
145 | boost::throw_exception(e: bad_get()); |
146 | return *result; |
147 | } |
148 | |
149 | template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) > |
150 | inline |
151 | typename add_reference<const U>::type |
152 | relaxed_get( |
153 | const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand |
154 | BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) |
155 | ) |
156 | { |
157 | typedef typename add_pointer<const U>::type U_ptr; |
158 | U_ptr result = relaxed_get<const U>(&operand); |
159 | |
160 | if (!result) |
161 | boost::throw_exception(e: bad_get()); |
162 | return *result; |
163 | } |
164 | |
165 | |
166 | |
167 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////// |
168 | // strict_get<U>(variant) methods |
169 | // |
170 | template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) > |
171 | inline |
172 | typename add_pointer<U>::type |
173 | strict_get( |
174 | boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand |
175 | BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) |
176 | ) BOOST_NOEXCEPT |
177 | { |
178 | BOOST_STATIC_ASSERT_MSG( |
179 | (boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value), |
180 | "boost::variant does not contain specified type U, " |
181 | "call to boost::get<U>(boost::variant<T...>*) will always return NULL" |
182 | ); |
183 | |
184 | return relaxed_get<U>(operand); |
185 | } |
186 | |
187 | template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) > |
188 | inline |
189 | typename add_pointer<const U>::type |
190 | strict_get( |
191 | const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand |
192 | BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) |
193 | ) BOOST_NOEXCEPT |
194 | { |
195 | BOOST_STATIC_ASSERT_MSG( |
196 | (boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, const U >::value), |
197 | "boost::variant does not contain specified type U, " |
198 | "call to boost::get<U>(const boost::variant<T...>*) will always return NULL" |
199 | ); |
200 | |
201 | return relaxed_get<U>(operand); |
202 | } |
203 | |
204 | template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) > |
205 | inline |
206 | typename add_reference<U>::type |
207 | strict_get( |
208 | boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand |
209 | BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) |
210 | ) |
211 | { |
212 | BOOST_STATIC_ASSERT_MSG( |
213 | (boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value), |
214 | "boost::variant does not contain specified type U, " |
215 | "call to boost::get<U>(boost::variant<T...>&) will always throw boost::bad_get exception" |
216 | ); |
217 | |
218 | return relaxed_get<U>(operand); |
219 | } |
220 | |
221 | template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) > |
222 | inline |
223 | typename add_reference<const U>::type |
224 | strict_get( |
225 | const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand |
226 | BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) |
227 | ) |
228 | { |
229 | BOOST_STATIC_ASSERT_MSG( |
230 | (boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, const U >::value), |
231 | "boost::variant does not contain specified type U, " |
232 | "call to boost::get<U>(const boost::variant<T...>&) will always throw boost::bad_get exception" |
233 | ); |
234 | |
235 | return relaxed_get<U>(operand); |
236 | } |
237 | |
238 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////// |
239 | // get<U>(variant) methods |
240 | // |
241 | |
242 | template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) > |
243 | inline |
244 | typename add_pointer<U>::type |
245 | get( |
246 | boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand |
247 | BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) |
248 | ) BOOST_NOEXCEPT |
249 | { |
250 | #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT |
251 | return relaxed_get<U>(operand); |
252 | #else |
253 | return strict_get<U>(operand); |
254 | #endif |
255 | |
256 | } |
257 | |
258 | template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) > |
259 | inline |
260 | typename add_pointer<const U>::type |
261 | get( |
262 | const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand |
263 | BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) |
264 | ) BOOST_NOEXCEPT |
265 | { |
266 | #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT |
267 | return relaxed_get<U>(operand); |
268 | #else |
269 | return strict_get<U>(operand); |
270 | #endif |
271 | } |
272 | |
273 | template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) > |
274 | inline |
275 | typename add_reference<U>::type |
276 | get( |
277 | boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand |
278 | BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) |
279 | ) |
280 | { |
281 | #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT |
282 | return relaxed_get<U>(operand); |
283 | #else |
284 | return strict_get<U>(operand); |
285 | #endif |
286 | } |
287 | |
288 | template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) > |
289 | inline |
290 | typename add_reference<const U>::type |
291 | get( |
292 | const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand |
293 | BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) |
294 | ) |
295 | { |
296 | #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT |
297 | return relaxed_get<U>(operand); |
298 | #else |
299 | return strict_get<U>(operand); |
300 | #endif |
301 | } |
302 | |
303 | } // namespace boost |
304 | |
305 | #endif // BOOST_VARIANT_GET_HPP |
306 | |