]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/variant/polymorphic_get.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / variant / polymorphic_get.hpp
1 //-----------------------------------------------------------------------------
2 // boost variant/polymorphic_get.hpp header file
3 // See http://www.boost.org for updates, documentation, and revision history.
4 //-----------------------------------------------------------------------------
5 //
6 // Copyright (c) 2013-2019 Antony Polukhin
7 //
8 // Distributed under the Boost Software License, Version 1.0. (See
9 // accompanying file LICENSE_1_0.txt or copy at
10 // http://www.boost.org/LICENSE_1_0.txt)
11
12 #ifndef BOOST_VARIANT_POLYMORPHIC_GET_HPP
13 #define BOOST_VARIANT_POLYMORPHIC_GET_HPP
14
15 #include <exception>
16
17 #include <boost/config.hpp>
18 #include <boost/detail/workaround.hpp>
19 #include <boost/static_assert.hpp>
20 #include <boost/throw_exception.hpp>
21 #include <boost/utility/addressof.hpp>
22 #include <boost/variant/variant_fwd.hpp>
23 #include <boost/variant/get.hpp>
24
25 #include <boost/type_traits/add_reference.hpp>
26 #include <boost/type_traits/add_pointer.hpp>
27 #include <boost/type_traits/is_base_of.hpp>
28 #include <boost/type_traits/is_const.hpp>
29
30 namespace boost {
31
32 //////////////////////////////////////////////////////////////////////////
33 // class bad_polymorphic_get
34 //
35 // The exception thrown in the event of a failed get of a value.
36 //
37 class BOOST_SYMBOL_VISIBLE bad_polymorphic_get
38 : public bad_get
39 {
40 public: // std::exception implementation
41
42 virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW
43 {
44 return "boost::bad_polymorphic_get: "
45 "failed value get using boost::polymorphic_get";
46 }
47
48 };
49
50 //////////////////////////////////////////////////////////////////////////
51 // function template get<T>
52 //
53 // Retrieves content of given variant object if content is of type T.
54 // Otherwise: pointer ver. returns 0; reference ver. throws bad_get.
55 //
56
57 namespace detail { namespace variant {
58
59
60 ///////////////////////////////////////////////////////////////////////////////////////////////////
61 // polymorphic metafunctions to detect index of a value
62 //
63
64 template <class Types, class T>
65 struct element_polymorphic_iterator_impl :
66 boost::mpl::find_if<
67 Types,
68 boost::mpl::or_<
69 variant_element_functor<boost::mpl::_1, T>,
70 variant_element_functor<boost::mpl::_1, typename boost::remove_cv<T>::type >,
71 boost::is_base_of<T, boost::mpl::_1>
72 >
73 >
74 {};
75
76 template <class Variant, class T>
77 struct holds_element_polymorphic :
78 boost::mpl::not_<
79 boost::is_same<
80 typename boost::mpl::end<typename Variant::types>::type,
81 typename element_polymorphic_iterator_impl<typename Variant::types, typename boost::remove_reference<T>::type >::type
82 >
83 >
84 {};
85
86 // (detail) class template get_polymorphic_visitor
87 //
88 // Generic static visitor that: if the value is of the specified
89 // type or of a type derived from specified, returns a pointer
90 // to the value it visits; else a null pointer.
91 //
92 template <typename Base>
93 struct get_polymorphic_visitor
94 {
95 private: // private typedefs
96 typedef get_polymorphic_visitor<Base> this_type;
97 typedef typename add_pointer<Base>::type pointer;
98 typedef typename add_reference<Base>::type reference;
99
100 pointer get(reference operand, boost::true_type) const BOOST_NOEXCEPT
101 {
102 return boost::addressof(operand);
103 }
104
105 template <class T>
106 pointer get(T&, boost::false_type) const BOOST_NOEXCEPT
107 {
108 return static_cast<pointer>(0);
109 }
110
111 public: // visitor interfaces
112 typedef pointer result_type;
113
114 template <typename U>
115 pointer operator()(U& operand) const BOOST_NOEXCEPT
116 {
117 typedef typename boost::remove_reference<Base>::type base_t;
118 typedef boost::integral_constant<
119 bool,
120 (
121 boost::is_base_of<base_t, U>::value &&
122 (boost::is_const<base_t>::value || !boost::is_const<U>::value)
123 )
124 || boost::is_same<base_t, U>::value
125 || boost::is_same<typename boost::remove_cv<base_t>::type, U >::value
126 > tag_t;
127
128 return this_type::get(operand, tag_t());
129 }
130 };
131
132 }} // namespace detail::variant
133
134 #ifndef BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE
135 # if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551))
136 # define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t)
137 # else
138 # define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t) \
139 , t* = 0
140 # endif
141 #endif
142
143 //////////////////////////////////////////////////////////////////////////////////////////////////////////
144 // polymorphic_relaxed_get
145 //
146
147 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
148 inline
149 typename add_pointer<U>::type
150 polymorphic_relaxed_get(
151 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
152 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
153 ) BOOST_NOEXCEPT
154 {
155 typedef typename add_pointer<U>::type U_ptr;
156 if (!operand) return static_cast<U_ptr>(0);
157
158 detail::variant::get_polymorphic_visitor<U> v;
159 return operand->apply_visitor(v);
160 }
161
162 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
163 inline
164 typename add_pointer<const U>::type
165 polymorphic_relaxed_get(
166 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
167 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
168 ) BOOST_NOEXCEPT
169 {
170 typedef typename add_pointer<const U>::type U_ptr;
171 if (!operand) return static_cast<U_ptr>(0);
172
173 detail::variant::get_polymorphic_visitor<const U> v;
174 return operand->apply_visitor(v);
175 }
176
177 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
178 inline
179 typename add_reference<U>::type
180 polymorphic_relaxed_get(
181 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
182 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
183 )
184 {
185 typedef typename add_pointer<U>::type U_ptr;
186 U_ptr result = polymorphic_relaxed_get<U>(&operand);
187
188 if (!result)
189 boost::throw_exception(bad_polymorphic_get());
190 return *result;
191 }
192
193 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
194 inline
195 typename add_reference<const U>::type
196 polymorphic_relaxed_get(
197 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
198 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
199 )
200 {
201 typedef typename add_pointer<const U>::type U_ptr;
202 U_ptr result = polymorphic_relaxed_get<const U>(&operand);
203
204 if (!result)
205 boost::throw_exception(bad_polymorphic_get());
206 return *result;
207 }
208
209 //////////////////////////////////////////////////////////////////////////////////////////////////////////
210 // polymorphic_strict_get
211 //
212
213 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
214 inline
215 typename add_pointer<U>::type
216 polymorphic_strict_get(
217 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
218 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
219 ) BOOST_NOEXCEPT
220 {
221 BOOST_STATIC_ASSERT_MSG(
222 (boost::detail::variant::holds_element_polymorphic<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
223 "boost::variant does not contain specified type U, "
224 "call to boost::polymorphic_get<U>(boost::variant<T...>*) will always return NULL"
225 );
226
227 return polymorphic_relaxed_get<U>(operand);
228 }
229
230 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
231 inline
232 typename add_pointer<const U>::type
233 polymorphic_strict_get(
234 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
235 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
236 ) BOOST_NOEXCEPT
237 {
238 BOOST_STATIC_ASSERT_MSG(
239 (boost::detail::variant::holds_element_polymorphic<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
240 "boost::variant does not contain specified type U, "
241 "call to boost::polymorphic_get<U>(const boost::variant<T...>*) will always return NULL"
242 );
243
244 return polymorphic_relaxed_get<U>(operand);
245 }
246
247 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
248 inline
249 typename add_reference<U>::type
250 polymorphic_strict_get(
251 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
252 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
253 )
254 {
255 BOOST_STATIC_ASSERT_MSG(
256 (boost::detail::variant::holds_element_polymorphic<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
257 "boost::variant does not contain specified type U, "
258 "call to boost::polymorphic_get<U>(boost::variant<T...>&) will always throw boost::bad_polymorphic_get exception"
259 );
260
261 return polymorphic_relaxed_get<U>(operand);
262 }
263
264 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
265 inline
266 typename add_reference<const U>::type
267 polymorphic_strict_get(
268 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
269 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
270 )
271 {
272 BOOST_STATIC_ASSERT_MSG(
273 (boost::detail::variant::holds_element_polymorphic<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
274 "boost::variant does not contain specified type U, "
275 "call to boost::polymorphic_get<U>(const boost::variant<T...>&) will always throw boost::bad_polymorphic_get exception"
276 );
277
278 return polymorphic_relaxed_get<U>(operand);
279 }
280
281 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
282 // polymorphic_get<U>(variant) methods
283 //
284
285 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
286 inline
287 typename add_pointer<U>::type
288 polymorphic_get(
289 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
290 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
291 ) BOOST_NOEXCEPT
292 {
293 #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
294 return polymorphic_relaxed_get<U>(operand);
295 #else
296 return polymorphic_strict_get<U>(operand);
297 #endif
298
299 }
300
301 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
302 inline
303 typename add_pointer<const U>::type
304 polymorphic_get(
305 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
306 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
307 ) BOOST_NOEXCEPT
308 {
309 #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
310 return polymorphic_relaxed_get<U>(operand);
311 #else
312 return polymorphic_strict_get<U>(operand);
313 #endif
314 }
315
316 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
317 inline
318 typename add_reference<U>::type
319 polymorphic_get(
320 boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
321 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
322 )
323 {
324 #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
325 return polymorphic_relaxed_get<U>(operand);
326 #else
327 return polymorphic_strict_get<U>(operand);
328 #endif
329 }
330
331 template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
332 inline
333 typename add_reference<const U>::type
334 polymorphic_get(
335 const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
336 BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
337 )
338 {
339 #ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
340 return polymorphic_relaxed_get<U>(operand);
341 #else
342 return polymorphic_strict_get<U>(operand);
343 #endif
344 }
345 } // namespace boost
346
347 #endif // BOOST_VARIANT_POLYMORPHIC_GET_HPP