Chris@16
|
1 //-----------------------------------------------------------------------------
|
Chris@16
|
2 // boost variant/get.hpp header file
|
Chris@16
|
3 // See http://www.boost.org for updates, documentation, and revision history.
|
Chris@16
|
4 //-----------------------------------------------------------------------------
|
Chris@16
|
5 //
|
Chris@16
|
6 // Copyright (c) 2003
|
Chris@16
|
7 // Eric Friedman, Itay Maman
|
Chris@16
|
8 //
|
Chris@16
|
9 // Distributed under the Boost Software License, Version 1.0. (See
|
Chris@16
|
10 // accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
11 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
12
|
Chris@16
|
13 #ifndef BOOST_VARIANT_GET_HPP
|
Chris@16
|
14 #define BOOST_VARIANT_GET_HPP
|
Chris@16
|
15
|
Chris@16
|
16 #include <exception>
|
Chris@16
|
17
|
Chris@16
|
18 #include "boost/config.hpp"
|
Chris@16
|
19 #include "boost/detail/workaround.hpp"
|
Chris@16
|
20 #include "boost/throw_exception.hpp"
|
Chris@16
|
21 #include "boost/utility/addressof.hpp"
|
Chris@16
|
22 #include "boost/variant/variant_fwd.hpp"
|
Chris@16
|
23
|
Chris@16
|
24 #include "boost/type_traits/add_reference.hpp"
|
Chris@16
|
25 #include "boost/type_traits/add_pointer.hpp"
|
Chris@16
|
26
|
Chris@16
|
27 #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
Chris@16
|
28 # include "boost/mpl/bool.hpp"
|
Chris@16
|
29 # include "boost/mpl/or.hpp"
|
Chris@16
|
30 # include "boost/type_traits/is_same.hpp"
|
Chris@16
|
31 #endif
|
Chris@16
|
32
|
Chris@16
|
33 namespace boost {
|
Chris@16
|
34
|
Chris@16
|
35 //////////////////////////////////////////////////////////////////////////
|
Chris@16
|
36 // class bad_get
|
Chris@16
|
37 //
|
Chris@16
|
38 // The exception thrown in the event of a failed get of a value.
|
Chris@16
|
39 //
|
Chris@16
|
40 class bad_get
|
Chris@16
|
41 : public std::exception
|
Chris@16
|
42 {
|
Chris@16
|
43 public: // std::exception implementation
|
Chris@16
|
44
|
Chris@16
|
45 virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW
|
Chris@16
|
46 {
|
Chris@16
|
47 return "boost::bad_get: "
|
Chris@16
|
48 "failed value get using boost::get";
|
Chris@16
|
49 }
|
Chris@16
|
50
|
Chris@16
|
51 };
|
Chris@16
|
52
|
Chris@16
|
53 //////////////////////////////////////////////////////////////////////////
|
Chris@16
|
54 // function template get<T>
|
Chris@16
|
55 //
|
Chris@16
|
56 // Retrieves content of given variant object if content is of type T.
|
Chris@16
|
57 // Otherwise: pointer ver. returns 0; reference ver. throws bad_get.
|
Chris@16
|
58 //
|
Chris@16
|
59
|
Chris@16
|
60 namespace detail { namespace variant {
|
Chris@16
|
61
|
Chris@16
|
62 // (detail) class template get_visitor
|
Chris@16
|
63 //
|
Chris@16
|
64 // Generic static visitor that: if the value is of the specified type,
|
Chris@16
|
65 // returns a pointer to the value it visits; else a null pointer.
|
Chris@16
|
66 //
|
Chris@16
|
67 template <typename T>
|
Chris@16
|
68 struct get_visitor
|
Chris@16
|
69 {
|
Chris@16
|
70 private: // private typedefs
|
Chris@16
|
71
|
Chris@16
|
72 typedef typename add_pointer<T>::type pointer;
|
Chris@16
|
73 typedef typename add_reference<T>::type reference;
|
Chris@16
|
74
|
Chris@16
|
75 public: // visitor typedefs
|
Chris@16
|
76
|
Chris@16
|
77 typedef pointer result_type;
|
Chris@16
|
78
|
Chris@16
|
79 public: // visitor interfaces
|
Chris@16
|
80
|
Chris@16
|
81 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
Chris@16
|
82
|
Chris@16
|
83 pointer operator()(reference operand) const
|
Chris@16
|
84 {
|
Chris@16
|
85 return boost::addressof(operand);
|
Chris@16
|
86 }
|
Chris@16
|
87
|
Chris@16
|
88 template <typename U>
|
Chris@16
|
89 pointer operator()(const U&) const
|
Chris@16
|
90 {
|
Chris@16
|
91 return static_cast<pointer>(0);
|
Chris@16
|
92 }
|
Chris@16
|
93
|
Chris@16
|
94 #else // MSVC6
|
Chris@16
|
95
|
Chris@16
|
96 private: // helpers, for visitor interfaces (below)
|
Chris@16
|
97
|
Chris@16
|
98 pointer execute_impl(reference operand, mpl::true_) const
|
Chris@16
|
99 {
|
Chris@16
|
100 return boost::addressof(operand);
|
Chris@16
|
101 }
|
Chris@16
|
102
|
Chris@16
|
103 template <typename U>
|
Chris@16
|
104 pointer execute_impl(const U& operand, mpl::false_) const
|
Chris@16
|
105 {
|
Chris@16
|
106 return static_cast<pointer>(0);
|
Chris@16
|
107 }
|
Chris@16
|
108
|
Chris@16
|
109 public: // visitor interfaces
|
Chris@16
|
110
|
Chris@16
|
111 template <typename U>
|
Chris@16
|
112 pointer operator()(U& operand) const
|
Chris@16
|
113 {
|
Chris@16
|
114 // MSVC6 finds normal implementation (above) ambiguous,
|
Chris@16
|
115 // so we must explicitly disambiguate
|
Chris@16
|
116
|
Chris@16
|
117 typedef typename mpl::or_<
|
Chris@16
|
118 is_same<U, T>
|
Chris@16
|
119 , is_same<const U, T>
|
Chris@16
|
120 >::type U_is_T;
|
Chris@16
|
121
|
Chris@16
|
122 return execute_impl(operand, U_is_T());
|
Chris@16
|
123 }
|
Chris@16
|
124
|
Chris@16
|
125 #endif // MSVC6 workaround
|
Chris@16
|
126
|
Chris@16
|
127 };
|
Chris@16
|
128
|
Chris@16
|
129 }} // namespace detail::variant
|
Chris@16
|
130
|
Chris@16
|
131 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551))
|
Chris@16
|
132 # define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t) \
|
Chris@16
|
133 BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(t)
|
Chris@16
|
134 #else
|
Chris@16
|
135 # define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t) \
|
Chris@16
|
136 , t* = 0
|
Chris@16
|
137 #endif
|
Chris@16
|
138
|
Chris@16
|
139 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
|
Chris@16
|
140 inline
|
Chris@16
|
141 typename add_pointer<U>::type
|
Chris@16
|
142 get(
|
Chris@16
|
143 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
|
Chris@16
|
144 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
|
Chris@16
|
145 )
|
Chris@16
|
146 {
|
Chris@16
|
147 typedef typename add_pointer<U>::type U_ptr;
|
Chris@16
|
148 if (!operand) return static_cast<U_ptr>(0);
|
Chris@16
|
149
|
Chris@16
|
150 detail::variant::get_visitor<U> v;
|
Chris@16
|
151 return operand->apply_visitor(v);
|
Chris@16
|
152 }
|
Chris@16
|
153
|
Chris@16
|
154 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
|
Chris@16
|
155 inline
|
Chris@16
|
156 typename add_pointer<const U>::type
|
Chris@16
|
157 get(
|
Chris@16
|
158 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
|
Chris@16
|
159 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
|
Chris@16
|
160 )
|
Chris@16
|
161 {
|
Chris@16
|
162 typedef typename add_pointer<const U>::type U_ptr;
|
Chris@16
|
163 if (!operand) return static_cast<U_ptr>(0);
|
Chris@16
|
164
|
Chris@16
|
165 detail::variant::get_visitor<const U> v;
|
Chris@16
|
166 return operand->apply_visitor(v);
|
Chris@16
|
167 }
|
Chris@16
|
168
|
Chris@16
|
169 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
|
Chris@16
|
170 inline
|
Chris@16
|
171 typename add_reference<U>::type
|
Chris@16
|
172 get(
|
Chris@16
|
173 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
|
Chris@16
|
174 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
|
Chris@16
|
175 )
|
Chris@16
|
176 {
|
Chris@16
|
177 typedef typename add_pointer<U>::type U_ptr;
|
Chris@16
|
178 U_ptr result = get<U>(&operand);
|
Chris@16
|
179
|
Chris@16
|
180 if (!result)
|
Chris@16
|
181 boost::throw_exception(bad_get());
|
Chris@16
|
182 return *result;
|
Chris@16
|
183 }
|
Chris@16
|
184
|
Chris@16
|
185 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
|
Chris@16
|
186 inline
|
Chris@16
|
187 typename add_reference<const U>::type
|
Chris@16
|
188 get(
|
Chris@16
|
189 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
|
Chris@16
|
190 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
|
Chris@16
|
191 )
|
Chris@16
|
192 {
|
Chris@16
|
193 typedef typename add_pointer<const U>::type U_ptr;
|
Chris@16
|
194 U_ptr result = get<const U>(&operand);
|
Chris@16
|
195
|
Chris@16
|
196 if (!result)
|
Chris@16
|
197 boost::throw_exception(bad_get());
|
Chris@16
|
198 return *result;
|
Chris@16
|
199 }
|
Chris@16
|
200
|
Chris@16
|
201 } // namespace boost
|
Chris@16
|
202
|
Chris@16
|
203 #endif // BOOST_VARIANT_GET_HPP
|