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-2022 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>
25 #include <boost/variant/detail/move.hpp>
27 #include <boost/type_traits/add_reference.hpp>
28 #include <boost/type_traits/add_pointer.hpp>
29 #include <boost/type_traits/is_lvalue_reference.hpp>
33 #if defined(BOOST_CLANG)
34 # pragma clang diagnostic push
35 # pragma clang diagnostic ignored "-Wweak-vtables"
37 //////////////////////////////////////////////////////////////////////////
40 // The exception thrown in the event of a failed get of a value.
42 class BOOST_SYMBOL_VISIBLE bad_get
43 : public std::exception
45 public: // std::exception implementation
47 const char * what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE
49 return "boost::bad_get: "
50 "failed value get using boost::get";
54 #if defined(BOOST_CLANG)
55 # pragma clang diagnostic pop
59 //////////////////////////////////////////////////////////////////////////
60 // function template get<T>
62 // Retrieves content of given variant object if content is of type T.
63 // Otherwise: pointer ver. returns 0; reference ver. throws bad_get.
66 namespace detail { namespace variant {
68 // (detail) class template get_visitor
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.
76 private: // private typedefs
78 typedef typename add_pointer<T>::type pointer;
79 typedef typename add_reference<T>::type reference;
81 public: // visitor typedefs
83 typedef pointer result_type;
85 public: // visitor interfaces
87 pointer operator()(reference operand) const BOOST_NOEXCEPT
89 return boost::addressof(operand);
93 pointer operator()(const U&) const BOOST_NOEXCEPT
95 return static_cast<pointer>(0);
99 }} // namespace detail::variant
101 #ifndef BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE
102 # if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0551))
103 # define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t)
105 # if defined(BOOST_NO_CXX11_NULLPTR)
106 # define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t) \
109 # define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t) \
115 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
116 // relaxed_get<U>(variant) methods
118 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
120 typename add_pointer<U>::type
122 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
123 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
126 typedef typename add_pointer<U>::type U_ptr;
127 if (!operand) return static_cast<U_ptr>(0);
129 detail::variant::get_visitor<U> v;
130 return operand->apply_visitor(v);
133 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
135 typename add_pointer<const U>::type
137 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
138 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
141 typedef typename add_pointer<const U>::type U_ptr;
142 if (!operand) return static_cast<U_ptr>(0);
144 detail::variant::get_visitor<const U> v;
145 return operand->apply_visitor(v);
148 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
150 typename add_reference<U>::type
152 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
153 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
156 typedef typename add_pointer<U>::type U_ptr;
157 U_ptr result = relaxed_get<U>(boost::addressof(operand));
160 boost::throw_exception(bad_get());
164 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
166 typename add_reference<const U>::type
168 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
169 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
172 typedef typename add_pointer<const U>::type U_ptr;
173 U_ptr result = relaxed_get<const U>(boost::addressof(operand));
176 boost::throw_exception(bad_get());
180 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
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
187 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
191 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >&& operand
192 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
195 typedef typename add_pointer<U>::type U_ptr;
196 U_ptr result = relaxed_get<U>(boost::addressof(operand));
199 boost::throw_exception(bad_get());
200 return static_cast<U&&>(*result);
203 #if defined(BOOST_MSVC) && (_MSC_VER < 1900)
204 # pragma warning(pop)
209 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
210 // strict_get<U>(variant) methods
212 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
214 typename add_pointer<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 return NULL"
226 return relaxed_get<U>(operand);
229 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
231 typename add_pointer<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 return NULL"
243 return relaxed_get<U>(operand);
246 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
248 typename add_reference<U>::type
250 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
251 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
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"
260 return relaxed_get<U>(operand);
263 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
265 typename add_reference<const U>::type
267 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
268 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
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"
277 return relaxed_get<U>(operand);
280 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
281 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
285 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >&& operand
286 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
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...>&&) "
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"
300 return relaxed_get<U>(detail::variant::move(operand));
304 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
305 // get<U>(variant) methods
308 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
310 typename add_pointer<U>::type
312 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
313 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
316 #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
317 return relaxed_get<U>(operand);
319 return strict_get<U>(operand);
324 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
326 typename add_pointer<const U>::type
328 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
329 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
332 #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
333 return relaxed_get<U>(operand);
335 return strict_get<U>(operand);
339 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
341 typename add_reference<U>::type
343 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
344 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
347 #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
348 return relaxed_get<U>(operand);
350 return strict_get<U>(operand);
354 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
356 typename add_reference<const U>::type
358 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
359 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
362 #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
363 return relaxed_get<U>(operand);
365 return strict_get<U>(operand);
369 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
370 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
374 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >&& operand
375 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
378 #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
379 return relaxed_get<U>(detail::variant::move(operand));
381 return strict_get<U>(detail::variant::move(operand));
388 #endif // BOOST_VARIANT_GET_HPP