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   	#include <boost/variant/detail/move.hpp>
26   	
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>
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   	
47   	    virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW
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
102  	#   if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551))
103  	#       define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t)
104  	#   else
105  	#       define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t)  \
106  	        , t* = 0
107  	#   endif
108  	#endif
109  	
110  	/////////////////////////////////////////////////////////////////////////////////////////////////////////////
111  	// relaxed_get<U>(variant) methods
112  	//
113  	template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
114  	inline
115  	    typename add_pointer<U>::type
116  	relaxed_get(
117  	      boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
118  	      BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
119  	    ) BOOST_NOEXCEPT
120  	{
121  	    typedef typename add_pointer<U>::type U_ptr;
122  	    if (!operand) return static_cast<U_ptr>(0);
123  	
124  	    detail::variant::get_visitor<U> v;
125  	    return operand->apply_visitor(v);
126  	}
127  	
128  	template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
129  	inline
130  	    typename add_pointer<const U>::type
131  	relaxed_get(
132  	      const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
133  	      BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
134  	    ) BOOST_NOEXCEPT
135  	{
136  	    typedef typename add_pointer<const U>::type U_ptr;
137  	    if (!operand) return static_cast<U_ptr>(0);
138  	
139  	    detail::variant::get_visitor<const U> v;
140  	    return operand->apply_visitor(v);
141  	}
142  	
143  	template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
144  	inline
145  	    typename add_reference<U>::type
146  	relaxed_get(
147  	      boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
148  	      BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
149  	    )
150  	{
151  	    typedef typename add_pointer<U>::type U_ptr;
152  	    U_ptr result = relaxed_get<U>(boost::addressof(operand));
153  	
154  	    if (!result)
155  	        boost::throw_exception(bad_get());
156  	    return *result;
157  	}
158  	
159  	template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
160  	inline
161  	    typename add_reference<const U>::type
162  	relaxed_get(
163  	      const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
164  	      BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
165  	    )
166  	{
167  	    typedef typename add_pointer<const U>::type U_ptr;
168  	    U_ptr result = relaxed_get<const U>(boost::addressof(operand));
169  	
170  	    if (!result)
(1) Event fun_call_w_exception: Called function throws an exception of type "boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::bad_get> >". [details]
171  	        boost::throw_exception(bad_get());
172  	    return *result;
173  	}
174  	
175  	#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
176  	
177  	#if defined(BOOST_MSVC) && (_MSC_VER < 1900) // MSVC-2014 has fixed the incorrect diagnostics.
178  	#   pragma warning(push)
179  	#   pragma warning(disable: 4172) // returning address of local variable or temporary
180  	#endif
181  	
182  	template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
183  	inline
184  	    U&&
185  	relaxed_get(
186  	      boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >&& operand
187  	      BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
188  	    )
189  	{
190  	    typedef typename add_pointer<U>::type U_ptr;
191  	    U_ptr result = relaxed_get<U>(boost::addressof(operand));
192  	
193  	    if (!result)
194  	        boost::throw_exception(bad_get());
195  	    return static_cast<U&&>(*result);
196  	}
197  	
198  	#if defined(BOOST_MSVC) && (_MSC_VER < 1900)
199  	#   pragma warning(pop)
200  	#endif
201  	
202  	#endif
203  	
204  	/////////////////////////////////////////////////////////////////////////////////////////////////////////////
205  	// strict_get<U>(variant) methods
206  	//
207  	template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
208  	inline
209  	    typename add_pointer<U>::type
210  	strict_get(
211  	      boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
212  	      BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
213  	    ) BOOST_NOEXCEPT
214  	{
215  	    BOOST_STATIC_ASSERT_MSG(
216  	        (boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
217  	        "boost::variant does not contain specified type U, "
218  	        "call to boost::get<U>(boost::variant<T...>*) will always return NULL"
219  	    );
220  	
221  	    return relaxed_get<U>(operand);
222  	}
223  	
224  	template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
225  	inline
226  	    typename add_pointer<const U>::type
227  	strict_get(
228  	      const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
229  	      BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
230  	    ) BOOST_NOEXCEPT
231  	{
232  	    BOOST_STATIC_ASSERT_MSG(
233  	        (boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, const U >::value),
234  	        "boost::variant does not contain specified type U, "
235  	        "call to boost::get<U>(const boost::variant<T...>*) will always return NULL"
236  	    );
237  	
238  	    return relaxed_get<U>(operand);
239  	}
240  	
241  	template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
242  	inline
243  	    typename add_reference<U>::type
244  	strict_get(
245  	      boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
246  	      BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
247  	    )
248  	{
249  	    BOOST_STATIC_ASSERT_MSG(
250  	        (boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
251  	        "boost::variant does not contain specified type U, "
252  	        "call to boost::get<U>(boost::variant<T...>&) will always throw boost::bad_get exception"
253  	    );
254  	
255  	    return relaxed_get<U>(operand);
256  	}
257  	
258  	template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
259  	inline
260  	    typename add_reference<const U>::type
261  	strict_get(
262  	      const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
263  	      BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
264  	    )
265  	{
266  	    BOOST_STATIC_ASSERT_MSG(
267  	        (boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, const U >::value),
268  	        "boost::variant does not contain specified type U, "
269  	        "call to boost::get<U>(const boost::variant<T...>&) will always throw boost::bad_get exception"
270  	    );
271  	
(1) Event fun_call_w_exception: Called function throws an exception of type "boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::bad_get> >". [details]
272  	    return relaxed_get<U>(operand);
273  	}
274  	
275  	#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
276  	template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
277  	inline
278  	    U&&
279  	strict_get(
280  	      boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >&& operand
281  	      BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
282  	    )
283  	{
284  	    BOOST_STATIC_ASSERT_MSG(
285  	        (!boost::is_lvalue_reference<U>::value),
286  	        "remove ampersand '&' from template type U in boost::get<U>(boost::variant<T...>&&) "
287  	    );
288  	
289  	    BOOST_STATIC_ASSERT_MSG(
290  	        (boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
291  	        "boost::variant does not contain specified type U, "
292  	        "call to boost::get<U>(const boost::variant<T...>&) will always throw boost::bad_get exception"
293  	    );
294  	
295  	    return relaxed_get<U>(detail::variant::move(operand));
296  	}
297  	#endif
298  	
299  	/////////////////////////////////////////////////////////////////////////////////////////////////////////////
300  	// get<U>(variant) methods
301  	//
302  	
303  	template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
304  	inline
305  	    typename add_pointer<U>::type
306  	get(
307  	      boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
308  	      BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
309  	    ) BOOST_NOEXCEPT
310  	{
311  	#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
312  	    return relaxed_get<U>(operand);
313  	#else
314  	    return strict_get<U>(operand);
315  	#endif
316  	
317  	}
318  	
319  	template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
320  	inline
321  	    typename add_pointer<const U>::type
322  	get(
323  	      const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
324  	      BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
325  	    ) BOOST_NOEXCEPT
326  	{
327  	#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
328  	    return relaxed_get<U>(operand);
329  	#else
330  	    return strict_get<U>(operand);
331  	#endif
332  	}
333  	
334  	template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
335  	inline
336  	    typename add_reference<U>::type
337  	get(
338  	      boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
339  	      BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
340  	    )
341  	{
342  	#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
343  	    return relaxed_get<U>(operand);
344  	#else
345  	    return strict_get<U>(operand);
346  	#endif
347  	}
348  	
349  	template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
350  	inline
351  	    typename add_reference<const U>::type
352  	get(
353  	      const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
354  	      BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
355  	    )
356  	{
357  	#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
358  	    return relaxed_get<U>(operand);
359  	#else
(1) Event fun_call_w_exception: Called function throws an exception of type "boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::bad_get> >". [details]
360  	    return strict_get<U>(operand);
361  	#endif
362  	}
363  	
364  	#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
365  	template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
366  	inline
367  	    U&&
368  	get(
369  	      boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >&& operand
370  	      BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
371  	    )
372  	{
373  	#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
374  	    return relaxed_get<U>(detail::variant::move(operand));
375  	#else
376  	    return strict_get<U>(detail::variant::move(operand));
377  	#endif
378  	}
379  	#endif
380  	
381  	} // namespace boost
382  	
383  	#endif // BOOST_VARIANT_GET_HPP
384