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
29namespace boost {
30
31//////////////////////////////////////////////////////////////////////////
32// class bad_get
33//
34// The exception thrown in the event of a failed get of a value.
35//
36class BOOST_SYMBOL_VISIBLE bad_get
37 : public std::exception
38{
39public: // 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
56namespace 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//
63template <typename T>
64struct get_visitor
65{
66private: // private typedefs
67
68 typedef typename add_pointer<T>::type pointer;
69 typedef typename add_reference<T>::type reference;
70
71public: // visitor typedefs
72
73 typedef pointer result_type;
74
75public: // 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//
103template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
104inline
105 typename add_pointer<U>::type
106relaxed_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
118template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
119inline
120 typename add_pointer<const U>::type
121relaxed_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
133template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
134inline
135 typename add_reference<U>::type
136relaxed_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
149template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
150inline
151 typename add_reference<const U>::type
152relaxed_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//
170template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
171inline
172 typename add_pointer<U>::type
173strict_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
187template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
188inline
189 typename add_pointer<const U>::type
190strict_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
204template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
205inline
206 typename add_reference<U>::type
207strict_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
221template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
222inline
223 typename add_reference<const U>::type
224strict_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
242template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
243inline
244 typename add_pointer<U>::type
245get(
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
258template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
259inline
260 typename add_pointer<const U>::type
261get(
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
273template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
274inline
275 typename add_reference<U>::type
276get(
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
288template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
289inline
290 typename add_reference<const U>::type
291get(
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

source code of boost/boost/variant/get.hpp