1 //-----------------------------------------------------------------------------
2 // boost variant/get.hpp header file
3 // See http://www.boost.org for updates, documentation, and revision history.
4 //-----------------------------------------------------------------------------
6 // Copyright (c) 2003 Eric Friedman, Itay Maman
7 // Copyright (c) 2014 Antony Polukhin
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)
13 #ifndef BOOST_VARIANT_GET_HPP
14 #define BOOST_VARIANT_GET_HPP
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>
26 #include <boost/type_traits/add_reference.hpp>
27 #include <boost/type_traits/add_pointer.hpp>
31 #if defined(BOOST_CLANG)
32 # pragma clang diagnostic push
33 # pragma clang diagnostic ignored "-Wweak-vtables"
35 //////////////////////////////////////////////////////////////////////////
38 // The exception thrown in the event of a failed get of a value.
40 class BOOST_SYMBOL_VISIBLE bad_get
41 : public std::exception
43 public: // std::exception implementation
45 virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW
47 return "boost::bad_get: "
48 "failed value get using boost::get";
52 #if defined(BOOST_CLANG)
53 # pragma clang diagnostic pop
57 //////////////////////////////////////////////////////////////////////////
58 // function template get<T>
60 // Retrieves content of given variant object if content is of type T.
61 // Otherwise: pointer ver. returns 0; reference ver. throws bad_get.
64 namespace detail { namespace variant {
66 // (detail) class template get_visitor
68 // Generic static visitor that: if the value is of the specified type,
69 // returns a pointer to the value it visits; else a null pointer.
74 private: // private typedefs
76 typedef typename add_pointer<T>::type pointer;
77 typedef typename add_reference<T>::type reference;
79 public: // visitor typedefs
81 typedef pointer result_type;
83 public: // visitor interfaces
85 pointer operator()(reference operand) const BOOST_NOEXCEPT
87 return boost::addressof(operand);
91 pointer operator()(const U&) const BOOST_NOEXCEPT
93 return static_cast<pointer>(0);
97 }} // namespace detail::variant
99 #ifndef BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE
100 # if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551))
101 # define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t)
103 # define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t) \
108 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
109 // relaxed_get<U>(variant) methods
111 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
113 typename add_pointer<U>::type
115 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
116 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
119 typedef typename add_pointer<U>::type U_ptr;
120 if (!operand) return static_cast<U_ptr>(0);
122 detail::variant::get_visitor<U> v;
123 return operand->apply_visitor(v);
126 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
128 typename add_pointer<const U>::type
130 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
131 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
134 typedef typename add_pointer<const U>::type U_ptr;
135 if (!operand) return static_cast<U_ptr>(0);
137 detail::variant::get_visitor<const U> v;
138 return operand->apply_visitor(v);
141 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
143 typename add_reference<U>::type
145 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
146 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
149 typedef typename add_pointer<U>::type U_ptr;
150 U_ptr result = relaxed_get<U>(boost::addressof(operand));
153 boost::throw_exception(bad_get());
157 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
159 typename add_reference<const U>::type
161 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
162 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
165 typedef typename add_pointer<const U>::type U_ptr;
166 U_ptr result = relaxed_get<const U>(boost::addressof(operand));
169 boost::throw_exception(bad_get());
175 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
176 // strict_get<U>(variant) methods
178 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
180 typename add_pointer<U>::type
182 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
183 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
186 BOOST_STATIC_ASSERT_MSG(
187 (boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
188 "boost::variant does not contain specified type U, "
189 "call to boost::get<U>(boost::variant<T...>*) will always return NULL"
192 return relaxed_get<U>(operand);
195 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
197 typename add_pointer<const U>::type
199 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
200 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
203 BOOST_STATIC_ASSERT_MSG(
204 (boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, const U >::value),
205 "boost::variant does not contain specified type U, "
206 "call to boost::get<U>(const boost::variant<T...>*) will always return NULL"
209 return relaxed_get<U>(operand);
212 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
214 typename add_reference<U>::type
216 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
217 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
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 throw boost::bad_get exception"
226 return relaxed_get<U>(operand);
229 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
231 typename add_reference<const U>::type
233 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
234 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
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 throw boost::bad_get exception"
243 return relaxed_get<U>(operand);
246 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
247 // get<U>(variant) methods
250 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
252 typename add_pointer<U>::type
254 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
255 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
258 #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
259 return relaxed_get<U>(operand);
261 return strict_get<U>(operand);
266 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
268 typename add_pointer<const U>::type
270 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
271 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
274 #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
275 return relaxed_get<U>(operand);
277 return strict_get<U>(operand);
281 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
283 typename add_reference<U>::type
285 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
286 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
289 #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
290 return relaxed_get<U>(operand);
292 return strict_get<U>(operand);
296 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
298 typename add_reference<const U>::type
300 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
301 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
304 #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
305 return relaxed_get<U>(operand);
307 return strict_get<U>(operand);
313 #endif // BOOST_VARIANT_GET_HPP